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),
]);
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({

View file

@ -183,7 +183,7 @@ export class UserEntityService implements OnModuleInit {
public isRemoteUser = isRemoteUser;
@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 [
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<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 [
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<string, string>,
instances?: Map<string, MiInstance | null>,
securityKeyCounts?: Map<string, number>,
myFollowings?: Map<string, Omit<MiFollowing, 'isFollowerHibernated'>>,
},
): Promise<Packed<S>> {
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<RolePolicies> | 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<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
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(

View file

@ -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,

View file

@ -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,

View file

@ -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

View file

@ -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;
};