From a786fd99fcac660e5c6e209fb218c5c3019870c9 Mon Sep 17 00:00:00 2001 From: Johann150 Date: Tue, 18 Apr 2023 21:27:05 +0200 Subject: [PATCH] make delivery manager author agnostic --- .../src/remote/activitypub/deliver-manager.ts | 57 ++++++++++--------- packages/backend/src/services/note/create.ts | 4 +- packages/backend/src/services/note/delete.ts | 4 +- .../src/services/note/reaction/create.ts | 4 +- .../src/services/note/reaction/delete.ts | 4 +- packages/backend/src/services/suspend-user.ts | 2 +- 6 files changed, 38 insertions(+), 37 deletions(-) diff --git a/packages/backend/src/remote/activitypub/deliver-manager.ts b/packages/backend/src/remote/activitypub/deliver-manager.ts index 4bc651c98..0262f94fe 100644 --- a/packages/backend/src/remote/activitypub/deliver-manager.ts +++ b/packages/backend/src/remote/activitypub/deliver-manager.ts @@ -14,6 +14,7 @@ interface IEveryoneRecipe extends IRecipe { interface IFollowersRecipe extends IRecipe { type: 'Followers'; + followee: ILocalUser; } interface IDirectRecipe extends IRecipe { @@ -32,26 +33,24 @@ const isDirect = (recipe: any): recipe is IDirectRecipe => //#endregion export class DeliverManager { - private actor: { id: User['id']; host: null; }; private activity: any; private recipes: IRecipe[] = []; /** * Constructor - * @param actor Actor * @param activity Activity to deliver */ - constructor(actor: { id: User['id']; host: null; }, activity: any) { - this.actor = actor; + constructor(activity: any) { this.activity = activity; } /** * Add recipe for followers deliver */ - public addFollowersRecipe() { + public addFollowersRecipe(followee: ILocalUser) { const deliver = { type: 'Followers', + followee, } as IFollowersRecipe; this.addRecipe(deliver); @@ -89,8 +88,6 @@ export class DeliverManager { * Execute delivers */ public async execute() { - if (!Users.isLocalUser(this.actor)) return; - const inboxes = new Set(); /* @@ -116,21 +113,25 @@ export class DeliverManager { } } - if (this.recipes.some(r => isFollowers(r))) { - // followers deliver - const followers = await Followings.createQueryBuilder('followings') - // return either the shared inbox (if available) or the individual inbox - .select('COALESCE(followings.followerSharedInbox, followings.followerInbox)', 'inbox') - // so we don't have to make our inboxes Set work as hard - .distinct(true) - // ...for the specific actors followers - .where('followings.followeeId = :actorId', { actorId: this.actor.id }) - // don't deliver to ourselves - .andWhere('followings.followerHost IS NOT NULL') - .getRawMany(); - - followers.forEach(({ inbox }) => inboxes.add(inbox)); - } + await Promise.all( + this.recipes.filter(isFollowers) + .map(recipe => { + // followers deliver + return Followings.createQueryBuilder('followings') + // return either the shared inbox (if available) or the individual inbox + .select('COALESCE(followings.followerSharedInbox, followings.followerInbox)', 'inbox') + // so we don't have to make our inboxes Set work as hard + .distinct(true) + // ...for the specific actors followers + .where('followings.followeeId = :actorId', { actorId: recipe.followee.id }) + // don't deliver to ourselves + .andWhere('followings.followerHost IS NOT NULL') + .getRawMany() + .then(followers => + followers.forEach(({ inbox }) => inboxes.add(inbox)) + ); + }) + ); this.recipes.filter((recipe): recipe is IDirectRecipe => // followers recipes have already been processed @@ -155,7 +156,7 @@ export class DeliverManager { // skip instances as indicated if (instancesToSkip.includes(new URL(inbox).host)) continue; - deliver(this.actor, this.activity, inbox); + deliver(null, this.activity, inbox); } } } @@ -166,9 +167,9 @@ export class DeliverManager { * @param activity Activity * @param from Followee */ -export async function deliverToFollowers(actor: { id: ILocalUser['id']; host: null; }, activity: any) { - const manager = new DeliverManager(actor, activity); - manager.addFollowersRecipe(); +export async function deliverToFollowers(actor: ILocalUser, activity: any) { + const manager = new DeliverManager(activity); + manager.addFollowersRecipe(actor); await manager.execute(); } @@ -177,8 +178,8 @@ export async function deliverToFollowers(actor: { id: ILocalUser['id']; host: nu * @param activity Activity * @param to Target user */ -export async function deliverToUser(actor: { id: ILocalUser['id']; host: null; }, activity: any, to: IRemoteUser) { - const manager = new DeliverManager(actor, activity); +export async function deliverToUser(activity: any, to: IRemoteUser) { + const manager = new DeliverManager(activity); manager.addDirectRecipe(to); await manager.execute(); } diff --git a/packages/backend/src/services/note/create.ts b/packages/backend/src/services/note/create.ts index 8f48bc12a..5fddfdcd3 100644 --- a/packages/backend/src/services/note/create.ts +++ b/packages/backend/src/services/note/create.ts @@ -432,7 +432,7 @@ export default async (user: { id: User['id']; username: User['username']; host: if (Users.isLocalUser(user) && !data.localOnly) { (async () => { const noteActivity = renderActivity(await renderNoteOrRenoteActivity(note)); - const dm = new DeliverManager(user, noteActivity); + const dm = new DeliverManager(noteActivity); // Delivered to remote users who have been mentioned for (const u of mentionedUsers.filter(u => Users.isRemoteUser(u))) { @@ -453,7 +453,7 @@ export default async (user: { id: User['id']; username: User['username']; host: // Deliver to followers if (['public', 'home', 'followers'].includes(note.visibility)) { - dm.addFollowersRecipe(); + dm.addFollowersRecipe(user); } if (['public'].includes(note.visibility)) { diff --git a/packages/backend/src/services/note/delete.ts b/packages/backend/src/services/note/delete.ts index f22ce80db..f8e7cd10b 100644 --- a/packages/backend/src/services/note/delete.ts +++ b/packages/backend/src/services/note/delete.ts @@ -60,8 +60,8 @@ export async function deleteNotes(notes: Note[], user?: User): Promise { // Compute addressing information. // Since we do not send any actual content, we send all note deletions to everyone. - const manager = new DeliverManager(fetchedUser, content); - manager.addFollowersRecipe(); + const manager = new DeliverManager(content); + manager.addFollowersRecipe(fetchedUser); manager.addEveryone(); // Check mentioned users, since not all may have a shared inbox. await Promise.all( diff --git a/packages/backend/src/services/note/reaction/create.ts b/packages/backend/src/services/note/reaction/create.ts index d50761a29..e35ceb991 100644 --- a/packages/backend/src/services/note/reaction/create.ts +++ b/packages/backend/src/services/note/reaction/create.ts @@ -130,14 +130,14 @@ export async function createReaction(user: { id: User['id']; host: User['host']; //#region 配信 if (Users.isLocalUser(user) && !note.localOnly) { const content = renderActivity(await renderLike(record, note)); - const dm = new DeliverManager(user, content); + const dm = new DeliverManager(content); if (note.userHost !== null) { const reactee = await Users.findOneBy({ id: note.userId }); dm.addDirectRecipe(reactee as IRemoteUser); } if (['public', 'home', 'followers'].includes(note.visibility)) { - dm.addFollowersRecipe(); + dm.addFollowersRecipe(user); } else if (note.visibility === 'specified') { const visibleUsers = await Promise.all(note.visibleUserIds.map(id => Users.findOneBy({ id }))); for (const u of visibleUsers.filter(u => u && Users.isRemoteUser(u))) { diff --git a/packages/backend/src/services/note/reaction/delete.ts b/packages/backend/src/services/note/reaction/delete.ts index 616a30015..060fe43de 100644 --- a/packages/backend/src/services/note/reaction/delete.ts +++ b/packages/backend/src/services/note/reaction/delete.ts @@ -46,12 +46,12 @@ export async function deleteReaction(user: { id: User['id']; host: User['host']; //#region 配信 if (Users.isLocalUser(user) && !note.localOnly) { const content = renderActivity(renderUndo(await renderLike(exist, note), user)); - const dm = new DeliverManager(user, content); + const dm = new DeliverManager(content); if (note.userHost !== null) { const reactee = await Users.findOneBy({ id: note.userId }); dm.addDirectRecipe(reactee as IRemoteUser); } - dm.addFollowersRecipe(); + dm.addFollowersRecipe(user); dm.execute(); } //#endregion diff --git a/packages/backend/src/services/suspend-user.ts b/packages/backend/src/services/suspend-user.ts index 11e6266a0..d08683008 100644 --- a/packages/backend/src/services/suspend-user.ts +++ b/packages/backend/src/services/suspend-user.ts @@ -13,7 +13,7 @@ export async function doPostSuspend(user: { id: User['id']; host: User['host'] } const content = renderActivity(renderDelete(`${config.url}/users/${user.id}`, user)); // deliver to all of known network - const dm = new DeliverManager(user, content); + const dm = new DeliverManager(content); dm.addEveryone(); await dm.execute(); }