From 389ec6350be1b5f980eb19db4c98ba2ebf22ca38 Mon Sep 17 00:00:00 2001 From: zyoshoka <107108195+zyoshoka@users.noreply.github.com> Date: Wed, 26 Feb 2025 09:29:12 +0900 Subject: fix(backend): send Delete activity of a note to users who renoted or replied to it (#15554) * fix(backend): send Delete activity of a note to users who renoted or replied to it * Update CHANGELOG.md --- packages/backend/src/core/NoteDeleteService.ts | 24 +++++++++++++++++----- .../core/activitypub/ApDeliverManagerService.ts | 19 +++++++++++++++++ 2 files changed, 38 insertions(+), 5 deletions(-) (limited to 'packages/backend/src') diff --git a/packages/backend/src/core/NoteDeleteService.ts b/packages/backend/src/core/NoteDeleteService.ts index 4ecd2592b2..e394506a44 100644 --- a/packages/backend/src/core/NoteDeleteService.ts +++ b/packages/backend/src/core/NoteDeleteService.ts @@ -3,7 +3,7 @@ * SPDX-License-Identifier: AGPL-3.0-only */ -import { Brackets, In } from 'typeorm'; +import { Brackets, In, IsNull, Not } from 'typeorm'; import { Injectable, Inject } from '@nestjs/common'; import type { MiUser, MiLocalUser, MiRemoteUser } from '@/models/User.js'; import type { MiNote, IMentionedRemoteUsers } from '@/models/Note.js'; @@ -189,13 +189,27 @@ export class NoteDeleteService { }) as MiRemoteUser[]; } + @bindThis + private async getRenotedOrRepliedRemoteUsers(note: MiNote) { + const query = this.notesRepository.createQueryBuilder('note') + .leftJoinAndSelect('note.user', 'user') + .where(new Brackets(qb => { + qb.orWhere('note.renoteId = :renoteId', { renoteId: note.id }); + qb.orWhere('note.replyId = :replyId', { replyId: note.id }); + })) + .andWhere({ userHost: Not(IsNull()) }); + const notes = await query.getMany() as (MiNote & { user: MiRemoteUser })[]; + const remoteUsers = notes.map(({ user }) => user); + return remoteUsers; + } + @bindThis private async deliverToConcerned(user: { id: MiLocalUser['id']; host: null; }, note: MiNote, content: any) { this.apDeliverManagerService.deliverToFollowers(user, content); this.relayService.deliverToRelays(user, content); - const remoteUsers = await this.getMentionedRemoteUsers(note); - for (const remoteUser of remoteUsers) { - this.apDeliverManagerService.deliverToUser(user, content, remoteUser); - } + this.apDeliverManagerService.deliverToUsers(user, content, [ + ...await this.getMentionedRemoteUsers(note), + ...await this.getRenotedOrRepliedRemoteUsers(note), + ]); } } diff --git a/packages/backend/src/core/activitypub/ApDeliverManagerService.ts b/packages/backend/src/core/activitypub/ApDeliverManagerService.ts index 5d07cd8e8f..0140ce9fd6 100644 --- a/packages/backend/src/core/activitypub/ApDeliverManagerService.ts +++ b/packages/backend/src/core/activitypub/ApDeliverManagerService.ts @@ -196,6 +196,25 @@ export class ApDeliverManagerService { await manager.execute(); } + /** + * Deliver activity to users + * @param actor + * @param activity Activity + * @param targets Target users + */ + @bindThis + public async deliverToUsers(actor: { id: MiLocalUser['id']; host: null; }, activity: IActivity, targets: MiRemoteUser[]): Promise { + const manager = new DeliverManager( + this.userEntityService, + this.followingsRepository, + this.queueService, + actor, + activity, + ); + for (const to of targets) manager.addDirectRecipe(to); + await manager.execute(); + } + @bindThis public createDeliverManager(actor: { id: MiUser['id']; host: null; }, activity: IActivity | null): DeliverManager { return new DeliverManager( -- cgit v1.2.3-freya