From 8920eeb86af5c29e576b6a10784696edb02731f7 Mon Sep 17 00:00:00 2001 From: Johann150 Date: Tue, 11 Oct 2022 00:27:43 +0200 Subject: [PATCH] ActivityPub: allow all known shared inboxes to be addressed This is oriented on this paragraph from the AP spec: > Additionally, if an object is addressed to the Public special collection, > a server MAY deliver that object to all known sharedInbox endpoints > on the network. --- .../src/remote/activitypub/deliver-manager.ts | 35 +++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/packages/backend/src/remote/activitypub/deliver-manager.ts b/packages/backend/src/remote/activitypub/deliver-manager.ts index e0af5b8f9..5fd0d5f60 100644 --- a/packages/backend/src/remote/activitypub/deliver-manager.ts +++ b/packages/backend/src/remote/activitypub/deliver-manager.ts @@ -8,6 +8,10 @@ interface IRecipe { type: string; } +interface IEveryoneRecipe extends IRecipe { + type: 'Everyone'; +} + interface IFollowersRecipe extends IRecipe { type: 'Followers'; } @@ -17,6 +21,9 @@ interface IDirectRecipe extends IRecipe { to: IRemoteUser; } +const isEveryone = (recipe: any): recipe is IEveryoneRecipe => + recipe.type === 'Everyone'; + const isFollowers = (recipe: any): recipe is IFollowersRecipe => recipe.type === 'Followers'; @@ -63,6 +70,13 @@ export default class DeliverManager { this.addRecipe(recipe); } + /** + * Add recipe to send this activity to all known sharedInboxes + */ + public addEveryone() { + this.addRecipe({ type: 'Everyone' } as IEveryoneRecipe); + } + /** * Add recipe * @param recipe Recipe @@ -82,9 +96,26 @@ export default class DeliverManager { /* build inbox list - Process follower recipes first to avoid duplication when processing - direct recipes later. + Processing order matters to avoid duplication. */ + + if (this.recipes.some(r => isEveryone(r))) { + // deliver to all of known network + const sharedInboxes = await Users.createQueryBuilder('users') + .select('users.sharedInbox', 'sharedInbox') + // can't deliver to unknown shared inbox + .where('users.sharedInbox IS NOT NULL') + // don't deliver to ourselves + .andWhere('users.host IS NOT NULL') + // so we don't have to make our inboxes Set work as hard + .groupBy('users.sharedInbox') + .getRawMany(); + + for (const inbox of sharedInboxes) { + inboxes.add(inbox.sharedInbox); + } + } + if (this.recipes.some(r => isFollowers(r))) { // followers deliver // TODO: SELECT DISTINCT ON ("followerSharedInbox") "followerSharedInbox" みたいな問い合わせにすればよりパフォーマンス向上できそう