Skip to content

Commit

Permalink
feat: 通報のカテゴリー化 (#288)
Browse files Browse the repository at this point in the history
  • Loading branch information
CyberRex0 authored Dec 28, 2023
1 parent 8a8196a commit 1478a6c
Show file tree
Hide file tree
Showing 10 changed files with 170 additions and 8 deletions.
22 changes: 22 additions & 0 deletions locales/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1190,6 +1190,28 @@ export interface Locale {
"decorate": string;
"addMfmFunction": string;
"enableQuickAddMfmFunction": string;
"abuseReportCategory": string;
"selectCategory": string;
"reportComplete": string;
"blockThisUser": string;
"muteThisUser": string;
"_abuseReportMsgs": {
"rightsAbuseCantAccept": string;
};
"_abuseReportCategory": {
"nsfw": string;
"spam": string;
"explicit": string;
"phishing": string;
"personalinfoleak": string;
"selfharm": string;
"criticalbreach": string;
"otherbreach": string;
"violationrights": string;
"violationrightsother": string;
"notlike": string;
"other": string;
};
"_announcement": {
"forExistingUsers": string;
"forExistingUsersDescription": string;
Expand Down
22 changes: 22 additions & 0 deletions locales/ja-JP.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1187,6 +1187,28 @@ seasonalScreenEffect: "季節に応じた画面の演出"
decorate: "デコる"
addMfmFunction: "装飾を追加"
enableQuickAddMfmFunction: "高度なMFMのピッカーを表示する"
abuseReportCategory: "通報の種類"
selectCategory: "カテゴリを選択"
reportComplete: "通報完了"
blockThisUser: "このユーザーをブロックする"
muteThisUser: "このユーザーをミュートする"

_abuseReportMsgs:
rightsAbuseCantAccept: "申し訳ございません。権利侵害の通報は権利者ご本人からのみ受け付けております。"

_abuseReportCategory:
nsfw: "センシティブなコンテンツを含む投稿"
spam: "スパム"
explicit: "暴力もしくは攻撃的な投稿"
phishing: "フィッシングもしくは詐欺行為"
personalinfoleak: "本人もしくは他人の個人情報の漏えい"
selfharm: "自殺もしくは自害など生命に関わる問題"
criticalbreach: "重大な規約違反"
otherbreach: "その他の規約違反"
violationrights: "権利侵害もしくはなりすまし(本人)"
violationrightsother: "権利侵害(他人)"
notlike: "この人が気に入らない"
other: "その他"

_announcement:
forExistingUsers: "既存ユーザーのみ"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/*
* SPDX-FileCopyrightText: syuilo and other misskey contributors
* SPDX-License-Identifier: AGPL-3.0-only
*/

export class AbuseUserReportCategory1703250468098 {
name = 'AbuseUserReportCategory1703250468098'

async up(queryRunner) {
await queryRunner.query(`ALTER TABLE "abuse_user_report" ADD "category" character varying(20) NOT NULL DEFAULT 'other'`);
await queryRunner.query(`CREATE INDEX "IDX_5b9acc09094daeb8683e362778" ON "abuse_user_report" ("category") `);
}

async down(queryRunner) {
await queryRunner.query(`DROP INDEX "public"."IDX_5b9acc09094daeb8683e362778"`);
await queryRunner.query(`ALTER TABLE "abuse_user_report" DROP COLUMN "category"`);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ export class AbuseUserReportEntityService {
detail: true,
}) : null,
forwarded: report.forwarded,
category: report.category,
});
}

Expand Down
7 changes: 7 additions & 0 deletions packages/backend/src/models/AbuseUserReport.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,13 @@ export class MiAbuseUserReport {
})
public comment: string;

@Index()
@Column('varchar', {
length: 20, nullable: false,
default: 'other',
})
public category: string;

