diff --git a/locales/en-US.yml b/locales/en-US.yml
index f9d4d23f02..6c22e0066a 100644
--- a/locales/en-US.yml
+++ b/locales/en-US.yml
@@ -197,6 +197,7 @@ perHour: "Per Hour"
perDay: "Per Day"
stopActivityDelivery: "Stop sending activities"
blockThisInstance: "Block this instance"
+silenceThisInstance: "Silence this instance"
operations: "Operations"
software: "Software"
version: "Version"
@@ -218,10 +219,13 @@ clearCachedFilesConfirm: "Are you sure that you want to delete all cached remote
blockedInstances: "Blocked Instances"
blockedInstancesDescription: "List the hostnames of the instances that you want to\
\ block. Listed instances will no longer be able to communicate with this instance."
+silencedInstances: "Silenced Instances"
+silencedInstancesDescription: "List the hostnames of the instances that you want to\
+ \ silence. Accounts in the listed instances are treated as \"Silenced\", can only make follow requests, and cannot mention local accounts if not followed. This will not affect the blocked instances."
hiddenTags: "Hidden Hashtags"
hiddenTagsDescription: "List the hashtags (without the #) of the hashtags you wish\
\ to hide from trending and explore. Hidden hashtags are still discoverable via\
- \ other means."
+ \ other means. Blocked instances are not affected even if listed here."
muteAndBlock: "Mutes and Blocks"
mutedUsers: "Muted users"
blockedUsers: "Blocked users"
@@ -829,7 +833,7 @@ active: "Active"
offline: "Offline"
notRecommended: "Not recommended"
botProtection: "Bot Protection"
-instanceBlocking: "Blocked Instances"
+instanceBlocking: "Blocked/Silenced Instances"
selectAccount: "Select account"
switchAccount: "Switch account"
enabled: "Enabled"
diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml
index 466212ba21..7db2a7c823 100644
--- a/locales/ja-JP.yml
+++ b/locales/ja-JP.yml
@@ -183,6 +183,7 @@ perHour: "1時間ごと"
perDay: "1日ごと"
stopActivityDelivery: "アクティビティの配送を停止"
blockThisInstance: "このインスタンスをブロック"
+silenceThisInstance: "このインスタンスをサイレンス"
operations: "操作"
software: "ソフトウェア"
version: "バージョン"
@@ -202,6 +203,8 @@ clearCachedFiles: "キャッシュをクリア"
clearCachedFilesConfirm: "キャッシュされたリモートファイルをすべて削除しますか?"
blockedInstances: "ブロックしたインスタンス"
blockedInstancesDescription: "ブロックしたいインスタンスのホストを改行で区切って設定します。ブロックされたインスタンスは、このインスタンスとやり取りできなくなります。"
+silencedInstances: "サイレンスしたインスタンス"
+silencedInstancesDescription: "サイレンスしたいインスタンスのホストを改行で区切って設定します。サイレンスされたインスタンスに所属するアカウントはすべて「サイレンス」として扱われ、フォローがすべてリクエストになり、フォロワーでないローカルアカウントにはメンションできなくなります。ブロックしたインスタンスには影響しません。"
muteAndBlock: "ミュートとブロック"
mutedUsers: "ミュートしたユーザー"
blockedUsers: "ブロックしたユーザー"
@@ -768,7 +771,7 @@ active: "アクティブ"
offline: "オフライン"
notRecommended: "非推奨"
botProtection: "Botプロテクション"
-instanceBlocking: "インスタンスブロック"
+instanceBlocking: "インスタンスブロック・サイレンス"
selectAccount: "アカウントを選択"
switchAccount: "アカウントを切り替え"
enabled: "有効"
diff --git a/packages/backend/src/server/api/endpoints/admin/update-meta.ts b/packages/backend/src/server/api/endpoints/admin/update-meta.ts
index 7f92e5e29e..60a9e85a30 100644
--- a/packages/backend/src/server/api/endpoints/admin/update-meta.ts
+++ b/packages/backend/src/server/api/endpoints/admin/update-meta.ts
@@ -231,7 +231,7 @@ export default define(meta, paramDef, async (ps, me) => {
set.silencedHosts = ps.silencedHosts.sort().filter((h) => {
const lv = lastValue;
lastValue = h;
- return h !== "" && h !== lv;
+ return h !== "" && h !== lv && !set.blockedHosts?.includes(h);
});
}
diff --git a/packages/client/src/pages/instance-info.vue b/packages/client/src/pages/instance-info.vue
index 5c81473516..7aeb2cd1c0 100644
--- a/packages/client/src/pages/instance-info.vue
+++ b/packages/client/src/pages/instance-info.vue
@@ -98,6 +98,14 @@
@update:modelValue="toggleBlock"
>{{ i18n.ts.blockThisInstance }}
+ {{
+ i18n.ts.silenceThisInstance
+ }}
(null);
let instance = $ref(null);
let suspended = $ref(false);
let isBlocked = $ref(false);
+let isSilenced = $ref(false);
let faviconUrl = $ref(null);
const usersPagination = {
@@ -387,7 +398,7 @@ const usersPagination = {
};
async function init() {
- meta = await os.api("admin/meta");
+ meta = (await os.api("admin/meta")) as AugmentedInstanceMetadata;
}
async function fetch() {
@@ -396,6 +407,7 @@ async function fetch() {
})) as AugmentedInstance;
suspended = instance.isSuspended;
isBlocked = instance.isBlocked;
+ isSilenced = instance.isSilenced;
faviconUrl =
getProxiedImageUrlNullable(instance.faviconUrl, "preview") ??
getProxiedImageUrlNullable(instance.iconUrl, "preview");
@@ -417,6 +429,22 @@ async function toggleBlock() {
});
}
+async function toggleSilence() {
+ if (meta == null) return;
+ if (!instance) {
+ throw new Error(`Instance info not loaded`);
+ }
+ let silencedHosts: string[];
+ if (isSilenced) {
+ silencedHosts = meta.silencedHosts.concat([instance.host]);
+ } else {
+ silencedHosts = meta.silencedHosts.filter((x) => x !== instance!.host);
+ }
+ await os.api("admin/update-meta", {
+ silencedHosts,
+ });
+}
+
async function toggleSuspend(v) {
await os.api("admin/federation/update-instance", {
host: instance.host,