diff --git a/locales/index.d.ts b/locales/index.d.ts
index 303f5df9c5..6a9d9f294e 100644
--- a/locales/index.d.ts
+++ b/locales/index.d.ts
@@ -12092,6 +12092,10 @@ export interface Locale extends ILocale {
* {name} said something in a muted thread
*/
"userSaysSomethingInMutedThread": ParameterizedString<"name">;
+ /**
+ * {name} has been silenced by {host} staff
+ */
+ "silencedUserSaysSomething": ParameterizedString<"name" | "host">;
/**
* {name} is flagged: "{cw}"
*/
diff --git a/packages/backend/src/core/WebhookTestService.ts b/packages/backend/src/core/WebhookTestService.ts
index 96b06ac0c2..5fabe2052d 100644
--- a/packages/backend/src/core/WebhookTestService.ts
+++ b/packages/backend/src/core/WebhookTestService.ts
@@ -409,6 +409,7 @@ export class WebhookTestService {
isMutingNote: false,
isFavorited: false,
isRenoted: false,
+ isSilenced: false,
visibility: note.visibility,
mentions: note.mentions,
visibleUserIds: note.visibleUserIds,
diff --git a/packages/backend/src/core/entities/NoteEntityService.ts b/packages/backend/src/core/entities/NoteEntityService.ts
index 3d329684ea..9df6e909a6 100644
--- a/packages/backend/src/core/entities/NoteEntityService.ts
+++ b/packages/backend/src/core/entities/NoteEntityService.ts
@@ -642,13 +642,26 @@ 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 ?? 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: packedUsers?.get(note.userId) ?? this.userEntityService.pack(note.user ?? note.userId, me),
+ user: packedUser,
text: text,
cw: note.cw,
mandatoryCW: note.mandatoryCW,
@@ -689,6 +702,7 @@ 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/models/json-schema/note.ts b/packages/backend/src/models/json-schema/note.ts
index 6d3b9fe15e..5ebea6c740 100644
--- a/packages/backend/src/models/json-schema/note.ts
+++ b/packages/backend/src/models/json-schema/note.ts
@@ -193,6 +193,10 @@ 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/frontend/src/components/SkMutedNote.vue b/packages/frontend/src/components/SkMutedNote.vue
index 05a1273238..fac948a987 100644
--- a/packages/frontend/src/components/SkMutedNote.vue
+++ b/packages/frontend/src/components/SkMutedNote.vue
@@ -47,6 +47,16 @@ Displays a placeholder for a muted note.
+
+
+
+
+
+
+ {{ host }}
+
+
+
diff --git a/packages/frontend/src/utility/check-word-mute.ts b/packages/frontend/src/utility/check-word-mute.ts
index 9406004312..c626cb48bf 100644
--- a/packages/frontend/src/utility/check-word-mute.ts
+++ b/packages/frontend/src/utility/check-word-mute.ts
@@ -16,7 +16,7 @@ export interface Mute {
softMutedWords?: string[];
sensitiveMuted?: boolean;
- isSensitive?: boolean;
+ isSilenced?: boolean;
threadMuted?: boolean;
noteMuted?: boolean;
@@ -110,6 +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 threadMuted = override.threadMuted ?? (!isMe && note.isMutingThread);
const noteMuted = override.noteMuted ?? (!isMe && note.isMutingNote);
const noteMandatoryCW = override.noteMandatoryCW !== undefined
@@ -126,7 +127,7 @@ function getMutes(note: Misskey.entities.Note, withHardMute: boolean, overrides:
const hasMute = hardMuted || softMutedWords.length > 0 || sensitiveMuted || threadMuted || noteMuted || !!noteMandatoryCW || !!userMandatoryCW || !!instanceMandatoryCW;
- return { hasMute, hardMuted, softMutedWords, sensitiveMuted, threadMuted, noteMuted, noteMandatoryCW, userMandatoryCW, instanceMandatoryCW };
+ return { hasMute, hardMuted, softMutedWords, sensitiveMuted, isSilenced, threadMuted, noteMuted, noteMandatoryCW, userMandatoryCW, instanceMandatoryCW };
}
function isHardMuted(note: Misskey.entities.Note): boolean {
diff --git a/packages/misskey-js/src/autogen/types.ts b/packages/misskey-js/src/autogen/types.ts
index ead1ca0c27..569b91158c 100644
--- a/packages/misskey-js/src/autogen/types.ts
+++ b/packages/misskey-js/src/autogen/types.ts
@@ -4731,6 +4731,7 @@ export type components = {
isMutingNote: boolean;
isFavorited: boolean;
isRenoted: boolean;
+ isSilenced: boolean;
emojis?: {
[key: string]: string;
};
diff --git a/sharkey-locales/en-US.yml b/sharkey-locales/en-US.yml
index f3e3951a7b..ddedfc92ef 100644
--- a/sharkey-locales/en-US.yml
+++ b/sharkey-locales/en-US.yml
@@ -35,6 +35,7 @@ muteNote: "Mute note"
unmuteNote: "Unmute note"
userSaysSomethingInMutedNote: "{name} said something in a muted post"
userSaysSomethingInMutedThread: "{name} said something in a muted thread"
+silencedUserSaysSomething: "{name} has been silenced by {host} staff"
userIsFlaggedAs: "{name} is flagged: \"{cw}\""
noteIsFlaggedAs: "Note is flagged: \"{cw}\""
instanceIsFlaggedAs: "{name} is flagged: \"{cw}\""