From 455be9e197e2b8c3000d80370fdf5f855bd5ea4e Mon Sep 17 00:00:00 2001 From: Hazelnoot Date: Sat, 26 Jul 2025 22:04:11 -0400 Subject: [PATCH] replace note.isSilenced with user.isSilencedForMe --- .../src/core/entities/NoteEntityService.ts | 16 +------ .../src/core/entities/UserEntityService.ts | 43 ++++++++++++++----- .../backend/src/models/json-schema/note.ts | 4 -- .../backend/src/models/json-schema/user.ts | 4 ++ .../frontend/src/utility/check-word-mute.ts | 2 +- packages/misskey-js/src/autogen/types.ts | 2 +- 6 files changed, 40 insertions(+), 31 deletions(-) diff --git a/packages/backend/src/core/entities/NoteEntityService.ts b/packages/backend/src/core/entities/NoteEntityService.ts index 368586d2fb..3d329684ea 100644 --- a/packages/backend/src/core/entities/NoteEntityService.ts +++ b/packages/backend/src/core/entities/NoteEntityService.ts @@ -642,26 +642,13 @@ export class NoteEntityService implements OnModuleInit { .getExists() : false), ]); - const packedUser = packedUsers?.get(note.userId) ?? this.userEntityService.pack(note.user ?? note.userId, me); - const isSilenced = Promise.resolve(packedUser).then(async u => { - if (!u.isSilenced && !u.instance?.isSilenced) return false; - if (note.userId === meId) return false; - - if (meId) { - const followings = opts._hint_?.userFollowings.get(meId) ?? await this.cacheService.userFollowingsCache.fetch(meId); - if (followings.has(note.userId)) return false; - } - - return true; - }); - const packed: Packed<'Note'> = await awaitAll({ id: note.id, threadId, createdAt: this.idService.parse(note.id).date.toISOString(), updatedAt: note.updatedAt ? note.updatedAt.toISOString() : undefined, userId: note.userId, - user: packedUser, + user: packedUsers?.get(note.userId) ?? this.userEntityService.pack(note.user ?? note.userId, me), text: text, cw: note.cw, mandatoryCW: note.mandatoryCW, @@ -702,7 +689,6 @@ export class NoteEntityService implements OnModuleInit { isMutingNote: mutedNotes.has(note.id), isFavorited, isRenoted, - isSilenced, ...(meId && Object.keys(reactions).length > 0 ? { myReaction: this.populateMyReaction({ diff --git a/packages/backend/src/core/entities/UserEntityService.ts b/packages/backend/src/core/entities/UserEntityService.ts index af25300944..a8667b4469 100644 --- a/packages/backend/src/core/entities/UserEntityService.ts +++ b/packages/backend/src/core/entities/UserEntityService.ts @@ -183,7 +183,7 @@ export class UserEntityService implements OnModuleInit { public isRemoteUser = isRemoteUser; @bindThis - public async getRelation(me: MiUser['id'], target: MiUser['id']): Promise { + public async getRelation(me: MiUser['id'], target: MiUser['id'], hint?: { myFollowings?: Map> }): Promise { const [ following, isFollowed, @@ -197,7 +197,9 @@ export class UserEntityService implements OnModuleInit { memo, mutedInstances, ] = await Promise.all([ - this.cacheService.userFollowingsCache.fetch(me).then(f => f.get(target) ?? null), + hint?.myFollowings + ? (hint.myFollowings.get(target) ?? null) + : this.cacheService.userFollowingsCache.fetch(me).then(f => f.get(target) ?? null), this.cacheService.userFollowingsCache.fetch(target).then(f => f.has(me)), this.followRequestsRepository.exists({ where: { @@ -248,7 +250,8 @@ export class UserEntityService implements OnModuleInit { } @bindThis - public async getRelations(me: MiUser['id'], targets: MiUser['id'][]): Promise> { + public async getRelations(me: MiUser['id'], targets: MiUser['id'][], hint?: { myFollowings?: Map> }): Promise> { + // noinspection ES6MissingAwait const [ myFollowing, myFollowers, @@ -262,7 +265,7 @@ export class UserEntityService implements OnModuleInit { memos, mutedInstances, ] = await Promise.all([ - this.cacheService.userFollowingsCache.fetch(me), + hint?.myFollowings ?? this.cacheService.userFollowingsCache.fetch(me), this.cacheService.userFollowersCache.fetch(me), this.followRequestsRepository.createQueryBuilder('f') .select('f.followeeId') @@ -432,6 +435,7 @@ export class UserEntityService implements OnModuleInit { userIdsByUri?: Map, instances?: Map, securityKeyCounts?: Map, + myFollowings?: Map>, }, ): Promise> { const opts = Object.assign({ @@ -479,12 +483,14 @@ export class UserEntityService implements OnModuleInit { ? (opts.userProfile ?? user.userProfile ?? await this.userProfilesRepository.findOneByOrFail({ userId: user.id })) : null; + const myFollowings = opts.myFollowings ?? (meId ? await this.cacheService.userFollowingsCache.fetch(meId) : undefined); + let relation: UserRelation | null = null; if (meId && !isMe && isDetailed) { if (opts.userRelations) { relation = opts.userRelations.get(user.id) ?? null; } else { - relation = await this.getRelation(meId, user.id); + relation = await this.getRelation(meId, user.id, { myFollowings }); } } @@ -537,6 +543,14 @@ export class UserEntityService implements OnModuleInit { let fetchPoliciesPromise: Promise | null = null; const fetchPolicies = () => fetchPoliciesPromise ??= this.roleService.getUserPolicies(user); + const instancePromise = Promise.resolve(user.host + ? opts.instances?.has(user.host) + ? opts.instances.get(user.host) + : this.federatedInstanceService.fetch(user.host) + : null); + + const bypassSilence = isMe || (meId && myFollowings ? myFollowings.has(meId) : false); + const packed = { id: user.id, name: user.name, @@ -564,13 +578,14 @@ export class UserEntityService implements OnModuleInit { mandatoryCW: user.mandatoryCW, rejectQuotes: user.rejectQuotes, attributionDomains: user.attributionDomains, - isSilenced: user.isSilenced || fetchPolicies().then(r => !r.canPublicNote), + isSilenced: user.isSilenced, + isSilencedForMe: !bypassSilence && instancePromise.then(i => user.isSilenced || i?.isSilenced), speakAsCat: user.speakAsCat ?? false, approved: user.approved, requireSigninToViewContents: user.requireSigninToViewContents === false ? undefined : true, makeNotesFollowersOnlyBefore: user.makeNotesFollowersOnlyBefore ?? undefined, makeNotesHiddenBefore: user.makeNotesHiddenBefore ?? undefined, - instance: user.host ? Promise.resolve(opts.instances?.has(user.host) ? opts.instances.get(user.host) : this.federatedInstanceService.fetch(user.host)).then(instance => instance ? { + instance: instancePromise.then(instance => instance ? { name: instance.name, softwareName: instance.softwareName, softwareVersion: instance.softwareVersion, @@ -579,7 +594,7 @@ export class UserEntityService implements OnModuleInit { themeColor: instance.themeColor, isSilenced: instance.isSilenced, mandatoryCW: instance.mandatoryCW, - } : undefined) : undefined, + } : undefined), followersCount: followersCount ?? 0, followingCount: followingCount ?? 0, notesCount: user.notesCount, @@ -783,14 +798,20 @@ export class UserEntityService implements OnModuleInit { // -- 実行者の有無や指定スキーマの種別によって要否が異なる値群を取得 - const [profilesMap, userMemos, userRelations, pinNotes, userIdsByUri, instances, securityKeyCounts] = await Promise.all([ + const myFollowingsPromise: Promise> | undefined> = meId + ? this.cacheService.userFollowingsCache.fetch(meId) + : Promise.resolve(undefined); + + const [profilesMap, userMemos, userRelations, pinNotes, userIdsByUri, instances, securityKeyCounts, myFollowings] = await Promise.all([ // profilesMap this.cacheService.userProfileCache.fetchMany(_profilesToFetch).then(profiles => new Map(profiles.concat(_profilesFromUsers))), // userMemos isDetailed && meId ? this.userMemosRepository.findBy({ userId: meId }) .then(memos => new Map(memos.map(memo => [memo.targetUserId, memo.memo]))) : new Map(), // userRelations - isDetailed && meId ? this.getRelations(meId, _userIds) : new Map(), + meId + ? myFollowingsPromise.then(myFollowings => this.getRelations(meId, _userIds, { myFollowings })) + : new Map(), // pinNotes isDetailed ? this.userNotePiningsRepository.createQueryBuilder('pin') .where('pin.userId IN (:...userIds)', { userIds: _userIds }) @@ -834,6 +855,8 @@ export class UserEntityService implements OnModuleInit { .getRawMany<{ userId: string, userCount: number }>() .then(counts => new Map(counts.map(c => [c.userId, c.userCount]))) : undefined, // .pack will fetch the keys for the requesting user if it's in the _userIds + // myFollowings + myFollowingsPromise, ]); return Promise.all( diff --git a/packages/backend/src/models/json-schema/note.ts b/packages/backend/src/models/json-schema/note.ts index 5ebea6c740..6d3b9fe15e 100644 --- a/packages/backend/src/models/json-schema/note.ts +++ b/packages/backend/src/models/json-schema/note.ts @@ -193,10 +193,6 @@ export const packedNoteSchema = { type: 'boolean', optional: false, nullable: false, }, - isSilenced: { - type: 'boolean', - optional: false, nullable: false, - }, emojis: { type: 'object', optional: true, nullable: false, diff --git a/packages/backend/src/models/json-schema/user.ts b/packages/backend/src/models/json-schema/user.ts index 0c9f9f540a..54c4ba3516 100644 --- a/packages/backend/src/models/json-schema/user.ts +++ b/packages/backend/src/models/json-schema/user.ts @@ -184,6 +184,10 @@ export const packedUserLiteSchema = { type: 'boolean', nullable: false, optional: false, }, + isSilencedForMe: { + type: 'boolean', + nullable: false, optional: false, + }, requireSigninToViewContents: { type: 'boolean', nullable: false, optional: true, diff --git a/packages/frontend/src/utility/check-word-mute.ts b/packages/frontend/src/utility/check-word-mute.ts index 0bd888fb20..7569493a07 100644 --- a/packages/frontend/src/utility/check-word-mute.ts +++ b/packages/frontend/src/utility/check-word-mute.ts @@ -110,7 +110,7 @@ function getMutes(note: Misskey.entities.Note, withHardMute: boolean, overrides: const hardMuted = override.hardMuted ?? (!isMe && withHardMute && isHardMuted(note)); const softMutedWords = override.softMutedWords ?? (isMe ? [] : isSoftMuted(note)); const sensitiveMuted = override.sensitiveMuted ?? isSensitiveMuted(note); - const isSilenced = override.isSilenced ?? note.isSilenced; + const isSilenced = override.isSilenced ?? note.user.isSilencedForMe; const threadMuted = override.threadMuted ?? (!isMe && note.isMutingThread); const noteMuted = override.noteMuted ?? (!isMe && note.isMutingNote); const noteMandatoryCW = override.noteMandatoryCW !== undefined diff --git a/packages/misskey-js/src/autogen/types.ts b/packages/misskey-js/src/autogen/types.ts index 569b91158c..92a884411c 100644 --- a/packages/misskey-js/src/autogen/types.ts +++ b/packages/misskey-js/src/autogen/types.ts @@ -4307,6 +4307,7 @@ export type components = { isCat?: boolean; speakAsCat?: boolean; isSilenced: boolean; + isSilencedForMe: boolean; requireSigninToViewContents?: boolean; makeNotesFollowersOnlyBefore?: number | null; makeNotesHiddenBefore?: number | null; @@ -4731,7 +4732,6 @@ export type components = { isMutingNote: boolean; isFavorited: boolean; isRenoted: boolean; - isSilenced: boolean; emojis?: { [key: string]: string; };