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/act/create.ts | 4 +- src/remote/activitypub/act/index.ts | 6 +- src/remote/activitypub/create.ts | 147 ++++++++++++++++++------------- src/remote/activitypub/resolve-person.ts | 6 +- 4 files changed, 96 insertions(+), 67 deletions(-) (limited to 'src/remote/activitypub') diff --git a/src/remote/activitypub/act/create.ts b/src/remote/activitypub/act/create.ts index 9eb74800ea..a6ba9a1d2b 100644 --- a/src/remote/activitypub/act/create.ts +++ b/src/remote/activitypub/act/create.ts @@ -1,9 +1,9 @@ import create from '../create'; -export default (resolver, actor, activity) => { +export default (resolver, actor, activity, distribute) => { if ('actor' in activity && actor.account.uri !== activity.actor) { throw new Error(); } - return create(resolver, actor, activity.object); + return create(resolver, actor, activity.object, distribute); }; diff --git a/src/remote/activitypub/act/index.ts b/src/remote/activitypub/act/index.ts index a76983638f..06d662c191 100644 --- a/src/remote/activitypub/act/index.ts +++ b/src/remote/activitypub/act/index.ts @@ -2,10 +2,10 @@ import create from './create'; import createObject from '../create'; import Resolver from '../resolver'; -export default (actor, value) => { +export default (actor, value, distribute) => { return new Resolver().resolve(value).then(resolved => Promise.all(resolved.map(async promisedResult => { const { resolver, object } = await promisedResult; - const created = await (await createObject(resolver, actor, [object]))[0]; + const created = await (await createObject(resolver, actor, [object], distribute))[0]; if (created !== null) { return created; @@ -13,7 +13,7 @@ export default (actor, value) => { switch (object.type) { case 'Create': - return create(resolver, actor, object); + return create(resolver, actor, object, distribute); default: return null; 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); +}; diff --git a/src/remote/activitypub/resolve-person.ts b/src/remote/activitypub/resolve-person.ts index d928e7ce19..4a2636b2f7 100644 --- a/src/remote/activitypub/resolve-person.ts +++ b/src/remote/activitypub/resolve-person.ts @@ -52,10 +52,10 @@ export default async (value, usernameLower, hostLower, acctLower) => { bannerId: null, createdAt: Date.parse(object.published), description: summaryDOM.textContent, - followersCount: followers.totalItem, - followingCount: following.totalItem, + followersCount: followers ? followers.totalItem || 0 : 0, + followingCount: following ? following.totalItem || 0 : 0, name: object.name, - postsCount: outbox.totalItem, + postsCount: outbox ? outbox.totalItem || 0 : 0, driveCapacity: 1024 * 1024 * 8, // 8MiB username: object.preferredUsername, usernameLower, -- cgit v1.2.3-freya