From d624547874edbcc40a5017549d1566b980584d36 Mon Sep 17 00:00:00 2001 From: kabo2468 <28654659+kabo2468@users.noreply.github.com> Date: Sun, 3 Mar 2024 03:48:47 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20AI=E3=81=AB=E3=82=88=E3=82=8BNSFW?= =?UTF-8?q?=E6=A4=9C=E5=87=BA=E3=82=92=E7=84=A1=E8=A6=96=E3=81=A7=E3=81=8D?= =?UTF-8?q?=E3=82=8B=E3=83=9D=E3=83=AA=E3=82=B7=E3=83=BC=E3=82=92=E8=BF=BD?= =?UTF-8?q?=E5=8A=A0=20(MisskeyIO#500)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: AIによるNSFW検出を無視できるポリシーを追加 * refactor: skipNsfwCheckの条件を同じようにまとめた --- locales/en-US.yml | 1 + locales/index.d.ts | 4 ++++ locales/ja-JP.yml | 1 + packages/backend/src/core/DriveService.ts | 20 +++++++++---------- packages/backend/src/core/RoleService.ts | 3 +++ .../backend/src/models/json-schema/role.ts | 4 ++++ packages/frontend/src/const.ts | 1 + .../frontend/src/pages/admin/roles.editor.vue | 20 +++++++++++++++++++ packages/frontend/src/pages/admin/roles.vue | 8 ++++++++ packages/misskey-js/src/autogen/types.ts | 1 + 10 files changed, 52 insertions(+), 11 deletions(-) diff --git a/locales/en-US.yml b/locales/en-US.yml index 7bfc5d3e44..569484a092 100644 --- a/locales/en-US.yml +++ b/locales/en-US.yml @@ -1698,6 +1698,7 @@ _role: canManageAvatarDecorations: "Manage avatar decorations" driveCapacity: "Drive capacity" alwaysMarkNsfw: "Always mark files as NSFW" + skipNsfwDetection: "Skip NSFW detection by AI" pinMax: "Maximum number of pinned notes" antennaMax: "Maximum number of antennas" antennaNotesMax: "Maximum number of notes stored in antennas" diff --git a/locales/index.d.ts b/locales/index.d.ts index c027b07b32..59bc5b5c16 100644 --- a/locales/index.d.ts +++ b/locales/index.d.ts @@ -6622,6 +6622,10 @@ export interface Locale extends ILocale { * ファイルにNSFWを常に付与 */ "alwaysMarkNsfw": string; + /** + * AIによるNSFW検出を無視 + */ + "skipNsfwDetection": string; /** * ノートのピン留めの最大数 */ diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml index 0efd769737..8065500bdf 100644 --- a/locales/ja-JP.yml +++ b/locales/ja-JP.yml @@ -1713,6 +1713,7 @@ _role: canManageAvatarDecorations: "アバターデコレーションの管理" driveCapacity: "ドライブ容量" alwaysMarkNsfw: "ファイルにNSFWを常に付与" + skipNsfwDetection: "AIによるNSFW検出を無視" pinMax: "ノートのピン留めの最大数" antennaMax: "アンテナの作成可能数" antennaNotesMax: "アンテナに保持する最大ノート数" diff --git a/packages/backend/src/core/DriveService.ts b/packages/backend/src/core/DriveService.ts index dd21f0ab00..b15fbeaab8 100644 --- a/packages/backend/src/core/DriveService.ts +++ b/packages/backend/src/core/DriveService.ts @@ -459,15 +459,14 @@ export class DriveService { }: AddFileArgs): Promise { let skipNsfwCheck = false; const instance = await this.metaService.fetch(); - const userRoleNSFW = user && (await this.roleService.getUserPolicies(user.id)).alwaysMarkNsfw; - if (user == null) { - skipNsfwCheck = true; - } else if (userRoleNSFW) { - skipNsfwCheck = true; - } - if (instance.sensitiveMediaDetection === 'none') skipNsfwCheck = true; - if (user && instance.sensitiveMediaDetection === 'local' && this.userEntityService.isRemoteUser(user)) skipNsfwCheck = true; - if (user && instance.sensitiveMediaDetection === 'remote' && this.userEntityService.isLocalUser(user)) skipNsfwCheck = true; + const policies = user && await this.roleService.getUserPolicies(user.id); + const userRoleNSFW = policies?.alwaysMarkNsfw; + skipNsfwCheck ||= user == null; + skipNsfwCheck ||= !!userRoleNSFW; + skipNsfwCheck ||= !!policies?.skipNsfwDetection; + skipNsfwCheck ||= instance.sensitiveMediaDetection === 'none'; + skipNsfwCheck ||= !!(user && instance.sensitiveMediaDetection === 'local' && this.userEntityService.isRemoteUser(user)); + skipNsfwCheck ||= !!(user && instance.sensitiveMediaDetection === 'remote' && this.userEntityService.isLocalUser(user)); const info = await this.fileInfoService.getFileInfo(path, { skipSensitiveDetection: skipNsfwCheck, @@ -511,11 +510,10 @@ export class DriveService { this.registerLogger.debug(`ADD DRIVE FILE: user ${user?.id ?? 'not set'}, name ${detectedName}, tmp ${path}`); //#region Check drive usage - if (user && !isLink) { + if (user && policies && !isLink) { const usage = await this.driveFileEntityService.calcDriveUsageOf(user); const isLocalUser = this.userEntityService.isLocalUser(user); - const policies = await this.roleService.getUserPolicies(user.id); const driveCapacity = 1024 * 1024 * policies.driveCapacityMb; this.registerLogger.debug('drive capacity override applied'); this.registerLogger.debug(`overrideCap: ${driveCapacity}bytes, usage: ${usage}bytes, u+s: ${usage + info.size}bytes`); diff --git a/packages/backend/src/core/RoleService.ts b/packages/backend/src/core/RoleService.ts index 5db2e6fc05..b0217679ed 100644 --- a/packages/backend/src/core/RoleService.ts +++ b/packages/backend/src/core/RoleService.ts @@ -55,6 +55,7 @@ export type RolePolicies = { canHideAds: boolean; driveCapacityMb: number; alwaysMarkNsfw: boolean; + skipNsfwDetection: boolean; pinLimit: number; antennaLimit: number; antennaNotesLimit: number; @@ -91,6 +92,7 @@ export const DEFAULT_POLICIES: RolePolicies = { canHideAds: false, driveCapacityMb: 100, alwaysMarkNsfw: false, + skipNsfwDetection: false, pinLimit: 5, antennaLimit: 5, antennaNotesLimit: 200, @@ -366,6 +368,7 @@ export class RoleService implements OnApplicationShutdown, OnModuleInit { canHideAds: calc('canHideAds', vs => vs.some(v => v === true)), driveCapacityMb: calc('driveCapacityMb', vs => Math.max(...vs)), alwaysMarkNsfw: calc('alwaysMarkNsfw', vs => vs.some(v => v === true)), + skipNsfwDetection: calc('skipNsfwDetection', vs => vs.some(v => v === true)), pinLimit: calc('pinLimit', vs => Math.max(...vs)), antennaLimit: calc('antennaLimit', vs => Math.max(...vs)), antennaNotesLimit: calc('antennaNotesLimit', vs => Math.max(...vs)), diff --git a/packages/backend/src/models/json-schema/role.ts b/packages/backend/src/models/json-schema/role.ts index c39e3824e9..e757d109e8 100644 --- a/packages/backend/src/models/json-schema/role.ts +++ b/packages/backend/src/models/json-schema/role.ts @@ -239,6 +239,10 @@ export const packedRolePoliciesSchema = { type: 'boolean', optional: false, nullable: false, }, + skipNsfwDetection: { + type: 'boolean', + optional: false, nullable: false, + }, pinLimit: { type: 'integer', optional: false, nullable: false, diff --git a/packages/frontend/src/const.ts b/packages/frontend/src/const.ts index 5edd983065..9ce2ceddf0 100644 --- a/packages/frontend/src/const.ts +++ b/packages/frontend/src/const.ts @@ -94,6 +94,7 @@ export const ROLE_POLICIES = [ 'canHideAds', 'driveCapacityMb', 'alwaysMarkNsfw', + 'skipNsfwDetection', 'pinLimit', 'antennaLimit', 'antennaNotesLimit', diff --git a/packages/frontend/src/pages/admin/roles.editor.vue b/packages/frontend/src/pages/admin/roles.editor.vue index 43c595a33a..ee6ea14464 100644 --- a/packages/frontend/src/pages/admin/roles.editor.vue +++ b/packages/frontend/src/pages/admin/roles.editor.vue @@ -518,6 +518,26 @@ SPDX-License-Identifier: AGPL-3.0-only + + + +
+ + + + + + + + + +
+
+