diff options
| author | まっちゃてぃー <56515516+mattyatea@users.noreply.github.com> | 2023-10-16 20:11:27 +0900 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-10-16 20:11:27 +0900 |
| commit | 5efd01ba70b37868f625e0acfc5c1c22d5df775c (patch) | |
| tree | d042555298ef2beb8feb3db1cca2320c41657fb9 /packages/backend/src | |
| parent | fix test (diff) | |
| download | misskey-5efd01ba70b37868f625e0acfc5c1c22d5df775c.tar.gz misskey-5efd01ba70b37868f625e0acfc5c1c22d5df775c.tar.bz2 misskey-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/backend/src')
9 files changed, 102 insertions, 22 deletions
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))'); |