//#region Denormalized fields
@Index()
@Column('varchar', {
Expand Down
4 changes: 4 additions & 0 deletions packages/backend/src/models/json-schema/abuse-user-report.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ export const packedAbuseUserReportSchema = {
format: 'id',
example: 'xxxxxxxxxx',
},
category: {
type: 'string',
optional: false, nullable: false,
},
createdAt: {
type: 'string',
optional: false, nullable: false,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,10 @@ export const meta = {
nullable: true, optional: true,
ref: 'User',
},
category: {
type: 'string',
nullable: false, optional: false,
}
},
},
},
Expand All @@ -89,6 +93,7 @@ export const paramDef = {
reporterOrigin: { type: 'string', enum: ['combined', 'local', 'remote'], default: 'combined' },
targetUserOrigin: { type: 'string', enum: ['combined', 'local', 'remote'], default: 'combined' },
forwarded: { type: 'boolean', default: false },
category: { type: 'string', nullable: true, default: null },
},
required: [],
} as const;
Expand Down Expand Up @@ -120,6 +125,10 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
case 'remote': query.andWhere('report.targetUserHost IS NOT NULL'); break;
}

if (ps.category) {
query.andWhere('report.category = :category', { category: ps.category });
}

const reports = await query.limit(ps.limit).getMany();

return await this.abuseUserReportEntityService.packMany(reports, me);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ export const paramDef = {
properties: {
userId: { type: 'string', format: 'misskey:id' },
comment: { type: 'string', minLength: 1, maxLength: 2048 },
category: { type: 'string', minLength: 1, maxLength: 20, default: 'other' },
},
required: ['userId', 'comment'],
} as const;
Expand Down Expand Up @@ -85,6 +86,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
reporterId: me.id,
reporterHost: null,
comment: ps.comment,
category: ps.category,
}).then(x => this.abuseUserReportsRepository.findOneByOrFail(x.identifiers[0]));

this.queueService.createReportAbuseJob(report);
Expand Down
1 change: 1 addition & 0 deletions packages/frontend/src/components/MkAbuseReport.vue
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ SPDX-License-Identifier: AGPL-3.0-only
{{ i18n.ts.moderator }}:
<MkAcct :user="report.assignee"/>
</div>
<div v-if="report.category">カテゴリ: {{ i18n.t(`_abuseReportCategory.${report.category}`) }}</div>
<div><MkTime :time="report.createdAt"/></div>
<div class="action">
<MkSwitch v-model="forward" :disabled="report.targetUser.host == null || report.resolved">
Expand Down
92 changes: 84 additions & 8 deletions packages/frontend/src/components/MkAbuseReportWindow.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ SPDX-License-Identifier: AGPL-3.0-only
-->

<template>
<MkWindow ref="uiWindow" :initialWidth="400" :initialHeight="500" :canResize="true" @closed="emit('closed')">
<MkWindow v-if="page === 1" ref="uiWindow" :initialWidth="400" :initialHeight="500" :canResize="true" @closed="emit('closed')">
<template #header>
<i class="ti ti-exclamation-circle" style="margin-right: 0.5em;"></i>
<I18n :src="i18n.ts.reportAbuseOf" tag="span">
Expand All @@ -15,26 +15,62 @@ SPDX-License-Identifier: AGPL-3.0-only
</template>
<MkSpacer :marginMin="20" :marginMax="28">
<div class="_gaps_m" :class="$style.root">
<div>
<MkSelect v-model="category" :required="true">
<template #label>{{ i18n.ts.abuseReportCategory }}</template>
<option value="" selected disabled>{{ i18n.ts.selectCategory }}</option>
<option value="nsfw">{{ i18n.ts._abuseReportCategory.nsfw }}</option>
<option value="spam">{{ i18n.ts._abuseReportCategory.spam }}</option>
<option value="explicit">{{ i18n.ts._abuseReportCategory.explicit }}</option>
<option value="phishing">{{ i18n.ts._abuseReportCategory.phishing }}</option>
<option value="personalinfoleak">{{ i18n.ts._abuseReportCategory.personalinfoleak }}</option>
<option value="selfharm">{{ i18n.ts._abuseReportCategory.selfharm }}</option>
<option value="criticalbreach">{{ i18n.ts._abuseReportCategory.criticalbreach }}</option>
<option value="otherbreach">{{ i18n.ts._abuseReportCategory.otherbreach }}</option>
<option value="violationrights">{{ i18n.ts._abuseReportCategory.violationrights }}</option>
<option value="violationrightsother">{{ i18n.ts._abuseReportCategory.violationrightsother }}</option>
<option value="notlike">{{ i18n.ts._abuseReportCategory.notlike }}</option>
<option value="other">{{ i18n.ts._abuseReportCategory.other }}</option>
</MkSelect>
</div>
<div class="">
<MkTextarea v-model="comment">
<template #label>{{ i18n.ts.details }}</template>
<template #caption>{{ i18n.ts.fillAbuseReportDescription }}</template>
</MkTextarea>
</div>
<div class="">
<MkButton primary full :disabled="comment.length === 0" @click="send">{{ i18n.ts.send }}</MkButton>
<MkButton primary full :disabled="comment.length === 0 || category.length === 0" @click="send">{{ i18n.ts.send }}</MkButton>
</div>
</div>
</MkSpacer>
</MkWindow>

