diff --git a/CHANGELOG.md b/CHANGELOG.md index 693b31c44a..32d57311a2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ - Fix: 自動バックアップが設定されている環境でログアウト直前に設定をバックアップするように - Fix: フォルダを開いた状態でメニューからアップロードしてもルートフォルダにアップロードされる問題を修正 #15836 - Fix: タイムラインのスクロール位置を記憶するように修正 +- Fix: アカウントの移行時にアンテナのフィルターのユーザが更新されない問題を修正 #15843 ### Server - Enhance: フォローしているユーザーならフォロワー限定投稿のノートでもアンテナで検知できるように diff --git a/packages/backend/src/core/AccountMoveService.ts b/packages/backend/src/core/AccountMoveService.ts index 406563bee8..f8e3eaf01f 100644 --- a/packages/backend/src/core/AccountMoveService.ts +++ b/packages/backend/src/core/AccountMoveService.ts @@ -25,6 +25,7 @@ import InstanceChart from '@/core/chart/charts/instance.js'; import PerUserFollowingChart from '@/core/chart/charts/per-user-following.js'; import { SystemAccountService } from '@/core/SystemAccountService.js'; import { RoleService } from '@/core/RoleService.js'; +import { AntennaService } from '@/core/AntennaService.js'; @Injectable() export class AccountMoveService { @@ -63,6 +64,7 @@ export class AccountMoveService { private queueService: QueueService, private systemAccountService: SystemAccountService, private roleService: RoleService, + private antennaService: AntennaService, ) { } @@ -123,6 +125,7 @@ export class AccountMoveService { this.copyMutings(src, dst), this.copyRoles(src, dst), this.updateLists(src, dst), + this.antennaService.onMoveAccount(src, dst), ]); } catch { /* skip if any error happens */ diff --git a/packages/backend/src/core/AntennaService.ts b/packages/backend/src/core/AntennaService.ts index 7db3e69155..ec79675b06 100644 --- a/packages/backend/src/core/AntennaService.ts +++ b/packages/backend/src/core/AntennaService.ts @@ -5,6 +5,7 @@ import { Inject, Injectable } from '@nestjs/common'; import * as Redis from 'ioredis'; +import { In } from 'typeorm'; import { FanoutTimelineService } from '@/core/FanoutTimelineService.js'; import type { GlobalEvents } from '@/core/GlobalEventService.js'; import { GlobalEventService } from '@/core/GlobalEventService.js'; @@ -219,6 +220,41 @@ export class AntennaService implements OnApplicationShutdown { return this.antennas; } + @bindThis + public async onMoveAccount(src: MiUser, dst: MiUser): Promise { + // There is a possibility for users to add the srcUser to their antennas, but it's low, so we don't check it. + + // Get MiAntenna[] from cache and filter to select antennas with the src user is in the users list + const srcUserAcct = this.utilityService.getFullApAccount(src.username, src.host).toLowerCase(); + const antennasToMigrate = (await this.getAntennas()).filter(antenna => { + return antenna.users.some(user => { + const { username, host } = Acct.parse(user); + return this.utilityService.getFullApAccount(username, host).toLowerCase() === srcUserAcct; + }); + }); + + if (antennasToMigrate.length === 0) return; + + const antennaIds = antennasToMigrate.map(x => x.id); + + // Update the antennas by appending dst users acct to the users list + const dstUserAcct = '@' + Acct.toString({ username: dst.username, host: dst.host }); + + await this.antennasRepository.createQueryBuilder('antenna') + .update() + .set({ + users: () => 'array_append(antenna.users, :dstUserAcct)', + }) + .where('antenna.id IN (:...antennaIds)', { antennaIds }) + .setParameters({ dstUserAcct }) + .execute(); + + // announce update to event + for (const newAntenna of await this.antennasRepository.findBy({ id: In(antennaIds) })) { + this.globalEventService.publishInternalEvent('antennaUpdated', newAntenna); + } + } + @bindThis public dispose(): void { this.redisForSub.off('message', this.onRedisMessage);