diff options
| author | syuilo <Syuilotan@yahoo.co.jp> | 2018-04-07 16:26:50 +0900 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2018-04-07 16:26:50 +0900 |
| commit | 2547891f940a2872fcfb2b33cd33d4f7a42ca7bc (patch) | |
| tree | 5cba4ae9cdfd63e7e1ef74a002a7b742183e8d3c /src/remote/activitypub/act/create | |
| parent | Merge pull request #1410 from akihikodaki/objec (diff) | |
| parent | Refactor (diff) | |
| download | misskey-2547891f940a2872fcfb2b33cd33d4f7a42ca7bc.tar.gz misskey-2547891f940a2872fcfb2b33cd33d4f7a42ca7bc.tar.bz2 misskey-2547891f940a2872fcfb2b33cd33d4f7a42ca7bc.zip | |
Merge pull request #1397 from syuilo/refactor
Refactor
Diffstat (limited to 'src/remote/activitypub/act/create')
| -rw-r--r-- | src/remote/activitypub/act/create/image.ts | 18 | ||||
| -rw-r--r-- | src/remote/activitypub/act/create/index.ts | 44 | ||||
| -rw-r--r-- | src/remote/activitypub/act/create/note.ts | 89 |
3 files changed, 151 insertions, 0 deletions
diff --git a/src/remote/activitypub/act/create/image.ts b/src/remote/activitypub/act/create/image.ts new file mode 100644 index 0000000000..30a75e7377 --- /dev/null +++ b/src/remote/activitypub/act/create/image.ts @@ -0,0 +1,18 @@ +import * as debug from 'debug'; + +import uploadFromUrl from '../../../../services/drive/upload-from-url'; +import { IRemoteUser } from '../../../../models/user'; +import { IDriveFile } from '../../../../models/drive-file'; + +const log = debug('misskey:activitypub'); + +export default async function(actor: IRemoteUser, image): Promise<IDriveFile> { + if ('attributedTo' in image && actor.account.uri !== image.attributedTo) { + log(`invalid image: ${JSON.stringify(image, null, 2)}`); + throw new Error('invalid image'); + } + + log(`Creating the Image: ${image.id}`); + + return await uploadFromUrl(image.url, actor); +} diff --git a/src/remote/activitypub/act/create/index.ts b/src/remote/activitypub/act/create/index.ts new file mode 100644 index 0000000000..dd0b112141 --- /dev/null +++ b/src/remote/activitypub/act/create/index.ts @@ -0,0 +1,44 @@ +import * as debug from 'debug'; + +import Resolver from '../../resolver'; +import { IRemoteUser } from '../../../../models/user'; +import createNote from './note'; +import createImage from './image'; +import { ICreate } from '../../type'; + +const log = debug('misskey:activitypub'); + +export default async (actor: IRemoteUser, activity: ICreate): Promise<void> => { + if ('actor' in activity && actor.account.uri !== activity.actor) { + throw new Error('invalid actor'); + } + + const uri = activity.id || activity; + + log(`Create: ${uri}`); + + const resolver = new Resolver(); + + let object; + + try { + object = await resolver.resolve(activity.object); + } catch (e) { + log(`Resolution failed: ${e}`); + throw e; + } + + switch (object.type) { + case 'Image': + createImage(actor, object); + break; + + case 'Note': + createNote(resolver, actor, object); + break; + + default: + console.warn(`Unknown type: ${object.type}`); + break; + } +}; diff --git a/src/remote/activitypub/act/create/note.ts b/src/remote/activitypub/act/create/note.ts new file mode 100644 index 0000000000..82a6207038 --- /dev/null +++ b/src/remote/activitypub/act/create/note.ts @@ -0,0 +1,89 @@ +import { JSDOM } from 'jsdom'; +import * as debug from 'debug'; + +import Resolver from '../../resolver'; +import Post, { IPost } from '../../../../models/post'; +import createPost from '../../../../services/post/create'; +import { IRemoteUser } from '../../../../models/user'; +import resolvePerson from '../../resolve-person'; +import createImage from './image'; +import config from '../../../../config'; + +const log = debug('misskey:activitypub'); + +/** + * 投稿作成アクティビティを捌きます + */ +export default async function createNote(resolver: Resolver, actor: IRemoteUser, note, silent = false): Promise<IPost> { + if (typeof note.id !== 'string') { + log(`invalid note: ${JSON.stringify(note, null, 2)}`); + throw new Error('invalid note'); + } + + // 既に同じURIを持つものが登録されていないかチェックし、登録されていたらそれを返す + const exist = await Post.findOne({ uri: note.id }); + if (exist) { + return exist; + } + + log(`Creating the Note: ${note.id}`); + + //#region Visibility + let visibility = 'public'; + if (!note.to.includes('https://www.w3.org/ns/activitystreams#Public')) visibility = 'unlisted'; + if (note.cc.length == 0) visibility = 'private'; + // TODO + if (visibility != 'public') throw new Error('unspported visibility'); + //#endergion + + //#region 添付メディア + const media = []; + if ('attachment' in note && note.attachment != null) { + // TODO: attachmentは必ずしもImageではない + // TODO: attachmentは必ずしも配列ではない + // TODO: ループの中でawaitはすべきでない + note.attachment.forEach(async media => { + const created = await createImage(note.actor, media); + media.push(created); + }); + } + //#endregion + + //#region リプライ + let reply = null; + if ('inReplyTo' in note && note.inReplyTo != null) { + // リプライ先の投稿がMisskeyに登録されているか調べる + const uri: string = note.inReplyTo.id || note.inReplyTo; + const inReplyToPost = uri.startsWith(config.url + '/') + ? await Post.findOne({ _id: uri.split('/').pop() }) + : await Post.findOne({ uri }); + + if (inReplyToPost) { + reply = inReplyToPost; + } else { + // 無かったらフェッチ + const inReplyTo = await resolver.resolve(note.inReplyTo) as any; + + // リプライ先の投稿の投稿者をフェッチ + const actor = await resolvePerson(inReplyTo.attributedTo) as IRemoteUser; + + // TODO: silentを常にtrueにしてはならない + reply = await createNote(resolver, actor, inReplyTo); + } + } + //#endregion + + const { window } = new JSDOM(note.content); + + return await createPost(actor, { + createdAt: new Date(note.published), + media, + reply, + repost: undefined, + text: window.document.body.textContent, + viaMobile: false, + geo: undefined, + visibility, + uri: note.id + }); +} |