replace note.isSilenced with user.isSilencedForMe

This commit is contained in:
Hazelnoot 2025-07-26 22:04:11 -04:00
parent b76bb672d9
commit 455be9e197
6 changed files with 40 additions and 31 deletions

View file

@ -642,26 +642,13 @@ export class NoteEntityService implements OnModuleInit {
.getExists() : false), .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({ const packed: Packed<'Note'> = await awaitAll({
id: note.id, id: note.id,
threadId, threadId,
createdAt: this.idService.parse(note.id).date.toISOString(), createdAt: this.idService.parse(note.id).date.toISOString(),
updatedAt: note.updatedAt ? note.updatedAt.toISOString() : undefined, updatedAt: note.updatedAt ? note.updatedAt.toISOString() : undefined,
userId: note.userId, userId: note.userId,
user: packedUser, user: packedUsers?.get(note.userId) ?? this.userEntityService.pack(note.user ?? note.userId, me),
text: text, text: text,
cw: note.cw, cw: note.cw,
mandatoryCW: note.mandatoryCW, mandatoryCW: note.mandatoryCW,
@ -702,7 +689,6 @@ export class NoteEntityService implements OnModuleInit {
isMutingNote: mutedNotes.has(note.id), isMutingNote: mutedNotes.has(note.id),
isFavorited, isFavorited,
isRenoted, isRenoted,
isSilenced,
...(meId && Object.keys(reactions).length > 0 ? { ...(meId && Object.keys(reactions).length > 0 ? {
myReaction: this.populateMyReaction({ myReaction: this.populateMyReaction({

View file

@ -183,7 +183,7 @@ export class UserEntityService implements OnModuleInit {
public isRemoteUser = isRemoteUser; public isRemoteUser = isRemoteUser;
@bindThis @bindThis
public async getRelation(me: MiUser['id'], target: MiUser['id']): Promise<UserRelation> { public async getRelation(me: MiUser['id'], target: MiUser['id'], hint?: { myFollowings?: Map<string, Omit<MiFollowing, 'isFollowerHibernated'>> }): Promise<UserRelation> {
const [ const [
following, following,
isFollowed, isFollowed,
@ -197,7 +197,9 @@ export class UserEntityService implements OnModuleInit {
memo, memo,
mutedInstances, mutedInstances,
] = await Promise.all([ ] = 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.cacheService.userFollowingsCache.fetch(target).then(f => f.has(me)),
this.followRequestsRepository.exists({ this.followRequestsRepository.exists({
where: { where: {
@ -248,7 +250,8 @@ export class UserEntityService implements OnModuleInit {
} }
@bindThis @bindThis
public async getRelations(me: MiUser['id'], targets: MiUser['id'][]): Promise<Map<MiUser['id'], UserRelation>> { public async getRelations(me: MiUser['id'], targets: MiUser['id'][], hint?: { myFollowings?: Map<string, Omit<MiFollowing, 'isFollowerHibernated'>> }): Promise<Map<MiUser['id'], UserRelation>> {
// noinspection ES6MissingAwait
const [ const [
myFollowing, myFollowing,
myFollowers, myFollowers,
@ -262,7 +265,7 @@ export class UserEntityService implements OnModuleInit {
memos, memos,
mutedInstances, mutedInstances,
] = await Promise.all([ ] = await Promise.all([
this.cacheService.userFollowingsCache.fetch(me), hint?.myFollowings ?? this.cacheService.userFollowingsCache.fetch(me),
this.cacheService.userFollowersCache.fetch(me), this.cacheService.userFollowersCache.fetch(me),
this.followRequestsRepository.createQueryBuilder('f') this.followRequestsRepository.createQueryBuilder('f')
.select('f.followeeId') .select('f.followeeId')
@ -432,6 +435,7 @@ export class UserEntityService implements OnModuleInit {
userIdsByUri?: Map<string, string>, userIdsByUri?: Map<string, string>,
instances?: Map<string, MiInstance | null>, instances?: Map<string, MiInstance | null>,
securityKeyCounts?: Map<string, number>, securityKeyCounts?: Map<string, number>,
myFollowings?: Map<string, Omit<MiFollowing, 'isFollowerHibernated'>>,
}, },
): Promise<Packed<S>> { ): Promise<Packed<S>> {
const opts = Object.assign({ const opts = Object.assign({
@ -479,12 +483,14 @@ export class UserEntityService implements OnModuleInit {
? (opts.userProfile ?? user.userProfile ?? await this.userProfilesRepository.findOneByOrFail({ userId: user.id })) ? (opts.userProfile ?? user.userProfile ?? await this.userProfilesRepository.findOneByOrFail({ userId: user.id }))
: null; : null;
const myFollowings = opts.myFollowings ?? (meId ? await this.cacheService.userFollowingsCache.fetch(meId) : undefined);
let relation: UserRelation | null = null; let relation: UserRelation | null = null;
if (meId && !isMe && isDetailed) { if (meId && !isMe && isDetailed) {
if (opts.userRelations) { if (opts.userRelations) {
relation = opts.userRelations.get(user.id) ?? null; relation = opts.userRelations.get(user.id) ?? null;
} else { } 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<RolePolicies> | null = null; let fetchPoliciesPromise: Promise<RolePolicies> | null = null;
const fetchPolicies = () => fetchPoliciesPromise ??= this.roleService.getUserPolicies(user); 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 = { const packed = {
id: user.id, id: user.id,
name: user.name, name: user.name,
@ -564,13 +578,14 @@ export class UserEntityService implements OnModuleInit {
mandatoryCW: user.mandatoryCW, mandatoryCW: user.mandatoryCW,
rejectQuotes: user.rejectQuotes, rejectQuotes: user.rejectQuotes,
attributionDomains: user.attributionDomains, 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, speakAsCat: user.speakAsCat ?? false,
approved: user.approved, approved: user.approved,
requireSigninToViewContents: user.requireSigninToViewContents === false ? undefined : true, requireSigninToViewContents: user.requireSigninToViewContents === false ? undefined : true,
makeNotesFollowersOnlyBefore: user.makeNotesFollowersOnlyBefore ?? undefined, makeNotesFollowersOnlyBefore: user.makeNotesFollowersOnlyBefore ?? undefined,
makeNotesHiddenBefore: user.makeNotesHiddenBefore ?? 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, name: instance.name,
softwareName: instance.softwareName, softwareName: instance.softwareName,
softwareVersion: instance.softwareVersion, softwareVersion: instance.softwareVersion,
@ -579,7 +594,7 @@ export class UserEntityService implements OnModuleInit {
themeColor: instance.themeColor, themeColor: instance.themeColor,
isSilenced: instance.isSilenced, isSilenced: instance.isSilenced,
mandatoryCW: instance.mandatoryCW, mandatoryCW: instance.mandatoryCW,
} : undefined) : undefined, } : undefined),
followersCount: followersCount ?? 0, followersCount: followersCount ?? 0,
followingCount: followingCount ?? 0, followingCount: followingCount ?? 0,
notesCount: user.notesCount, 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<Map<string, Omit<MiFollowing, 'isFollowerHibernated'>> | undefined> = meId
? this.cacheService.userFollowingsCache.fetch(meId)
: Promise.resolve(undefined);
const [profilesMap, userMemos, userRelations, pinNotes, userIdsByUri, instances, securityKeyCounts, myFollowings] = await Promise.all([
// profilesMap // profilesMap
this.cacheService.userProfileCache.fetchMany(_profilesToFetch).then(profiles => new Map(profiles.concat(_profilesFromUsers))), this.cacheService.userProfileCache.fetchMany(_profilesToFetch).then(profiles => new Map(profiles.concat(_profilesFromUsers))),
// userMemos // userMemos
isDetailed && meId ? this.userMemosRepository.findBy({ userId: meId }) isDetailed && meId ? this.userMemosRepository.findBy({ userId: meId })
.then(memos => new Map(memos.map(memo => [memo.targetUserId, memo.memo]))) : new Map(), .then(memos => new Map(memos.map(memo => [memo.targetUserId, memo.memo]))) : new Map(),
// userRelations // userRelations
isDetailed && meId ? this.getRelations(meId, _userIds) : new Map(), meId
? myFollowingsPromise.then(myFollowings => this.getRelations(meId, _userIds, { myFollowings }))
: new Map(),
// pinNotes // pinNotes
isDetailed ? this.userNotePiningsRepository.createQueryBuilder('pin') isDetailed ? this.userNotePiningsRepository.createQueryBuilder('pin')
.where('pin.userId IN (:...userIds)', { userIds: _userIds }) .where('pin.userId IN (:...userIds)', { userIds: _userIds })
@ -834,6 +855,8 @@ export class UserEntityService implements OnModuleInit {
.getRawMany<{ userId: string, userCount: number }>() .getRawMany<{ userId: string, userCount: number }>()
.then(counts => new Map(counts.map(c => [c.userId, c.userCount]))) .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 : undefined, // .pack will fetch the keys for the requesting user if it's in the _userIds
// myFollowings
myFollowingsPromise,
]); ]);
return Promise.all( return Promise.all(

View file

@ -193,10 +193,6 @@ export const packedNoteSchema = {
type: 'boolean', type: 'boolean',
optional: false, nullable: false, optional: false, nullable: false,
}, },
isSilenced: {
type: 'boolean',
optional: false, nullable: false,
},
emojis: { emojis: {
type: 'object', type: 'object',
optional: true, nullable: false, optional: true, nullable: false,

View file

@ -184,6 +184,10 @@ export const packedUserLiteSchema = {
type: 'boolean', type: 'boolean',
nullable: false, optional: false, nullable: false, optional: false,
}, },
isSilencedForMe: {
type: 'boolean',
nullable: false, optional: false,
},
requireSigninToViewContents: { requireSigninToViewContents: {
type: 'boolean', type: 'boolean',
nullable: false, optional: true, nullable: false, optional: true,

View file

@ -110,7 +110,7 @@ function getMutes(note: Misskey.entities.Note, withHardMute: boolean, overrides:
const hardMuted = override.hardMuted ?? (!isMe && withHardMute && isHardMuted(note)); const hardMuted = override.hardMuted ?? (!isMe && withHardMute && isHardMuted(note));
const softMutedWords = override.softMutedWords ?? (isMe ? [] : isSoftMuted(note)); const softMutedWords = override.softMutedWords ?? (isMe ? [] : isSoftMuted(note));
const sensitiveMuted = override.sensitiveMuted ?? isSensitiveMuted(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 threadMuted = override.threadMuted ?? (!isMe && note.isMutingThread);
const noteMuted = override.noteMuted ?? (!isMe && note.isMutingNote); const noteMuted = override.noteMuted ?? (!isMe && note.isMutingNote);
const noteMandatoryCW = override.noteMandatoryCW !== undefined const noteMandatoryCW = override.noteMandatoryCW !== undefined

View file

@ -4307,6 +4307,7 @@ export type components = {
isCat?: boolean; isCat?: boolean;
speakAsCat?: boolean; speakAsCat?: boolean;
isSilenced: boolean; isSilenced: boolean;
isSilencedForMe: boolean;
requireSigninToViewContents?: boolean; requireSigninToViewContents?: boolean;
makeNotesFollowersOnlyBefore?: number | null; makeNotesFollowersOnlyBefore?: number | null;
makeNotesHiddenBefore?: number | null; makeNotesHiddenBefore?: number | null;
@ -4731,7 +4732,6 @@ export type components = {
isMutingNote: boolean; isMutingNote: boolean;
isFavorited: boolean; isFavorited: boolean;
isRenoted: boolean; isRenoted: boolean;
isSilenced: boolean;
emojis?: { emojis?: {
[key: string]: string; [key: string]: string;
}; };