From ce7efc4dbb9dca05b6b99b5ada22205890ca823f Mon Sep 17 00:00:00 2001 From: Akihiko Odaki Date: Mon, 2 Apr 2018 17:11:14 +0900 Subject: Distribute posts from remote --- src/remote/activitypub/create.ts | 147 +++++++++++++++++++++++---------------- 1 file changed, 88 insertions(+), 59 deletions(-) (limited to 'src/remote/activitypub/create.ts') diff --git a/src/remote/activitypub/create.ts b/src/remote/activitypub/create.ts index 8ea8a85fd8..dd3f7b0227 100644 --- a/src/remote/activitypub/create.ts +++ b/src/remote/activitypub/create.ts @@ -1,8 +1,11 @@ import { JSDOM } from 'jsdom'; import config from '../../config'; -import Post from '../../models/post'; +import { pack as packPost } from '../../models/post'; import RemoteUserObject, { IRemoteUserObject } from '../../models/remote-user-object'; +import { IRemoteUser } from '../../models/user'; import uploadFromUrl from '../../drive/upload-from-url'; +import createPost from '../../post/create'; +import distributePost from '../../post/distribute'; import Resolver from './resolver'; const createDOMPurify = require('dompurify'); @@ -16,72 +19,98 @@ function createRemoteUserObject($ref, $id, { id }) { return RemoteUserObject.insert({ uri: id, object }); } -async function createImage(actor, object) { - if ('attributedTo' in object && actor.account.uri !== object.attributedTo) { - throw new Error(); +class Creator { + private actor: IRemoteUser; + private distribute: boolean; + + constructor(actor, distribute) { + this.actor = actor; + this.distribute = distribute; } - const { _id } = await uploadFromUrl(object.url, actor); - return createRemoteUserObject('driveFiles.files', _id, object); -} + private async createImage(object) { + if ('attributedTo' in object && this.actor.account.uri !== object.attributedTo) { + throw new Error(); + } -async function createNote(resolver, actor, object) { - if ('attributedTo' in object && actor.account.uri !== object.attributedTo) { - throw new Error(); + const { _id } = await uploadFromUrl(object.url, this.actor); + return createRemoteUserObject('driveFiles.files', _id, object); } - const mediaIds = 'attachment' in object && - (await Promise.all(await create(resolver, actor, object.attachment))) - .filter(media => media !== null && media.object.$ref === 'driveFiles.files') - .map(({ object }) => object.$id); - - const { window } = new JSDOM(object.content); - - const { _id } = await Post.insert({ - channelId: undefined, - index: undefined, - createdAt: new Date(object.published), - mediaIds, - replyId: undefined, - repostId: undefined, - poll: undefined, - text: window.document.body.textContent, - textHtml: object.content && createDOMPurify(window).sanitize(object.content), - userId: actor._id, - appId: null, - viaMobile: false, - geo: undefined - }); - - // Register to search database - if (object.content && config.elasticsearch.enable) { - const es = require('../../db/elasticsearch'); - - es.index({ - index: 'misskey', - type: 'post', - id: _id.toString(), - body: { - text: window.document.body.textContent - } - }); - } + private async createNote(resolver, object) { + if ('attributedTo' in object && this.actor.account.uri !== object.attributedTo) { + throw new Error(); + } - return createRemoteUserObject('posts', _id, object); -} + const mediaIds = 'attachment' in object && + (await Promise.all(await this.create(resolver, object.attachment))) + .filter(media => media !== null && media.object.$ref === 'driveFiles.files') + .map(({ object }) => object.$id); + + const { window } = new JSDOM(object.content); + + const inserted = await createPost({ + channelId: undefined, + index: undefined, + createdAt: new Date(object.published), + mediaIds, + replyId: undefined, + repostId: undefined, + poll: undefined, + text: window.document.body.textContent, + textHtml: object.content && createDOMPurify(window).sanitize(object.content), + userId: this.actor._id, + appId: null, + viaMobile: false, + geo: undefined + }, null, null, []); + + const promisedRemoteUserObject = createRemoteUserObject('posts', inserted._id, object); + const promises = []; + + if (this.distribute) { + promises.push(distributePost(this.actor, inserted.mentions, packPost(inserted))); + } -export default async function create(parentResolver: Resolver, actor, value): Promise>> { - const results = await parentResolver.resolveRemoteUserObjects(value); + // Register to search database + if (object.content && config.elasticsearch.enable) { + const es = require('../../db/elasticsearch'); + + promises.push(new Promise((resolve, reject) => { + es.index({ + index: 'misskey', + type: 'post', + id: inserted._id.toString(), + body: { + text: window.document.body.textContent + } + }, resolve); + })); + } - return results.map(promisedResult => promisedResult.then(({ resolver, object }) => { - switch (object.type) { - case 'Image': - return createImage(actor, object); + await Promise.all(promises); - case 'Note': - return createNote(resolver, actor, object); - } + return promisedRemoteUserObject; + } + + public async create(parentResolver, value): Promise>> { + const results = await parentResolver.resolveRemoteUserObjects(value); + + return results.map(promisedResult => promisedResult.then(({ resolver, object }) => { + switch (object.type) { + case 'Image': + return this.createImage(object); - return null; - })); + case 'Note': + return this.createNote(resolver, object); + } + + return null; + })); + } } + +export default (resolver: Resolver, actor, value, distribute?: boolean) => { + const creator = new Creator(actor, distribute); + return creator.create(resolver, value); +}; -- cgit v1.2.3-freya