enhance: ハードワードミュートの最大文字数を設定可能に

Resolve #7574
This commit is contained in:
syuilo 2023-01-14 08:04:38 +09:00
parent d2204fd5c8
commit d1807ee5dc
6 changed files with 48 additions and 2 deletions

View file

@ -73,8 +73,9 @@ You should also include the user name that made the change.
- Push notification of Antenna note @tamaina - Push notification of Antenna note @tamaina
- AVIF support @tamaina - AVIF support @tamaina
- Add Cloudflare Turnstile CAPTCHA support @CyberRex0 - Add Cloudflare Turnstile CAPTCHA support @CyberRex0
- 非モデレーターでも、権限を持つロールをアサインされたユーザーはインスタンスの招待コードを発行できるように - 非モデレーターでも、権限を持つロールをアサインされたユーザーはインスタンスの招待コードを発行できるように @syuilo
- 非モデレーターでも、権限を持つロールをアサインされたユーザーはカスタム絵文字の追加、編集、削除を行えるように - 非モデレーターでも、権限を持つロールをアサインされたユーザーはカスタム絵文字の追加、編集、削除を行えるように @syuilo
- ハードワードミュートの最大文字数を設定可能に @syuilo
- Server: signToActivityPubGet is set to true by default @syuilo - Server: signToActivityPubGet is set to true by default @syuilo
- Server: improve syslog performance @syuilo - Server: improve syslog performance @syuilo
- Server: Use undici instead of node-fetch and got @tamaina - Server: Use undici instead of node-fetch and got @tamaina

View file

@ -962,6 +962,7 @@ _role:
canManageCustomEmojis: "カスタム絵文字の管理" canManageCustomEmojis: "カスタム絵文字の管理"
driveCapacity: "ドライブ容量" driveCapacity: "ドライブ容量"
antennaMax: "アンテナの作成可能数" antennaMax: "アンテナの作成可能数"
wordMuteMax: "ワードミュートの最大文字数"
_condition: _condition:
isLocal: "ローカルユーザー" isLocal: "ローカルユーザー"
isRemote: "リモートユーザー" isRemote: "リモートユーザー"

View file

@ -20,6 +20,7 @@ export type RoleOptions = {
canManageCustomEmojis: boolean; canManageCustomEmojis: boolean;
driveCapacityMb: number; driveCapacityMb: number;
antennaLimit: number; antennaLimit: number;
wordMuteLimit: number;
}; };
export const DEFAULT_ROLE: RoleOptions = { export const DEFAULT_ROLE: RoleOptions = {
@ -30,6 +31,7 @@ export const DEFAULT_ROLE: RoleOptions = {
canManageCustomEmojis: false, canManageCustomEmojis: false,
driveCapacityMb: 100, driveCapacityMb: 100,
antennaLimit: 5, antennaLimit: 5,
wordMuteLimit: 200,
}; };
@Injectable() @Injectable()
@ -187,6 +189,7 @@ export class RoleService implements OnApplicationShutdown {
canManageCustomEmojis: getOptionValues('canManageCustomEmojis').some(x => x === true), canManageCustomEmojis: getOptionValues('canManageCustomEmojis').some(x => x === true),
driveCapacityMb: Math.max(...getOptionValues('driveCapacityMb')), driveCapacityMb: Math.max(...getOptionValues('driveCapacityMb')),
antennaLimit: Math.max(...getOptionValues('antennaLimit')), antennaLimit: Math.max(...getOptionValues('antennaLimit')),
wordMuteLimit: Math.max(...getOptionValues('wordMuteLimit')),
}; };
} }

View file

