From 02ac7d002938c595db3ecba88750d697ba989e09 Mon Sep 17 00:00:00 2001 From: tamaina Date: Sun, 13 Jul 2025 20:24:31 +0900 Subject: [PATCH] wip --- .../backend/src/core/NoteCreateService.ts | 2 + .../backend/src/core/UserFollowingService.ts | 7 ++-- .../backend/src/core/UserSuspendService.ts | 40 ++++++++++--------- .../activitypub/ApDeliverManagerService.ts | 1 + packages/backend/src/models/Following.ts | 7 ++++ .../api/endpoints/federation/followers.ts | 3 +- .../api/endpoints/federation/following.ts | 3 +- .../server/api/endpoints/federation/stats.ts | 2 + .../server/api/endpoints/users/followers.ts | 2 + .../server/api/endpoints/users/following.ts | 2 + .../api/endpoints/users/recommendation.ts | 3 +- 11 files changed, 48 insertions(+), 24 deletions(-) diff --git a/packages/backend/src/core/NoteCreateService.ts b/packages/backend/src/core/NoteCreateService.ts index 469426f87e..3f045efd03 100644 --- a/packages/backend/src/core/NoteCreateService.ts +++ b/packages/backend/src/core/NoteCreateService.ts @@ -545,6 +545,7 @@ export class NoteCreateService implements OnApplicationShutdown { // TODO: キャッシュ this.followingsRepository.findBy({ followeeId: user.id, + isFollowerSuspended: false, notify: 'normal', }).then(async followings => { if (note.visibility !== 'specified') { @@ -850,6 +851,7 @@ export class NoteCreateService implements OnApplicationShutdown { where: { followeeId: user.id, followerHost: IsNull(), + isFollowerSuspended: false, isFollowerHibernated: false, }, select: ['followerId', 'withReplies'], diff --git a/packages/backend/src/core/UserFollowingService.ts b/packages/backend/src/core/UserFollowingService.ts index e7a6be99fb..f5d8222a8e 100644 --- a/packages/backend/src/core/UserFollowingService.ts +++ b/packages/backend/src/core/UserFollowingService.ts @@ -229,9 +229,7 @@ export class UserFollowingService implements OnModuleInit { followee: { id: MiUser['id']; host: MiUser['host']; uri: MiUser['host']; inbox: MiUser['inbox']; sharedInbox: MiUser['sharedInbox'] }, - follower: { - id: MiUser['id']; host: MiUser['host']; uri: MiUser['host']; inbox: MiUser['inbox']; sharedInbox: MiUser['sharedInbox'] - }, + follower: MiUser, silent = false, withReplies?: boolean, ): Promise { @@ -244,6 +242,7 @@ export class UserFollowingService implements OnModuleInit { followerId: follower.id, followeeId: followee.id, withReplies: withReplies, + isFollowerSuspended: follower.isSuspended, // 非正規化 followerHost: follower.host, @@ -734,6 +733,7 @@ export class UserFollowingService implements OnModuleInit { return this.followingsRepository.createQueryBuilder('following') .select('following.followeeId') .where('following.followerId = :followerId', { followerId: userId }) + .andWhere('following.isFollowerSuspended = false') .getMany(); } @@ -743,6 +743,7 @@ export class UserFollowingService implements OnModuleInit { where: { followerId, followeeId, + isFollowerSuspended: false, }, }); } diff --git a/packages/backend/src/core/UserSuspendService.ts b/packages/backend/src/core/UserSuspendService.ts index 7920e58e36..601859990a 100644 --- a/packages/backend/src/core/UserSuspendService.ts +++ b/packages/backend/src/core/UserSuspendService.ts @@ -49,8 +49,8 @@ export class UserSuspendService { }); (async () => { - await this.postSuspend(user).catch(e => {}); - await this.unFollowAll(user).catch(e => {}); + await this.postSuspend(user).catch((e: any) => {}); + await this.unFollowAll(user).catch((e: any) => {}); })(); } @@ -67,7 +67,8 @@ export class UserSuspendService { }); (async () => { - await this.postUnsuspend(user).catch(e => {}); + await this.postUnsuspend(user).catch((e: any) => {}); + await this.restoreFollowings(user).catch((e: any) => {}); })(); } @@ -140,23 +141,26 @@ export class UserSuspendService { @bindThis private async unFollowAll(follower: MiUser) { - const followings = await this.followingsRepository.find({ - where: { + await this.followingsRepository.update( + { followerId: follower.id, - followeeId: Not(IsNull()), }, - }); - - const jobs: RelationshipJobData[] = []; - for (const following of followings) { - if (following.followeeId && following.followerId) { - jobs.push({ - from: { id: following.followerId }, - to: { id: following.followeeId }, - silent: true, - }); + { + isFollowerSuspended: true, } - } - this.queueService.createUnfollowJob(jobs); + ); + } + + @bindThis + private async restoreFollowings(follower: MiUser) { + // フォロー関係を復元(isFollowerSuspended: false)に変更 + await this.followingsRepository.update( + { + followerId: follower.id, + }, + { + isFollowerSuspended: false, + } + ); } } diff --git a/packages/backend/src/core/activitypub/ApDeliverManagerService.ts b/packages/backend/src/core/activitypub/ApDeliverManagerService.ts index 0140ce9fd6..c0d667253f 100644 --- a/packages/backend/src/core/activitypub/ApDeliverManagerService.ts +++ b/packages/backend/src/core/activitypub/ApDeliverManagerService.ts @@ -119,6 +119,7 @@ class DeliverManager { where: { followeeId: this.actor.id, followerHost: Not(IsNull()), + isFollowerSuspended: false, }, select: { followerSharedInbox: true, diff --git a/packages/backend/src/models/Following.ts b/packages/backend/src/models/Following.ts index 62cbc29f26..c30a7d42d6 100644 --- a/packages/backend/src/models/Following.ts +++ b/packages/backend/src/models/Following.ts @@ -10,6 +10,8 @@ import { MiUser } from './User.js'; @Entity('following') @Index(['followerId', 'followeeId'], { unique: true }) @Index(['followeeId', 'followerHost', 'isFollowerHibernated']) +@Index(['followeeId', 'followerHost', 'isFollowerSuspended']) +@Index(['followerId', 'isFollowerSuspended']) export class MiFollowing { @PrimaryColumn(id()) public id: string; @@ -45,6 +47,11 @@ export class MiFollowing { }) public isFollowerHibernated: boolean; + @Column('boolean', { + default: false, + }) + public isFollowerSuspended: boolean; + // タイムラインにその人のリプライまで含めるかどうか @Column('boolean', { default: false, diff --git a/packages/backend/src/server/api/endpoints/federation/followers.ts b/packages/backend/src/server/api/endpoints/federation/followers.ts index 296bc7c5a8..f4d4caf988 100644 --- a/packages/backend/src/server/api/endpoints/federation/followers.ts +++ b/packages/backend/src/server/api/endpoints/federation/followers.ts @@ -50,7 +50,8 @@ export default class extends Endpoint { // eslint- ) { super(meta, paramDef, async (ps, me) => { const query = this.queryService.makePaginationQuery(this.followingsRepository.createQueryBuilder('following'), ps.sinceId, ps.untilId, ps.sinceDate, ps.untilDate) - .andWhere('following.followeeHost = :host', { host: ps.host }); + .andWhere('following.followeeHost = :host', { host: ps.host }) + .andWhere('following.isFollowerSuspended = false'); const followings = await query .limit(ps.limit) diff --git a/packages/backend/src/server/api/endpoints/federation/following.ts b/packages/backend/src/server/api/endpoints/federation/following.ts index 091bf442af..fa8af37c1c 100644 --- a/packages/backend/src/server/api/endpoints/federation/following.ts +++ b/packages/backend/src/server/api/endpoints/federation/following.ts @@ -50,7 +50,8 @@ export default class extends Endpoint { // eslint- ) { super(meta, paramDef, async (ps, me) => { const query = this.queryService.makePaginationQuery(this.followingsRepository.createQueryBuilder('following'), ps.sinceId, ps.untilId, ps.sinceDate, ps.untilDate) - .andWhere('following.followerHost = :host', { host: ps.host }); + .andWhere('following.followerHost = :host', { host: ps.host }) + .andWhere('following.isFollowerSuspended = false'); const followings = await query .limit(ps.limit) diff --git a/packages/backend/src/server/api/endpoints/federation/stats.ts b/packages/backend/src/server/api/endpoints/federation/stats.ts index 69900bff9a..3093aa1e86 100644 --- a/packages/backend/src/server/api/endpoints/federation/stats.ts +++ b/packages/backend/src/server/api/endpoints/federation/stats.ts @@ -94,11 +94,13 @@ export default class extends Endpoint { // eslint- this.followingsRepository.count({ where: { followeeHost: Not(IsNull()), + isFollowerSuspended: false, }, }), this.followingsRepository.count({ where: { followerHost: Not(IsNull()), + isFollowerSuspended: false, }, }), ]); diff --git a/packages/backend/src/server/api/endpoints/users/followers.ts b/packages/backend/src/server/api/endpoints/users/followers.ts index 84c4c80d01..3afba603a2 100644 --- a/packages/backend/src/server/api/endpoints/users/followers.ts +++ b/packages/backend/src/server/api/endpoints/users/followers.ts @@ -125,6 +125,7 @@ export default class extends Endpoint { // eslint- where: { followeeId: user.id, followerId: me.id, + isFollowerSuspended: false, }, }); if (!isFollowing) { @@ -136,6 +137,7 @@ export default class extends Endpoint { // eslint- const query = this.queryService.makePaginationQuery(this.followingsRepository.createQueryBuilder('following'), ps.sinceId, ps.untilId, ps.sinceDate, ps.untilDate) .andWhere('following.followeeId = :userId', { userId: user.id }) + .andWhere('following.isFollowerSuspended = false') .innerJoinAndSelect('following.follower', 'follower'); const followings = await query diff --git a/packages/backend/src/server/api/endpoints/users/following.ts b/packages/backend/src/server/api/endpoints/users/following.ts index 047f9a053b..fb85106e11 100644 --- a/packages/backend/src/server/api/endpoints/users/following.ts +++ b/packages/backend/src/server/api/endpoints/users/following.ts @@ -133,6 +133,7 @@ export default class extends Endpoint { // eslint- where: { followeeId: user.id, followerId: me.id, + isFollowerSuspended: false, }, }); if (!isFollowing) { @@ -144,6 +145,7 @@ export default class extends Endpoint { // eslint- const query = this.queryService.makePaginationQuery(this.followingsRepository.createQueryBuilder('following'), ps.sinceId, ps.untilId, ps.sinceDate, ps.untilDate) .andWhere('following.followerId = :userId', { userId: user.id }) + .andWhere('following.isFollowerSuspended = false') .innerJoinAndSelect('following.followee', 'followee'); if (ps.birthday) { diff --git a/packages/backend/src/server/api/endpoints/users/recommendation.ts b/packages/backend/src/server/api/endpoints/users/recommendation.ts index 769a72d7a1..3ef7848ebb 100644 --- a/packages/backend/src/server/api/endpoints/users/recommendation.ts +++ b/packages/backend/src/server/api/endpoints/users/recommendation.ts @@ -68,7 +68,8 @@ export default class extends Endpoint { // eslint- const followingQuery = this.followingsRepository.createQueryBuilder('following') .select('following.followeeId') - .where('following.followerId = :followerId', { followerId: me.id }); + .where('following.followerId = :followerId', { followerId: me.id }) + .andWhere('following.isFollowerSuspended = false'); query .andWhere(`user.id NOT IN (${ followingQuery.getQuery() })`);