From b9f5fca3333283cda2ccbd7843f7496dd9eae574 Mon Sep 17 00:00:00 2001 From: MeiMei <30769358+mei23@users.noreply.github.com> Date: Sun, 7 Oct 2018 20:20:55 +0900 Subject: [PATCH] =?UTF-8?q?ActivityPub=E3=82=AA=E3=83=96=E3=82=B8=E3=82=A7?= =?UTF-8?q?=E3=82=AF=E3=83=88=E6=8E=A1=E7=95=AAAPI=20(#2832)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Show ActivityPub object API * Add missing return --- src/server/api/endpoints/ap/show.ts | 116 ++++++++++++++++++++++++++++ 1 file changed, 116 insertions(+) create mode 100644 src/server/api/endpoints/ap/show.ts diff --git a/src/server/api/endpoints/ap/show.ts b/src/server/api/endpoints/ap/show.ts new file mode 100644 index 000000000..1f390d01a --- /dev/null +++ b/src/server/api/endpoints/ap/show.ts @@ -0,0 +1,116 @@ +import $ from 'cafy'; +import getParams from '../../get-params'; +import config from '../../../../config'; +import * as mongo from 'mongodb'; +import User, { pack as packUser, IUser } from '../../../../models/user'; +import { createPerson } from '../../../../remote/activitypub/models/person'; +import Note, { pack as packNote, INote } from '../../../../models/note'; +import { createNote } from '../../../../remote/activitypub/models/note'; +import Resolver from '../../../../remote/activitypub/resolver'; + +export const meta = { + desc: { + 'ja-JP': 'URIを指定してActivityPubオブジェクトを参照します。' + }, + + requireCredential: false, + + params: { + uri: $.str.note({ + desc: { + 'ja-JP': 'ActivityPubオブジェクトのURI' + } + }), + }, +}; + +export default (params: any) => new Promise(async (res, rej) => { + const [ps, psErr] = getParams(meta, params); + if (psErr) return rej(psErr); + + const object = await fetchAny(ps.uri); + if (object !== null) return res(object); + + return rej('object not found'); +}); + +/*** + * URIからUserかNoteを解決する + */ +async function fetchAny(uri: string) { + // URIがこのサーバーを指しているなら、ローカルユーザーIDとしてDBからフェッチ + if (uri.startsWith(config.url + '/')) { + const id = new mongo.ObjectID(uri.split('/').pop()); + const [ user, note ] = await Promise.all([ + User.findOne({ _id: id }), + Note.findOne({ _id: id }) + ]); + + const packed = await mergePack(user, note); + if (packed !== null) return packed; + } + + // URI(AP Object id)としてDB検索 + { + const [ user, note ] = await Promise.all([ + User.findOne({ uri: uri }), + Note.findOne({ uri: uri }) + ]); + + const packed = await mergePack(user, note); + if (packed !== null) return packed; + } + + // リモートから一旦オブジェクトフェッチ + const resolver = new Resolver(); + const object = await resolver.resolve(uri) as any; + + // /@user のような正規id以外で取得できるURIが指定されていた場合、ここで初めて正規URIが確定する + // これはDBに存在する可能性があるため再度DB検索 + if (uri !== object.id) { + const [ user, note ] = await Promise.all([ + User.findOne({ uri: object.id }), + Note.findOne({ uri: object.id }) + ]); + + const packed = await mergePack(user, note); + if (packed !== null) return packed; + } + + // それでもみつからなければ新規であるため登録 + if (object.type === 'Person') { + const user = await createPerson(object.id); + return { + type: 'User', + object: user + }; + } + + if (object.type === 'Note') { + const note = await createNote(object.id); + return { + type: 'Note', + object: note + }; + } + + return null; +} + +async function mergePack(user: IUser, note: INote) { + if (user !== null) { + return { + type: 'User', + object: await packUser(user, null, { detail: true }) + }; + } + + if (note !== null) { + return { + type: 'Note', + object: await packNote(note, null, { detail: true }) + }; + } + + return null; +}