diff --git a/packages/backend/src/core/AccountMoveService.ts b/packages/backend/src/core/AccountMoveService.ts index e2b38a396f..017e2d7e58 100644 --- a/packages/backend/src/core/AccountMoveService.ts +++ b/packages/backend/src/core/AccountMoveService.ts @@ -5,7 +5,7 @@ import { bindThis } from '@/decorators.js'; import { DI } from '@/di-symbols.js'; import type { Config } from '@/config.js'; import type { LocalUser } from '@/models/entities/User.js'; -import type { BlockingsRepository, FollowingsRepository, InstancesRepository, MutingsRepository, UserListJoiningsRepository, UsersRepository } from '@/models/index.js'; +import type { BlockingsRepository, FollowingsRepository, InstancesRepository, Muting, MutingsRepository, UserListJoiningsRepository, UsersRepository } from '@/models/index.js'; import type { RelationshipJobData, ThinUser } from '@/queue/types.js'; import type { User } from '@/models/entities/User.js'; @@ -154,17 +154,38 @@ export class AccountMoveService { @bindThis public async copyMutings(src: ThinUser, dst: ThinUser): Promise { // Insert new mutings with the same values except mutee - const mutings = await this.mutingsRepository.findBy([ + const oldMutings = await this.mutingsRepository.findBy([ { muteeId: src.id, expiresAt: IsNull() }, { muteeId: src.id, expiresAt: MoreThan(new Date()) }, ]); - const muteIds = mutings.map(mute => mute.id); - if (muteIds.length > 0) { - await this.mutingsRepository.update({ id: In(muteIds) }, { muteeId: dst.id }); - for (const muterId of mutings.map(mute => mute.muterId)) { - this.cacheService.userMutingsCache.refresh(muterId); - } + if (oldMutings.length === 0) return; + + // Check if the destination account is already indefinitely muted by the muter + const existingMutingsMuterUserIds = await this.mutingsRepository.findBy( + { muteeId: dst.id, expiresAt: IsNull() }, + ).then(mutings => mutings.map(muting => muting.muterId)); + + const newMutings: Map = new Map(); + + // 重複しないようにIDを生成 + const genId = (): string => { + let id: string; + do { + id = this.idService.genId(); + } while (newMutings.has(id)); + return id; + }; + for (const muting of oldMutings) { + if (existingMutingsMuterUserIds.includes(muting.muterId)) continue; // skip if already muted indefinitely + newMutings.set(genId(), { + ...muting, + createdAt: new Date(), + muteeId: dst.id, + }); } + + const arrayToInsert = Array.from(newMutings.entries()).map(entry => ({ ...entry[1], id: entry[0] })); + await this.mutingsRepository.insert(arrayToInsert); } /** diff --git a/packages/backend/test/e2e/move.ts b/packages/backend/test/e2e/move.ts index db3110f56c..2a49402aa7 100644 --- a/packages/backend/test/e2e/move.ts +++ b/packages/backend/test/e2e/move.ts @@ -282,8 +282,9 @@ describe('Account Move', () => { const mutings = await api('/mute/list', {}, dave); assert.strictEqual(mutings.status, 200); - assert.strictEqual(mutings.body.length, 1); + assert.strictEqual(mutings.body.length, 2); assert.strictEqual(mutings.body[0].muteeId, bob.id); + assert.strictEqual(mutings.body[1].muteeId, alice.id); const rootLists = await api('/users/lists/list', {}, root); assert.strictEqual(rootLists.status, 200); diff --git a/packages/backend/test/e2e/users.ts b/packages/backend/test/e2e/users.ts index 2c4716c060..c1a57f102f 100644 --- a/packages/backend/test/e2e/users.ts +++ b/packages/backend/test/e2e/users.ts @@ -83,7 +83,7 @@ describe('ユーザー', () => { ...userLite(user), url: user.url, uri: user.uri, - movedToUri: user.movedToUri, + movedTo: user.movedTo, alsoKnownAs: user.alsoKnownAs, createdAt: user.createdAt, updatedAt: user.updatedAt, @@ -348,7 +348,7 @@ describe('ユーザー', () => { // UserDetailedNotMeOnly assert.strictEqual(response.url, null); assert.strictEqual(response.uri, null); - assert.strictEqual(response.movedToUri, null); + assert.strictEqual(response.movedTo, null); assert.strictEqual(response.alsoKnownAs, null); assert.strictEqual(response.createdAt, new Date(response.createdAt).toISOString()); assert.strictEqual(response.updatedAt, null);