@ -17,6 +17,7 @@ import { UserFollowingService } from '@/core/UserFollowingService.js';
import { AccountUpdateService } from '@/core/AccountUpdateService.js'; import { AccountUpdateService } from '@/core/AccountUpdateService.js';
import { HashtagService } from '@/core/HashtagService.js'; import { HashtagService } from '@/core/HashtagService.js';
import { DI } from '@/di-symbols.js'; import { DI } from '@/di-symbols.js';
import { RoleService } from '@/core/RoleService.js';
import { ApiError } from '../../error.js'; import { ApiError } from '../../error.js';
export const meta = { export const meta = {
@ -62,6 +63,12 @@ export const meta = {
code: 'INVALID_REGEXP', code: 'INVALID_REGEXP',
id: '0d786918-10df-41cd-8f33-8dec7d9a89a5', id: '0d786918-10df-41cd-8f33-8dec7d9a89a5',
}, },
tooManyMutedWords: {
message: 'Too many muted words.',
code: 'TOO_MANY_MUTED_WORDS',
id: '010665b1-a211-42d2-bc64-8f6609d79785',
},
}, },
res: { res: {
@ -144,6 +151,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
private userFollowingService: UserFollowingService, private userFollowingService: UserFollowingService,
private accountUpdateService: AccountUpdateService, private accountUpdateService: AccountUpdateService,
private hashtagService: HashtagService, private hashtagService: HashtagService,
private roleService: RoleService,
) { ) {
super(meta, paramDef, async (ps, _user, token) => { super(meta, paramDef, async (ps, _user, token) => {
const user = await this.usersRepository.findOneByOrFail({ id: _user.id }); const user = await this.usersRepository.findOneByOrFail({ id: _user.id });
@ -163,6 +171,12 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
if (ps.avatarId !== undefined) updates.avatarId = ps.avatarId; if (ps.avatarId !== undefined) updates.avatarId = ps.avatarId;
if (ps.bannerId !== undefined) updates.bannerId = ps.bannerId; if (ps.bannerId !== undefined) updates.bannerId = ps.bannerId;
if (ps.mutedWords !== undefined) { if (ps.mutedWords !== undefined) {
// TODO: ちゃんと数える
const length = JSON.stringify(ps.mutedWords).length;
if (length > (await this.roleService.getUserRoleOptions(user.id)).antennaLimit) {
throw new ApiError(meta.errors.tooManyMutedWords);
}
// validate regular expression syntax // validate regular expression syntax
ps.mutedWords.filter(x => !Array.isArray(x)).forEach(x => { ps.mutedWords.filter(x => !Array.isArray(x)).forEach(x => {
const regexp = x.match(/^\/(.+)\/(.*)$/); const regexp = x.match(/^\/(.+)\/(.*)$/);

View file

@ -127,6 +127,19 @@
</MkInput> </MkInput>
</div> </div>
</MkFolder> </MkFolder>
<MkFolder>
<template #label>{{ i18n.ts._role._options.wordMuteMax }}</template>
<template #suffix>{{ options_wordMuteLimit_useDefault ? i18n.ts._role.useBaseValue : (options_wordMuteLimit_value) }}</template>
<div class="_gaps">
<MkSwitch v-model="options_wordMuteLimit_useDefault" :readonly="readonly">
<template #label>{{ i18n.ts._role.useBaseValue }}</template>
</MkSwitch>
<MkInput v-model="options_wordMuteLimit_value" :disabled="options_wordMuteLimit_useDefault" type="number" :readonly="readonly">
<template #suffix>chars</template>
</MkInput>
</div>
</MkFolder>
</div> </div>
</FormSlot> </FormSlot>
@ -194,6 +207,8 @@ let options_driveCapacityMb_useDefault = $ref(role?.options?.driveCapacityMb?.us
let options_driveCapacityMb_value = $ref(role?.options?.driveCapacityMb?.value ?? 0); let options_driveCapacityMb_value = $ref(role?.options?.driveCapacityMb?.value ?? 0);
let options_antennaLimit_useDefault = $ref(role?.options?.antennaLimit?.useDefault ?? true); let options_antennaLimit_useDefault = $ref(role?.options?.antennaLimit?.useDefault ?? true);
let options_antennaLimit_value = $ref(role?.options?.antennaLimit?.value ?? 0); let options_antennaLimit_value = $ref(role?.options?.antennaLimit?.value ?? 0);
let options_wordMuteLimit_useDefault = $ref(role?.options?.wordMuteLimit?.useDefault ?? true);
let options_wordMuteLimit_value = $ref(role?.options?.wordMuteLimit?.value ?? 0);
if (_DEV_) { if (_DEV_) {
watch($$(condFormula), () => { watch($$(condFormula), () => {
@ -210,6 +225,7 @@ function getOptions() {
canManageCustomEmojis: { useDefault: options_canManageCustomEmojis_useDefault, value: options_canManageCustomEmojis_value }, canManageCustomEmojis: { useDefault: options_canManageCustomEmojis_useDefault, value: options_canManageCustomEmojis_value },
driveCapacityMb: { useDefault: options_driveCapacityMb_useDefault, value: options_driveCapacityMb_value }, driveCapacityMb: { useDefault: options_driveCapacityMb_useDefault, value: options_driveCapacityMb_value },
antennaLimit: { useDefault: options_antennaLimit_useDefault, value: options_antennaLimit_value }, antennaLimit: { useDefault: options_antennaLimit_useDefault, value: options_antennaLimit_value },
wordMuteLimit: { useDefault: options_wordMuteLimit_useDefault, value: options_wordMuteLimit_value },
}; };
} }

View file

@ -62,6 +62,15 @@
<MkInput v-model="options_antennaLimit" type="number"> <MkInput v-model="options_antennaLimit" type="number">
</MkInput> </MkInput>
</MkFolder> </MkFolder>
<MkFolder>
<template #label>{{ i18n.ts._role._options.wordMuteMax }}</template>
<template #suffix>{{ options_wordMuteLimit }}</template>
<MkInput v-model="options_wordMuteLimit" type="number">
<template #suffix>chars</template>
</MkInput>
</MkFolder>
<MkButton primary rounded @click="updateBaseRole">{{ i18n.ts.save }}</MkButton> <MkButton primary rounded @click="updateBaseRole">{{ i18n.ts.save }}</MkButton>
</div> </div>
</MkFolder> </MkFolder>
@ -101,6 +110,7 @@ let options_canInvite = $ref(instance.baseRole.canInvite);
let options_canManageCustomEmojis = $ref(instance.baseRole.canManageCustomEmojis); let options_canManageCustomEmojis = $ref(instance.baseRole.canManageCustomEmojis);
let options_driveCapacityMb = $ref(instance.baseRole.driveCapacityMb); let options_driveCapacityMb = $ref(instance.baseRole.driveCapacityMb);
let options_antennaLimit = $ref(instance.baseRole.antennaLimit); let options_antennaLimit = $ref(instance.baseRole.antennaLimit);
let options_wordMuteLimit = $ref(instance.baseRole.wordMuteLimit);
async function updateBaseRole() { async function updateBaseRole() {
await os.apiWithDialog('admin/roles/update-default-role-override', { await os.apiWithDialog('admin/roles/update-default-role-override', {
@ -112,6 +122,7 @@ async function updateBaseRole() {
canManageCustomEmojis: options_canManageCustomEmojis, canManageCustomEmojis: options_canManageCustomEmojis,
driveCapacityMb: options_driveCapacityMb, driveCapacityMb: options_driveCapacityMb,
antennaLimit: options_antennaLimit, antennaLimit: options_antennaLimit,
wordMuteLimit: options_wordMuteLimit,
}, },
}); });
} }