<MkWindow v-if="page === 2" ref="uiWindow2" :initialWidth="450" :initialHeight="250" :canResize="true" @closed="emit('closed')">
<template #header>
<i class="ti ti-circle-check" style="margin-right: 0.5em;"></i>
<span><MkAcct :user="props.user"/> {{ i18n.ts.reportComplete }}</span>
</template>
<MkSpacer :marginMin="20" :marginMax="28">
<div class="_gaps_m" :class="$style.root">
<div>
<p style="margin-bottom: 20px;">{{ i18n.ts.abuseReported }}</p>
<MkButton :disabled="fullUserInfo?.isBlocking" @click="blockUser">{{ i18n.ts.blockThisUser }}</MkButton>
<br>
<MkButton :disabled="fullUserInfo?.isMuted" @click="muteUser">{{ i18n.ts.muteThisUser }}</MkButton>
</div>
</div>
</MkSpacer>
</MkWindow>
</template>

<script setup lang="ts">
import { ref, shallowRef } from 'vue';
import { ref, shallowRef, Ref } from 'vue';
import * as Misskey from 'misskey-js';
import MkWindow from '@/components/MkWindow.vue';
import MkTextarea from '@/components/MkTextarea.vue';
import MkButton from '@/components/MkButton.vue';
import MkSelect from '@/components/MkSelect.vue';
import * as os from '@/os.js';
import { i18n } from '@/i18n.js';

Expand All @@ -48,19 +84,59 @@ const emit = defineEmits<{
}>();

const uiWindow = shallowRef<InstanceType<typeof MkWindow>>();
const uiWindow2 = shallowRef<InstanceType<typeof MkWindow>>();
const comment = ref(props.initialComment ?? '');
const category = ref('');
const page = ref(1);
const fullUserInfo: Ref<Misskey.entities.UserDetailed | null> = ref(null);

function blockUser() {
os.confirm({
type: 'warning',
title: i18n.ts.block,
text: i18n.ts.blockConfirm,
}).then((v) => {
if (v.canceled) return;
os.apiWithDialog('blocking/create', { userId: props.user.id }).then(refreshUserInfo);
});
}

function muteUser() {
os.apiWithDialog('mute/create', { userId: props.user.id }).then(refreshUserInfo);
}

function refreshUserInfo() {
os.api('users/show', { userId: props.user.id })
.then((res) => {
fullUserInfo.value = res;
});
}

function send() {
if (category.value === 'violationrightsother') {
os.alert({
type: 'info',
text: i18n.ts._abuseReportMsgs.rightsAbuseCantAccept
});
uiWindow.value?.close();
emit('closed');
return;
}
if (category.value === 'notlike') {
uiWindow.value?.close();
page.value = 2;
}
os.apiWithDialog('users/report-abuse', {
userId: props.user.id,
comment: comment.value,
category: category.value,
}, undefined).then(res => {
os.alert({
type: 'success',
text: i18n.ts.abuseReported,
os.api('users/show', { userId: props.user.id })
.then((res) => {
fullUserInfo.value = res;
uiWindow.value?.close();
page.value = 2;
});
uiWindow.value?.close();
emit('closed');
});
}
</script>
Expand Down

0 comments on commit 1478a6c

Please sign in to comment.