summaryrefslogtreecommitdiff
path: root/packages
diff options
context:
space:
mode:
authorまっちゃてぃー <56515516+mattyatea@users.noreply.github.com>2023-10-16 20:11:27 +0900
committerGitHub <noreply@github.com>2023-10-16 20:11:27 +0900
commit5efd01ba70b37868f625e0acfc5c1c22d5df775c (patch)
treed042555298ef2beb8feb3db1cca2320c41657fb9 /packages
parentfix test (diff)
downloadsharkey-5efd01ba70b37868f625e0acfc5c1c22d5df775c.tar.gz
sharkey-5efd01ba70b37868f625e0acfc5c1c22d5df775c.tar.bz2
sharkey-5efd01ba70b37868f625e0acfc5c1c22d5df775c.zip
feat: サーバーサイレンス機能を追加 (#12031)
* feat : サーバーサイレンスを追加 * Update CHANGELOG.md * Update CHANGELOG.md * Update locale * Update instance-info.vue * update misskey-js.api.md * lint fix * migration fix * 既存のものを使うように * fix * 色々直した * Update packages/frontend/src/pages/admin/instance-block.vue * Update packages/frontend/src/pages/admin/instance-block.vue * Update packages/frontend/src/components/MkInstanceCardMini.vue * Update packages/backend/src/core/entities/InstanceEntityService.ts * Update packages/backend/src/core/entities/InstanceEntityService.ts * Update packages/backend/src/core/entities/InstanceEntityService.ts * Update packages/backend/src/core/UserFollowingService.ts * Update packages/backend/src/core/UserFollowingService.ts * fix: サイレンスされてるサーバーからの投稿は全部ホームにする * fix: undefinedでfalseを返すようにした --------- Co-authored-by: syuilo <Syuilotan@yahoo.co.jp>
Diffstat (limited to 'packages')
-rw-r--r--packages/backend/migration/1697247230117-InstanceSilence.js16
-rw-r--r--packages/backend/src/core/NoteCreateService.ts8
-rw-r--r--packages/backend/src/core/UserFollowingService.ts11
-rw-r--r--packages/backend/src/core/UtilityService.ts6
-rw-r--r--packages/backend/src/core/entities/InstanceEntityService.ts4
-rw-r--r--packages/backend/src/models/Meta.ts5
-rw-r--r--packages/backend/src/models/json-schema/federation-instance.ts5
-rw-r--r--packages/backend/src/server/api/endpoints/admin/meta.ts11
-rw-r--r--packages/backend/src/server/api/endpoints/admin/update-meta.ts56
-rw-r--r--packages/backend/src/server/api/endpoints/federation/instances.ts18
-rw-r--r--packages/frontend/src/components/MkInstanceCardMini.vue8
-rw-r--r--packages/frontend/src/pages/about.federation.vue3
-rw-r--r--packages/frontend/src/pages/admin/instance-block.vue25
-rw-r--r--packages/frontend/src/pages/instance-info.vue16
-rw-r--r--packages/misskey-js/etc/misskey-js.api.md4
-rw-r--r--packages/misskey-js/src/entities.ts2
16 files changed, 166 insertions, 32 deletions
diff --git a/packages/backend/migration/1697247230117-InstanceSilence.js b/packages/backend/migration/1697247230117-InstanceSilence.js
new file mode 100644
index 0000000000..5fdbca3b27
--- /dev/null
+++ b/packages/backend/migration/1697247230117-InstanceSilence.js
@@ -0,0 +1,16 @@
+/*
+ * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+export class InstanceSilence1697247230117 {
+ name = 'InstanceSilence1697247230117'
+
+ async up(queryRunner) {
+ await queryRunner.query(`ALTER TABLE "meta" ADD "silencedHosts" character varying(1024) array NOT NULL DEFAULT '{}'`);
+ }
+
+ async down(queryRunner) {
+ await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "silencedHosts"`);
+ }
+}
diff --git a/packages/backend/src/core/NoteCreateService.ts b/packages/backend/src/core/NoteCreateService.ts
index 400f1ec98c..a308e1aaa8 100644
--- a/packages/backend/src/core/NoteCreateService.ts
+++ b/packages/backend/src/core/NoteCreateService.ts
@@ -56,6 +56,7 @@ import { SearchService } from '@/core/SearchService.js';
import { FeaturedService } from '@/core/FeaturedService.js';
import { RedisTimelineService } from '@/core/RedisTimelineService.js';
import { nyaize } from '@/misc/nyaize.js';
+import { UtilityService } from '@/core/UtilityService.js';
type NotificationType = 'reply' | 'renote' | 'quote' | 'mention';
@@ -215,6 +216,7 @@ export class NoteCreateService implements OnApplicationShutdown {
private perUserNotesChart: PerUserNotesChart,
private activeUsersChart: ActiveUsersChart,
private instanceChart: InstanceChart,
+ private utilityService: UtilityService,
) { }
@bindThis
@@ -259,6 +261,12 @@ export class NoteCreateService implements OnApplicationShutdown {
}
}
+ const inSilencedInstance = this.utilityService.isSilencedHost((await this.metaService.fetch()).silencedHosts, user.host);
+
+ if (data.visibility === 'public' && inSilencedInstance && user.host !== null) {
+ data.visibility = 'home';
+ }
+
if (data.renote) {
switch (data.renote.visibility) {
case 'public':
diff --git a/packages/backend/src/core/UserFollowingService.ts b/packages/backend/src/core/UserFollowingService.ts
index f6d0c3a6d5..87484f0383 100644
--- a/packages/backend/src/core/UserFollowingService.ts
+++ b/packages/backend/src/core/UserFollowingService.ts
@@ -3,7 +3,7 @@
* SPDX-License-Identifier: AGPL-3.0-only
*/
-import { Inject, Injectable, OnModuleInit, forwardRef } from '@nestjs/common';
+import { Inject, Injectable, OnModuleInit } from '@nestjs/common';
import { ModuleRef } from '@nestjs/core';
import { IsNull } from 'typeorm';
import type { MiLocalUser, MiPartialLocalUser, MiPartialRemoteUser, MiRemoteUser, MiUser } from '@/models/User.js';
@@ -28,6 +28,7 @@ import { MetaService } from '@/core/MetaService.js';
import { CacheService } from '@/core/CacheService.js';
import type { Config } from '@/config.js';
import { AccountMoveService } from '@/core/AccountMoveService.js';
+import { UtilityService } from '@/core/UtilityService.js';
import Logger from '../logger.js';
const logger = new Logger('following/create');
@@ -71,6 +72,7 @@ export class UserFollowingService implements OnModuleInit {
private instancesRepository: InstancesRepository,
private cacheService: CacheService,
+ private utilityService: UtilityService,
private userEntityService: UserEntityService,
private idService: IdService,
private queueService: QueueService,
@@ -118,15 +120,16 @@ export class UserFollowingService implements OnModuleInit {
}
const followeeProfile = await this.userProfilesRepository.findOneByOrFail({ userId: followee.id });
-
// フォロー対象が鍵アカウントである or
// フォロワーがBotであり、フォロー対象がBotからのフォローに慎重である or
- // フォロワーがローカルユーザーであり、フォロー対象がリモートユーザーである
+ // フォロワーがローカルユーザーであり、フォロー対象がリモートユーザーである or
+ // フォロワーがローカルユーザーであり、フォロー対象がサイレンスされているサーバーである
// 上記のいずれかに当てはまる場合はすぐフォローせずにフォローリクエストを発行しておく
if (
followee.isLocked ||
(followeeProfile.carefulBot && follower.isBot) ||
- (this.userEntityService.isLocalUser(follower) && this.userEntityService.isRemoteUser(followee) && process.env.FORCE_FOLLOW_REMOTE_USER_FOR_TESTING !== 'true')
+ (this.userEntityService.isLocalUser(follower) && this.userEntityService.isRemoteUser(followee) && process.env.FORCE_FOLLOW_REMOTE_USER_FOR_TESTING !== 'true') ||
+ (this.userEntityService.isLocalUser(followee) && this.userEntityService.isRemoteUser(follower) && this.utilityService.isSilencedHost((await this.metaService.fetch()).silencedHosts, follower.host))
) {
let autoAccept = false;
diff --git a/packages/backend/src/core/UtilityService.ts b/packages/backend/src/core/UtilityService.ts
index d2d2776bd2..b95e41167b 100644
--- a/packages/backend/src/core/UtilityService.ts
+++ b/packages/backend/src/core/UtilityService.ts
@@ -36,6 +36,12 @@ export class UtilityService {
}
@bindThis
+ public isSilencedHost(silencedHosts: string[] | undefined, host: string | null): boolean {
+ if (!silencedHosts || host == null) return false;
+ return silencedHosts.some(x => `.${host.toLowerCase()}`.endsWith(`.${x}`));
+ }
+
+ @bindThis
public extractDbHost(uri: string): string {
const url = new URL(uri);
return this.toPuny(url.hostname);
diff --git a/packages/backend/src/core/entities/InstanceEntityService.ts b/packages/backend/src/core/entities/InstanceEntityService.ts
index 0e27e9df7f..9afe87eab7 100644
--- a/packages/backend/src/core/entities/InstanceEntityService.ts
+++ b/packages/backend/src/core/entities/InstanceEntityService.ts
@@ -3,9 +3,8 @@
* SPDX-License-Identifier: AGPL-3.0-only
*/
-import { Injectable } from '@nestjs/common';
+import { Inject, Injectable } from '@nestjs/common';
import type { Packed } from '@/misc/json-schema.js';
-import type { } from '@/models/Blocking.js';
import type { MiInstance } from '@/models/Instance.js';
import { MetaService } from '@/core/MetaService.js';
import { bindThis } from '@/decorators.js';
@@ -43,6 +42,7 @@ export class InstanceEntityService {
description: instance.description,
maintainerName: instance.maintainerName,
maintainerEmail: instance.maintainerEmail,
+ isSilenced: this.utilityService.isSilencedHost(meta.silencedHosts, instance.host),
iconUrl: instance.iconUrl,
faviconUrl: instance.faviconUrl,
themeColor: instance.themeColor,
diff --git a/packages/backend/src/models/Meta.ts b/packages/backend/src/models/Meta.ts
index d2bd0c26e9..23ae513ede 100644
--- a/packages/backend/src/models/Meta.ts
+++ b/packages/backend/src/models/Meta.ts
@@ -77,6 +77,11 @@ export class MiMeta {
public sensitiveWords: string[];
@Column('varchar', {
+ length: 1024, array: true, default: '{}',
+ })
+ public silencedHosts: string[];
+
+ @Column('varchar', {
length: 1024,
nullable: true,
})
diff --git a/packages/backend/src/models/json-schema/federation-instance.ts b/packages/backend/src/models/json-schema/federation-instance.ts
index ac07519f16..4ad84d02ff 100644
--- a/packages/backend/src/models/json-schema/federation-instance.ts
+++ b/packages/backend/src/models/json-schema/federation-instance.ts
@@ -93,6 +93,11 @@ export const packedFederationInstanceSchema = {
type: 'string',
optional: false, nullable: true,
},
+ isSilenced: {
+ type: "boolean",
+ optional: false,
+ nullable: false,
+ },
infoUpdatedAt: {
type: 'string',
optional: false, nullable: true,
diff --git a/packages/backend/src/server/api/endpoints/admin/meta.ts b/packages/backend/src/server/api/endpoints/admin/meta.ts
index 5a74456ab0..f294934344 100644
--- a/packages/backend/src/server/api/endpoints/admin/meta.ts
+++ b/packages/backend/src/server/api/endpoints/admin/meta.ts
@@ -105,6 +105,16 @@ export const meta = {
type: 'boolean',
optional: false, nullable: false,
},
+ silencedHosts: {
+ type: "array",
+ optional: true,
+ nullable: false,
+ items: {
+ type: "string",
+ optional: false,
+ nullable: false,
+ },
+ },
pinnedUsers: {
type: 'array',
optional: false, nullable: false,
@@ -367,6 +377,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
pinnedUsers: instance.pinnedUsers,
hiddenTags: instance.hiddenTags,
blockedHosts: instance.blockedHosts,
+ silencedHosts: instance.silencedHosts,
sensitiveWords: instance.sensitiveWords,
preservedUsernames: instance.preservedUsernames,
hcaptchaSecretKey: instance.hcaptchaSecretKey,
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 7db25e659f..72c4936c13 100644
--- a/packages/backend/src/server/api/endpoints/admin/update-meta.ts
+++ b/packages/backend/src/server/api/endpoints/admin/update-meta.ts
@@ -20,18 +20,26 @@ export const paramDef = {
type: 'object',
properties: {
disableRegistration: { type: 'boolean', nullable: true },
- pinnedUsers: { type: 'array', nullable: true, items: {
- type: 'string',
- } },
- hiddenTags: { type: 'array', nullable: true, items: {
- type: 'string',
- } },
- blockedHosts: { type: 'array', nullable: true, items: {
- type: 'string',
- } },
- sensitiveWords: { type: 'array', nullable: true, items: {
- type: 'string',
- } },
+ pinnedUsers: {
+ type: 'array', nullable: true, items: {
+ type: 'string',
+ },
+ },
+ hiddenTags: {
+ type: 'array', nullable: true, items: {
+ type: 'string',
+ },
+ },
+ blockedHosts: {
+ type: 'array', nullable: true, items: {
+ type: 'string',
+ },
+ },
+ sensitiveWords: {
+ type: 'array', nullable: true, items: {
+ type: 'string',
+ },
+ },
themeColor: { type: 'string', nullable: true, pattern: '^#[0-9a-fA-F]{6}$' },
mascotImageUrl: { type: 'string', nullable: true },
bannerUrl: { type: 'string', nullable: true },
@@ -67,9 +75,11 @@ export const paramDef = {
proxyAccountId: { type: 'string', format: 'misskey:id', nullable: true },
maintainerName: { type: 'string', nullable: true },
maintainerEmail: { type: 'string', nullable: true },
- langs: { type: 'array', items: {
- type: 'string',
- } },
+ langs: {
+ type: 'array', items: {
+ type: 'string',
+ },
+ },
summalyProxy: { type: 'string', nullable: true },
deeplAuthKey: { type: 'string', nullable: true },
deeplIsPro: { type: 'boolean' },
@@ -115,6 +125,13 @@ export const paramDef = {
perUserHomeTimelineCacheMax: { type: 'integer' },
perUserListTimelineCacheMax: { type: 'integer' },
notesPerOneAd: { type: 'integer' },
+ silencedHosts: {
+ type: 'array',
+ nullable: true,
+ items: {
+ type: 'string',
+ },
+ },
},
required: [],
} as const;
@@ -147,7 +164,14 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
if (Array.isArray(ps.sensitiveWords)) {
set.sensitiveWords = ps.sensitiveWords.filter(Boolean);
}
-
+ if (Array.isArray(ps.silencedHosts)) {
+ let lastValue = '';
+ set.silencedHosts = ps.silencedHosts.sort().filter((h) => {
+ const lv = lastValue;
+ lastValue = h;
+ return h !== '' && h !== lv && !set.blockedHosts?.includes(h);
+ });
+ }
if (ps.themeColor !== undefined) {
set.themeColor = ps.themeColor;
}
diff --git a/packages/backend/src/server/api/endpoints/federation/instances.ts b/packages/backend/src/server/api/endpoints/federation/instances.ts
index be73e5dbb8..c8beefa9c7 100644
--- a/packages/backend/src/server/api/endpoints/federation/instances.ts
+++ b/packages/backend/src/server/api/endpoints/federation/instances.ts
@@ -36,6 +36,7 @@ export const paramDef = {
blocked: { type: 'boolean', nullable: true },
notResponding: { type: 'boolean', nullable: true },
suspended: { type: 'boolean', nullable: true },
+ silenced: { type: "boolean", nullable: true },
federating: { type: 'boolean', nullable: true },
subscribing: { type: 'boolean', nullable: true },
publishing: { type: 'boolean', nullable: true },
@@ -102,6 +103,23 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
}
}
+ if (typeof ps.silenced === "boolean") {
+ const meta = await this.metaService.fetch(true);
+
+ if (ps.silenced) {
+ if (meta.silencedHosts.length === 0) {
+ return [];
+ }
+ query.andWhere("instance.host IN (:...silences)", {
+ silences: meta.silencedHosts,
+ });
+ } else if (meta.silencedHosts.length > 0) {
+ query.andWhere("instance.host NOT IN (:...silences)", {
+ silences: meta.silencedHosts,
+ });
+ }
+ }
+
if (typeof ps.federating === 'boolean') {
if (ps.federating) {
query.andWhere('((instance.followingCount > 0) OR (instance.followersCount > 0))');
diff --git a/packages/frontend/src/components/MkInstanceCardMini.vue b/packages/frontend/src/components/MkInstanceCardMini.vue
index de726e3aa4..e384b7a0bc 100644
--- a/packages/frontend/src/components/MkInstanceCardMini.vue
+++ b/packages/frontend/src/components/MkInstanceCardMini.vue
@@ -4,7 +4,7 @@ SPDX-License-Identifier: AGPL-3.0-only
-->
<template>
-<div :class="[$style.root, { yellow: instance.isNotResponding, red: instance.isBlocked, gray: instance.isSuspended }]">
+<div :class="[$style.root, { yellow: instance.isNotResponding, red: instance.isBlocked, gray: instance.isSuspended, blue: instance.isSilenced }]">
<img class="icon" :src="getInstanceIcon(instance)" alt="" loading="lazy"/>
<div class="body">
<span class="host">{{ instance.name ?? instance.host }}</span>
@@ -89,6 +89,12 @@ function getInstanceIcon(instance): string {
height: 30px;
}
+ &:global(.blue) {
+ --c: rgba(0, 42, 255, 0.15);
+ background-image: linear-gradient(45deg, var(--c) 16.67%, transparent 16.67%, transparent 50%, var(--c) 50%, var(--c) 66.67%, transparent 66.67%, transparent 100%);
+ background-size: 16px 16px;
+ }
+
&:global(.yellow) {
--c: rgb(255 196 0 / 15%);
background-image: linear-gradient(45deg, var(--c) 16.67%, transparent 16.67%, transparent 50%, var(--c) 50%, var(--c) 66.67%, transparent 66.67%, transparent 100%);
diff --git a/packages/frontend/src/pages/about.federation.vue b/packages/frontend/src/pages/about.federation.vue
index 2aa5af939b..333af93ef8 100644
--- a/packages/frontend/src/pages/about.federation.vue
+++ b/packages/frontend/src/pages/about.federation.vue
@@ -18,6 +18,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<option value="subscribing">{{ i18n.ts.subscribing }}</option>
<option value="publishing">{{ i18n.ts.publishing }}</option>
<option value="suspended">{{ i18n.ts.suspended }}</option>
+ <option value="silenced">{{ i18n.ts.silence }}</option>
<option value="blocked">{{ i18n.ts.blocked }}</option>
<option value="notResponding">{{ i18n.ts.notResponding }}</option>
</MkSelect>
@@ -75,6 +76,7 @@ const pagination = {
state === 'publishing' ? { publishing: true } :
state === 'suspended' ? { suspended: true } :
state === 'blocked' ? { blocked: true } :
+ state === 'silenced' ? { silenced: true } :
state === 'notResponding' ? { notResponding: true } :
{}),
})),
@@ -83,6 +85,7 @@ const pagination = {
function getStatus(instance) {
if (instance.isSuspended) return 'Suspended';
if (instance.isBlocked) return 'Blocked';
+ if (instance.isSilenced) return 'Silenced';
if (instance.isNotResponding) return 'Error';
return 'Alive';
}
diff --git a/packages/frontend/src/pages/admin/instance-block.vue b/packages/frontend/src/pages/admin/instance-block.vue
index 9a0f5e026b..259354b3d0 100644
--- a/packages/frontend/src/pages/admin/instance-block.vue
+++ b/packages/frontend/src/pages/admin/instance-block.vue
@@ -5,14 +5,17 @@ SPDX-License-Identifier: AGPL-3.0-only
<template>
<MkStickyContainer>
- <template #header><XHeader :actions="headerActions" :tabs="headerTabs"/></template>
+ <template #header><XHeader v-model:tab="tab" :actions="headerActions" :tabs="headerTabs"/></template>
<MkSpacer :contentMax="700" :marginMin="16" :marginMax="32">
<FormSuspense :p="init">
- <MkTextarea v-model="blockedHosts">
+ <MkTextarea v-if="tab === 'block'" v-model="blockedHosts">
<span>{{ i18n.ts.blockedInstances }}</span>
<template #caption>{{ i18n.ts.blockedInstancesDescription }}</template>
</MkTextarea>
-
+ <MkTextarea v-else-if="tab === 'silence'" v-model="silencedHosts" class="_formBlock">
+ <span>{{ i18n.ts.silencedInstances }}</span>
+ <template #caption>{{ i18n.ts.silencedInstancesDescription }}</template>
+ </MkTextarea>
<MkButton primary @click="save"><i class="ti ti-device-floppy"></i> {{ i18n.ts.save }}</MkButton>
</FormSuspense>
</MkSpacer>
@@ -20,7 +23,6 @@ SPDX-License-Identifier: AGPL-3.0-only
</template>
<script lang="ts" setup>
-import { } from 'vue';
import XHeader from './_header_.vue';
import MkButton from '@/components/MkButton.vue';
import MkTextarea from '@/components/MkTextarea.vue';
@@ -31,15 +33,20 @@ import { i18n } from '@/i18n.js';
import { definePageMetadata } from '@/scripts/page-metadata.js';
let blockedHosts: string = $ref('');
+let silencedHosts: string = $ref('');
+let tab = $ref('block');
async function init() {
const meta = await os.api('admin/meta');
blockedHosts = meta.blockedHosts.join('\n');
+ silencedHosts = meta.silencedHosts.join('\n');
}
function save() {
os.apiWithDialog('admin/update-meta', {
blockedHosts: blockedHosts.split('\n') || [],
+ silencedHosts: silencedHosts.split('\n') || [],
+
}).then(() => {
fetchInstance();
});
@@ -47,7 +54,15 @@ function save() {
const headerActions = $computed(() => []);
-const headerTabs = $computed(() => []);
+const headerTabs = $computed(() => [{
+ key: 'block',
+ title: i18n.ts.block,
+ icon: 'ti ti-ban',
+}, {
+ key: 'silence',
+ title: i18n.ts.silence,
+ icon: 'ti ti-eye-off',
+}]);
definePageMetadata({
title: i18n.ts.instanceBlocking,
diff --git a/packages/frontend/src/pages/instance-info.vue b/packages/frontend/src/pages/instance-info.vue
index 2285e4c88e..fb93637e00 100644
--- a/packages/frontend/src/pages/instance-info.vue
+++ b/packages/frontend/src/pages/instance-info.vue
@@ -36,7 +36,8 @@ SPDX-License-Identifier: AGPL-3.0-only
<div class="_gaps_s">
<MkSwitch v-model="suspended" :disabled="!instance" @update:modelValue="toggleSuspend">{{ i18n.ts.stopActivityDelivery }}</MkSwitch>
<MkSwitch v-model="isBlocked" :disabled="!meta || !instance" @update:modelValue="toggleBlock">{{ i18n.ts.blockThisInstance }}</MkSwitch>
- <MkButton @click="refreshMetadata"><i class="ti ti-refresh"></i> Refresh metadata</MkButton>
+ <MkSwitch v-model="isSilenced" :disabled="!meta || !instance" @update:modelValue="toggleSilenced">{{ i18n.ts.silenceThisInstance }}</MkSwitch>
+ <MkButton @click="refreshMetadata"><i class="ti ti-refresh"></i> Refresh metadata</MkButton>
</div>
</FormSection>
@@ -147,6 +148,7 @@ let meta = $ref<Misskey.entities.AdminInstanceMetadata | null>(null);
let instance = $ref<Misskey.entities.Instance | null>(null);
let suspended = $ref(false);
let isBlocked = $ref(false);
+let isSilenced = $ref(false);
let faviconUrl = $ref<string | null>(null);
const usersPagination = {
@@ -169,7 +171,8 @@ async function fetch(): Promise<void> {
});
suspended = instance.isSuspended;
isBlocked = instance.isBlocked;
- faviconUrl = getProxiedImageUrlNullable(instance.faviconUrl, 'preview') ?? getProxiedImageUrlNullable(instance.iconUrl, 'preview');
+ isSilenced = instance.isSilenced;
+ faviconUrl = getProxiedImageUrlNullable(instance.faviconUrl, 'preview') ?? getProxiedImageUrlNullable(instance.iconUrl, 'preview');
}
async function toggleBlock(): Promise<void> {
@@ -180,7 +183,14 @@ async function toggleBlock(): Promise<void> {
blockedHosts: isBlocked ? meta.blockedHosts.concat([host]) : meta.blockedHosts.filter(x => x !== host),
});
}
-
+async function toggleSilenced(): Promise<void> {
+ if (!meta) throw new Error('No meta?');
+ if (!instance) throw new Error('No instance?');
+ const { host } = instance;
+ await os.api('admin/update-meta', {
+ silencedHosts: isSilenced ? meta.silencedHosts.concat([host]) : meta.silencedHosts.filter(x => x !== host),
+ });
+}
async function toggleSuspend(): Promise<void> {
if (!instance) throw new Error('No instance?');
await os.api('admin/federation/update-instance', {
diff --git a/packages/misskey-js/etc/misskey-js.api.md b/packages/misskey-js/etc/misskey-js.api.md
index b9777993fd..6b01321047 100644
--- a/packages/misskey-js/etc/misskey-js.api.md
+++ b/packages/misskey-js/etc/misskey-js.api.md
@@ -29,6 +29,7 @@ type Ad = TODO_2;
// @public (undocumented)
type AdminInstanceMetadata = DetailedInstanceMetadata & {
blockedHosts: string[];
+ silencedHosts: string[];
app192IconUrl: string | null;
app512IconUrl: string | null;
manifestJsonOverride: string;
@@ -2359,6 +2360,7 @@ type Instance = {
lastCommunicatedAt: DateString;
isNotResponding: boolean;
isSuspended: boolean;
+ isSilenced: boolean;
isBlocked: boolean;
softwareName: string | null;
softwareVersion: string | null;
@@ -2985,7 +2987,7 @@ type UserSorting = '+follower' | '-follower' | '+createdAt' | '-createdAt' | '+u
// src/api.types.ts:18:25 - (ae-forgotten-export) The symbol "NoParams" needs to be exported by the entry point index.d.ts
// src/api.types.ts:630:18 - (ae-forgotten-export) The symbol "ShowUserReq" needs to be exported by the entry point index.d.ts
// src/entities.ts:107:2 - (ae-forgotten-export) The symbol "notificationTypes_2" needs to be exported by the entry point index.d.ts
-// src/entities.ts:601:2 - (ae-forgotten-export) The symbol "ModerationLogPayloads" needs to be exported by the entry point index.d.ts
+// src/entities.ts:603:2 - (ae-forgotten-export) The symbol "ModerationLogPayloads" needs to be exported by the entry point index.d.ts
// src/streaming.types.ts:33:4 - (ae-forgotten-export) The symbol "FIXME" needs to be exported by the entry point index.d.ts
// (No @packageDocumentation comment for this package)
diff --git a/packages/misskey-js/src/entities.ts b/packages/misskey-js/src/entities.ts
index bcf5538532..e05412abb9 100644
--- a/packages/misskey-js/src/entities.ts
+++ b/packages/misskey-js/src/entities.ts
@@ -385,6 +385,7 @@ export type InstanceMetadata = LiteInstanceMetadata | DetailedInstanceMetadata;
export type AdminInstanceMetadata = DetailedInstanceMetadata & {
// TODO: There are more fields.
blockedHosts: string[];
+ silencedHosts: string[];
app192IconUrl: string | null;
app512IconUrl: string | null;
manifestJsonOverride: string;
@@ -545,6 +546,7 @@ export type Instance = {
lastCommunicatedAt: DateString;
isNotResponding: boolean;
isSuspended: boolean;
+ isSilenced: boolean;
isBlocked: boolean;
softwareName: string | null;
softwareVersion: string | null;