From 93f631e3586e0674dc177789bebca8ddd946c153 Mon Sep 17 00:00:00 2001 From: syuilo Date: Sat, 7 Apr 2018 16:14:35 +0900 Subject: [PATCH] Refactor --- src/remote/activitypub/act/create/image.ts | 3 +-- src/remote/activitypub/act/create/index.ts | 5 ++-- src/remote/activitypub/act/create/note.ts | 2 +- src/remote/activitypub/act/follow.ts | 7 ++--- src/remote/activitypub/act/undo/follow.ts | 7 ++--- src/remote/activitypub/act/undo/index.ts | 30 +++++++++++++++++++--- src/remote/activitypub/act/unfollow.ts | 25 ------------------ src/remote/activitypub/type.ts | 22 +++++++++++++--- 8 files changed, 58 insertions(+), 43 deletions(-) delete mode 100644 src/remote/activitypub/act/unfollow.ts diff --git a/src/remote/activitypub/act/create/image.ts b/src/remote/activitypub/act/create/image.ts index cd9e7b4e0f..30a75e7377 100644 --- a/src/remote/activitypub/act/create/image.ts +++ b/src/remote/activitypub/act/create/image.ts @@ -1,13 +1,12 @@ import * as debug from 'debug'; -import Resolver from '../../resolver'; 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(resolver: Resolver, actor: IRemoteUser, image): Promise { +export default async function(actor: IRemoteUser, image): Promise { if ('attributedTo' in image && actor.account.uri !== image.attributedTo) { log(`invalid image: ${JSON.stringify(image, null, 2)}`); throw new Error('invalid image'); diff --git a/src/remote/activitypub/act/create/index.ts b/src/remote/activitypub/act/create/index.ts index 7ab4c2abaf..dd0b112141 100644 --- a/src/remote/activitypub/act/create/index.ts +++ b/src/remote/activitypub/act/create/index.ts @@ -4,10 +4,11 @@ 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): Promise => { +export default async (actor: IRemoteUser, activity: ICreate): Promise => { if ('actor' in activity && actor.account.uri !== activity.actor) { throw new Error('invalid actor'); } @@ -29,7 +30,7 @@ export default async (actor: IRemoteUser, activity): Promise => { switch (object.type) { case 'Image': - createImage(resolver, actor, object); + createImage(actor, object); break; case 'Note': diff --git a/src/remote/activitypub/act/create/note.ts b/src/remote/activitypub/act/create/note.ts index 364fddfe0b..82a6207038 100644 --- a/src/remote/activitypub/act/create/note.ts +++ b/src/remote/activitypub/act/create/note.ts @@ -43,7 +43,7 @@ export default async function createNote(resolver: Resolver, actor: IRemoteUser, // TODO: attachmentは必ずしも配列ではない // TODO: ループの中でawaitはすべきでない note.attachment.forEach(async media => { - const created = await createImage(resolver, note.actor, media); + const created = await createImage(note.actor, media); media.push(created); }); } diff --git a/src/remote/activitypub/act/follow.ts b/src/remote/activitypub/act/follow.ts index 4fc423d15c..3dd029af54 100644 --- a/src/remote/activitypub/act/follow.ts +++ b/src/remote/activitypub/act/follow.ts @@ -1,11 +1,12 @@ import parseAcct from '../../../acct/parse'; -import User from '../../../models/user'; +import User, { IRemoteUser } from '../../../models/user'; import config from '../../../config'; import follow from '../../../services/following/create'; +import { IFollow } from '../type'; -export default async (actor, activity): Promise => { +export default async (actor: IRemoteUser, activity: IFollow): Promise => { const prefix = config.url + '/@'; - const id = activity.object.id || activity.object; + const id = typeof activity == 'string' ? activity : activity.id; if (!id.startsWith(prefix)) { return null; diff --git a/src/remote/activitypub/act/undo/follow.ts b/src/remote/activitypub/act/undo/follow.ts index b1c462a3b0..fcf27c9507 100644 --- a/src/remote/activitypub/act/undo/follow.ts +++ b/src/remote/activitypub/act/undo/follow.ts @@ -1,11 +1,12 @@ import parseAcct from '../../../../acct/parse'; -import User from '../../../../models/user'; +import User, { IRemoteUser } from '../../../../models/user'; import config from '../../../../config'; import unfollow from '../../../../services/following/delete'; +import { IFollow } from '../../type'; -export default async (actor, activity): Promise => { +export default async (actor: IRemoteUser, activity: IFollow): Promise => { const prefix = config.url + '/@'; - const id = activity.object.id || activity.object; + const id = typeof activity == 'string' ? activity : activity.id; if (!id.startsWith(prefix)) { return null; diff --git a/src/remote/activitypub/act/undo/index.ts b/src/remote/activitypub/act/undo/index.ts index ecd9944b42..3ede9fcfb8 100644 --- a/src/remote/activitypub/act/undo/index.ts +++ b/src/remote/activitypub/act/undo/index.ts @@ -1,13 +1,35 @@ -import unfollow from './follow'; +import * as debug from 'debug'; -export default async (actor, activity): Promise => { +import { IRemoteUser } from '../../../../models/user'; +import { IUndo } from '../../type'; +import unfollow from './follow'; +import Resolver from '../../resolver'; + +const log = debug('misskey:activitypub'); + +export default async (actor: IRemoteUser, activity: IUndo): Promise => { if ('actor' in activity && actor.account.uri !== activity.actor) { throw new Error('invalid actor'); } - switch (activity.object.type) { + const uri = activity.id || activity; + + log(`Undo: ${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 'Follow': - unfollow(actor, activity.object); + unfollow(actor, object); break; } diff --git a/src/remote/activitypub/act/unfollow.ts b/src/remote/activitypub/act/unfollow.ts deleted file mode 100644 index 66c15e9a91..0000000000 --- a/src/remote/activitypub/act/unfollow.ts +++ /dev/null @@ -1,25 +0,0 @@ -import parseAcct from '../../../acct/parse'; -import User from '../../../models/user'; -import config from '../../../config'; -import unfollow from '../../../services/following/delete'; - -export default async (actor, activity): Promise => { - const prefix = config.url + '/@'; - const id = activity.object.id || activity.object; - - if (!id.startsWith(prefix)) { - return null; - } - - const { username, host } = parseAcct(id.slice(prefix.length)); - if (host !== null) { - throw new Error(); - } - - const followee = await User.findOne({ username, host }); - if (followee === null) { - throw new Error(); - } - - await unfollow(actor, followee, activity); -}; diff --git a/src/remote/activitypub/type.ts b/src/remote/activitypub/type.ts index cd7f40630a..9a4b3c75fc 100644 --- a/src/remote/activitypub/type.ts +++ b/src/remote/activitypub/type.ts @@ -1,8 +1,5 @@ export type Object = { [x: string]: any }; -export type ActivityType = - 'Create'; - export interface IObject { '@context': string | object | any[]; type: string; @@ -10,6 +7,13 @@ export interface IObject { summary?: string; } +export interface IActivity extends IObject { + //type: 'Activity'; + actor: IObject | string; + object: IObject | string; + target?: IObject | string; +} + export interface ICollection extends IObject { type: 'Collection'; totalItems: number; @@ -30,3 +34,15 @@ export const isOrderedCollection = (object: IObject): object is IOrderedCollecti export const isCollectionOrOrderedCollection = (object: IObject): object is ICollection | IOrderedCollection => isCollection(object) || isOrderedCollection(object); + +export interface ICreate extends IActivity { + type: 'Create'; +} + +export interface IUndo extends IActivity { + type: 'Undo'; +} + +export interface IFollow extends IActivity { + type: 'Follow'; +}