feat: auto nsfw detection (#8840)

* feat: auto nsfw detection

* ✌️

* Update ja-JP.yml

* Update ja-JP.yml

* ポルノ判定のしきい値を高めに

* エラーハンドリングちゃんとした

* Update ja-JP.yml

* 感度設定を強化

* refactor

* feat: add video support for auto nsfw detection

* rename: image -> media

* .js

* fix: add missing error handling

* fix: use valid pathname instead of using filename due to invalid usage

* perf(nsfw-detection): decode frames

* disable detection of video for some reasons

* perf(nsfw-detection): streamify detection process for video

* disable disallowUploadWhenPredictedAsPorn option

* fix(nsfw-detection): improve reliability

* fix(nsfw-detection): use Math.ceil instead of Math.round

* perf(nsfw-detection): delete tmp frames after used

* fix(nsfw-detection): FSWatcher does not emit ready event

* perf(nsfw-detection): skip black frames

* refactor: strip exists check

* Update package.json

* めっちゃ変えた

* lint

* Update COPYING

* オプションで動画解析できるように

* Update yarn.lock

* Update CHANGELOG.md

Co-authored-by: Acid Chicken (硫酸鶏) <root@acid-chicken.com>
This commit is contained in:
syuilo
2022-07-07 21:06:37 +09:00
committed by GitHub
parent 010db2515c
commit e560601815
39 changed files with 1275 additions and 78 deletions

View File

@@ -1,9 +1,9 @@
import { ref } from 'vue';
import { DriveFile } from 'misskey-js/built/entities';
import * as os from '@/os';
import { stream } from '@/stream';
import { i18n } from '@/i18n';
import { defaultStore } from '@/store';
import { DriveFile } from 'misskey-js/built/entities';
import { uploadFile } from '@/scripts/upload';
function select(src: any, label: string | null, multiple: boolean): Promise<DriveFile | DriveFile[]> {
@@ -20,10 +20,7 @@ function select(src: any, label: string | null, multiple: boolean): Promise<Driv
Promise.all(promises).then(driveFiles => {
res(multiple ? driveFiles : driveFiles[0]);
}).catch(err => {
os.alert({
type: 'error',
text: err
});
// アップロードのエラーは uploadFile 内でハンドリングされているためアラートダイアログを出したりはしてはいけない
});
// 一応廃棄
@@ -47,7 +44,7 @@ function select(src: any, label: string | null, multiple: boolean): Promise<Driv
os.inputText({
title: i18n.ts.uploadFromUrl,
type: 'url',
placeholder: i18n.ts.uploadFromUrlDescription
placeholder: i18n.ts.uploadFromUrlDescription,
}).then(({ canceled, result: url }) => {
if (canceled) return;
@@ -64,35 +61,35 @@ function select(src: any, label: string | null, multiple: boolean): Promise<Driv
os.api('drive/files/upload-from-url', {
url: url,
folderId: defaultStore.state.uploadFolder,
marker
marker,
});
os.alert({
title: i18n.ts.uploadFromUrlRequested,
text: i18n.ts.uploadFromUrlMayTakeTime
text: i18n.ts.uploadFromUrlMayTakeTime,
});
});
};
os.popupMenu([label ? {
text: label,
type: 'label'
type: 'label',
} : undefined, {
type: 'switch',
text: i18n.ts.keepOriginalUploading,
ref: keepOriginal
ref: keepOriginal,
}, {
text: i18n.ts.upload,
icon: 'fas fa-upload',
action: chooseFileFromPc
action: chooseFileFromPc,
}, {
text: i18n.ts.fromDrive,
icon: 'fas fa-cloud',
action: chooseFileFromDrive
action: chooseFileFromDrive,
}, {
text: i18n.ts.fromUrl,
icon: 'fas fa-link',
action: chooseFileFromUrl
action: chooseFileFromUrl,
}], src);
});
}

View File

@@ -5,6 +5,7 @@ import { defaultStore } from '@/store';
import { apiUrl } from '@/config';
import { $i } from '@/account';
import { alert } from '@/os';
import { i18n } from '@/i18n';
type Uploading = {
id: string;
@@ -80,14 +81,37 @@ export function uploadFile(
xhr.open('POST', apiUrl + '/drive/files/create', true);
xhr.onload = (ev) => {
if (xhr.status !== 200 || ev.target == null || ev.target.response == null) {
// TODO: 消すのではなくて再送できるようにしたい
// TODO: 消すのではなくて(ネットワーク的なエラーなら)再送できるようにしたい
uploads.value = uploads.value.filter(x => x.id !== id);
alert({
type: 'error',
title: 'Failed to upload',
text: `${JSON.stringify(ev.target?.response)}, ${JSON.stringify(xhr.response)}`,
});
if (ev.target?.response) {
const res = JSON.parse(ev.target.response);
if (res.error?.id === 'bec5bd69-fba3-43c9-b4fb-2894b66ad5d2') {
alert({
type: 'error',
title: i18n.ts.failedToUpload,
text: i18n.ts.cannotUploadBecauseInappropriate,
});
} else if (res.error?.id === 'd08dbc37-a6a9-463a-8c47-96c32ab5f064') {
alert({
type: 'error',
title: i18n.ts.failedToUpload,
text: i18n.ts.cannotUploadBecauseNoFreeSpace,
});
} else {
alert({
type: 'error',
title: i18n.ts.failedToUpload,
text: `${res.error?.message}\n${res.error?.code}\n${res.error?.id}`,
});
}
} else {
alert({
type: 'error',
title: 'Failed to upload',
text: `${JSON.stringify(ev.target?.response)}, ${JSON.stringify(xhr.response)}`,
});
}
reject();
return;