diff options
| author | MeiMei <30769358+mei23@users.noreply.github.com> | 2019-03-07 21:19:32 +0900 |
|---|---|---|
| committer | syuilo <Syuilotan@yahoo.co.jp> | 2019-03-07 21:19:32 +0900 |
| commit | 7325d66c52365104b6b5d6343324a258470ad2a8 (patch) | |
| tree | 2e34ad9e592d64ab1a672877b33d384bc67e3d90 /src/remote/activitypub | |
| parent | Update README.md [AUTOGEN] (#4441) (diff) | |
| download | misskey-7325d66c52365104b6b5d6343324a258470ad2a8.tar.gz misskey-7325d66c52365104b6b5d6343324a258470ad2a8.tar.bz2 misskey-7325d66c52365104b6b5d6343324a258470ad2a8.zip | |
Implement Update Question (#4435)
* Update remote votes count
* save updatedAt
* deliver Update
* use renderNote
* use id
* fix typeof
Diffstat (limited to 'src/remote/activitypub')
| -rw-r--r-- | src/remote/activitypub/kernel/index.ts | 5 | ||||
| -rw-r--r-- | src/remote/activitypub/kernel/update/index.ts | 28 | ||||
| -rw-r--r-- | src/remote/activitypub/models/note.ts | 4 | ||||
| -rw-r--r-- | src/remote/activitypub/models/question.ts | 69 | ||||
| -rw-r--r-- | src/remote/activitypub/type.ts | 23 |
5 files changed, 114 insertions, 15 deletions
diff --git a/src/remote/activitypub/kernel/index.ts b/src/remote/activitypub/kernel/index.ts index 7cf9ba8334..4f7a5c91fd 100644 --- a/src/remote/activitypub/kernel/index.ts +++ b/src/remote/activitypub/kernel/index.ts @@ -2,6 +2,7 @@ import { Object } from '../type'; import { IRemoteUser } from '../../../models/user'; import create from './create'; import performDeleteActivity from './delete'; +import performUpdateActivity from './update'; import follow from './follow'; import undo from './undo'; import like from './like'; @@ -23,6 +24,10 @@ const self = async (actor: IRemoteUser, activity: Object): Promise<void> => { await performDeleteActivity(actor, activity); break; + case 'Update': + await performUpdateActivity(actor, activity); + break; + case 'Follow': await follow(actor, activity); break; diff --git a/src/remote/activitypub/kernel/update/index.ts b/src/remote/activitypub/kernel/update/index.ts new file mode 100644 index 0000000000..49b730391a --- /dev/null +++ b/src/remote/activitypub/kernel/update/index.ts @@ -0,0 +1,28 @@ +import { IRemoteUser } from '../../../../models/user'; +import { IUpdate, IObject } from '../../type'; +import { apLogger } from '../../logger'; +import { updateQuestion } from '../../models/question'; + +/** + * Updateアクティビティを捌きます + */ +export default async (actor: IRemoteUser, activity: IUpdate): Promise<void> => { + if ('actor' in activity && actor.uri !== activity.actor) { + throw new Error('invalid actor'); + } + + apLogger.debug('Update'); + + const object = activity.object as IObject; + + switch (object.type) { + case 'Question': + apLogger.debug('Question'); + await updateQuestion(object).catch(e => console.log(e)); + break; + + default: + apLogger.warn(`Unknown type: ${object.type}`); + break; + } +}; diff --git a/src/remote/activitypub/models/note.ts b/src/remote/activitypub/models/note.ts index 5932d3d90e..a87257dffc 100644 --- a/src/remote/activitypub/models/note.ts +++ b/src/remote/activitypub/models/note.ts @@ -18,6 +18,7 @@ import { extractPollFromQuestion } from './question'; import vote from '../../../services/note/polls/vote'; import { apLogger } from '../logger'; import { IDriveFile } from '../../../models/drive-file'; +import { deliverQuestionUpdate } from '../../../services/note/polls/update'; const logger = apLogger; @@ -136,6 +137,9 @@ export async function createNote(value: any, resolver?: Resolver, silent = false } else if (index >= 0) { logger.info(`vote from AP: actor=${actor.username}@${actor.host}, note=${note.id}, choice=${name}`); await vote(actor, reply, index); + + // リモートフォロワーにUpdate配信 + deliverQuestionUpdate(reply._id); } return null; }; diff --git a/src/remote/activitypub/models/question.ts b/src/remote/activitypub/models/question.ts index edfd8701b4..c073684349 100644 --- a/src/remote/activitypub/models/question.ts +++ b/src/remote/activitypub/models/question.ts @@ -1,18 +1,8 @@ -import { IChoice, IPoll } from '../../../models/note'; +import config from '../../../config'; +import Note, { IChoice, IPoll } from '../../../models/note'; import Resolver from '../resolver'; -import { ICollection } from '../type'; - -interface IQuestionChoice { - name?: string; - replies?: ICollection; - _misskey_votes?: number; -} - -interface IQuestion { - oneOf?: IQuestionChoice[]; - anyOf?: IQuestionChoice[]; - endTime?: Date; -} +import { IQuestion } from '../type'; +import { apLogger } from '../logger'; export async function extractPollFromQuestion(source: string | IQuestion): Promise<IPoll> { const question = typeof source === 'string' ? await new Resolver().resolve(source) as IQuestion : source; @@ -36,3 +26,54 @@ export async function extractPollFromQuestion(source: string | IQuestion): Promi expiresAt }; } + +/** + * Update votes of Question + * @param uri URI of AP Question object + * @returns true if updated + */ +export async function updateQuestion(value: any) { + const uri = typeof value == 'string' ? value : value.id; + + // URIがこのサーバーを指しているならスキップ + if (uri.startsWith(config.url + '/')) throw 'uri points local'; + + //#region このサーバーに既に登録されているか + const note = await Note.findOne({ uri }); + + if (note == null) throw 'Question is not registed'; + //#endregion + + // resolve new Question object + const resolver = new Resolver(); + const question = await resolver.resolve(value) as IQuestion; + apLogger.debug(`fetched question: ${JSON.stringify(question, null, 2)}`); + + if (question.type !== 'Question') throw 'object is not a Question'; + + const apChoices = question.oneOf || question.anyOf; + const dbChoices = note.poll.choices; + + let changed = false; + + for (const db of dbChoices) { + const oldCount = db.votes; + const newCount = apChoices.filter(ap => ap.name === db.text)[0].replies.totalItems; + + if (oldCount != newCount) { + changed = true; + db.votes = newCount; + } + } + + await Note.update({ + _id: note._id + }, { + $set: { + 'poll.choices': dbChoices, + updatedAt: new Date(), + } + }); + + return changed; +} diff --git a/src/remote/activitypub/type.ts b/src/remote/activitypub/type.ts index c8a00f3591..c381e63507 100644 --- a/src/remote/activitypub/type.ts +++ b/src/remote/activitypub/type.ts @@ -43,12 +43,28 @@ export interface IOrderedCollection extends IObject { } export interface INote extends IObject { - type: 'Note'; + type: 'Note' | 'Question'; _misskey_content: string; _misskey_quote: string; _misskey_question: string; } +export interface IQuestion extends IObject { + type: 'Note' | 'Question'; + _misskey_content: string; + _misskey_quote: string; + _misskey_question: string; + oneOf?: IQuestionChoice[]; + anyOf?: IQuestionChoice[]; + endTime?: Date; +} + +interface IQuestionChoice { + name?: string; + replies?: ICollection; + _misskey_votes?: number; +} + export interface IPerson extends IObject { type: 'Person'; name: string; @@ -81,6 +97,10 @@ export interface IDelete extends IActivity { type: 'Delete'; } +export interface IUpdate extends IActivity { + type: 'Update'; +} + export interface IUndo extends IActivity { type: 'Undo'; } @@ -123,6 +143,7 @@ export type Object = IOrderedCollection | ICreate | IDelete | + IUpdate | IUndo | IFollow | IAccept | |