diff --git a/CHANGELOG.md b/CHANGELOG.md index ac9d4b835a..7ca44f87f9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -73,8 +73,9 @@ You should also include the user name that made the change. - Push notification of Antenna note @tamaina - AVIF support @tamaina - Add Cloudflare Turnstile CAPTCHA support @CyberRex0 -- 非モデレーターでも、権限を持つロールをアサインされたユーザーはインスタンスの招待コードを発行できるように -- 非モデレーターでも、権限を持つロールをアサインされたユーザーはカスタム絵文字の追加、編集、削除を行えるように +- 非モデレーターでも、権限を持つロールをアサインされたユーザーはインスタンスの招待コードを発行できるように @syuilo +- 非モデレーターでも、権限を持つロールをアサインされたユーザーはカスタム絵文字の追加、編集、削除を行えるように @syuilo +- ハードワードミュートの最大文字数を設定可能に @syuilo - Server: signToActivityPubGet is set to true by default @syuilo - Server: improve syslog performance @syuilo - Server: Use undici instead of node-fetch and got @tamaina diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml index daeacf7690..943168061c 100644 --- a/locales/ja-JP.yml +++ b/locales/ja-JP.yml @@ -962,6 +962,7 @@ _role: canManageCustomEmojis: "カスタム絵文字の管理" driveCapacity: "ドライブ容量" antennaMax: "アンテナの作成可能数" + wordMuteMax: "ワードミュートの最大文字数" _condition: isLocal: "ローカルユーザー" isRemote: "リモートユーザー" diff --git a/packages/backend/src/core/RoleService.ts b/packages/backend/src/core/RoleService.ts index 15ba900802..d2056709e1 100644 --- a/packages/backend/src/core/RoleService.ts +++ b/packages/backend/src/core/RoleService.ts @@ -20,6 +20,7 @@ export type RoleOptions = { canManageCustomEmojis: boolean; driveCapacityMb: number; antennaLimit: number; + wordMuteLimit: number; }; export const DEFAULT_ROLE: RoleOptions = { @@ -30,6 +31,7 @@ export const DEFAULT_ROLE: RoleOptions = { canManageCustomEmojis: false, driveCapacityMb: 100, antennaLimit: 5, + wordMuteLimit: 200, }; @Injectable() @@ -187,6 +189,7 @@ export class RoleService implements OnApplicationShutdown { canManageCustomEmojis: getOptionValues('canManageCustomEmojis').some(x => x === true), driveCapacityMb: Math.max(...getOptionValues('driveCapacityMb')), antennaLimit: Math.max(...getOptionValues('antennaLimit')), + wordMuteLimit: Math.max(...getOptionValues('wordMuteLimit')), }; } diff --git a/packages/backend/src/server/api/endpoints/i/update.ts b/packages/backend/src/server/api/endpoints/i/update.ts index c2231f5f75..ef5ab16bc4 100644 --- a/packages/backend/src/server/api/endpoints/i/update.ts +++ b/packages/backend/src/server/api/endpoints/i/update.ts @@ -17,6 +17,7 @@ import { UserFollowingService } from '@/core/UserFollowingService.js'; import { AccountUpdateService } from '@/core/AccountUpdateService.js'; import { HashtagService } from '@/core/HashtagService.js'; import { DI } from '@/di-symbols.js'; +import { RoleService } from '@/core/RoleService.js'; import { ApiError } from '../../error.js'; export const meta = { @@ -62,6 +63,12 @@ export const meta = { code: 'INVALID_REGEXP', id: '0d786918-10df-41cd-8f33-8dec7d9a89a5', }, + + tooManyMutedWords: { + message: 'Too many muted words.', + code: 'TOO_MANY_MUTED_WORDS', + id: '010665b1-a211-42d2-bc64-8f6609d79785', + }, }, res: { @@ -144,6 +151,7 @@ export default class extends Endpoint { private userFollowingService: UserFollowingService, private accountUpdateService: AccountUpdateService, private hashtagService: HashtagService, + private roleService: RoleService, ) { super(meta, paramDef, async (ps, _user, token) => { const user = await this.usersRepository.findOneByOrFail({ id: _user.id }); @@ -163,6 +171,12 @@ export default class extends Endpoint { if (ps.avatarId !== undefined) updates.avatarId = ps.avatarId; if (ps.bannerId !== undefined) updates.bannerId = ps.bannerId; 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 ps.mutedWords.filter(x => !Array.isArray(x)).forEach(x => { const regexp = x.match(/^\/(.+)\/(.*)$/); diff --git a/packages/frontend/src/pages/admin/roles.editor.vue b/packages/frontend/src/pages/admin/roles.editor.vue index b66c967e6a..30bc6c238e 100644 --- a/packages/frontend/src/pages/admin/roles.editor.vue +++ b/packages/frontend/src/pages/admin/roles.editor.vue @@ -127,6 +127,19 @@ + + + + +
+ + + + + + +
+
@@ -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_antennaLimit_useDefault = $ref(role?.options?.antennaLimit?.useDefault ?? true); 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_) { watch($$(condFormula), () => { @@ -210,6 +225,7 @@ function getOptions() { canManageCustomEmojis: { useDefault: options_canManageCustomEmojis_useDefault, value: options_canManageCustomEmojis_value }, driveCapacityMb: { useDefault: options_driveCapacityMb_useDefault, value: options_driveCapacityMb_value }, antennaLimit: { useDefault: options_antennaLimit_useDefault, value: options_antennaLimit_value }, + wordMuteLimit: { useDefault: options_wordMuteLimit_useDefault, value: options_wordMuteLimit_value }, }; } diff --git a/packages/frontend/src/pages/admin/roles.vue b/packages/frontend/src/pages/admin/roles.vue index 16c12f9928..001800ea26 100644 --- a/packages/frontend/src/pages/admin/roles.vue +++ b/packages/frontend/src/pages/admin/roles.vue @@ -62,6 +62,15 @@ + + + + + + + + + {{ i18n.ts.save }} @@ -101,6 +110,7 @@ let options_canInvite = $ref(instance.baseRole.canInvite); let options_canManageCustomEmojis = $ref(instance.baseRole.canManageCustomEmojis); let options_driveCapacityMb = $ref(instance.baseRole.driveCapacityMb); let options_antennaLimit = $ref(instance.baseRole.antennaLimit); +let options_wordMuteLimit = $ref(instance.baseRole.wordMuteLimit); async function updateBaseRole() { await os.apiWithDialog('admin/roles/update-default-role-override', { @@ -112,6 +122,7 @@ async function updateBaseRole() { canManageCustomEmojis: options_canManageCustomEmojis, driveCapacityMb: options_driveCapacityMb, antennaLimit: options_antennaLimit, + wordMuteLimit: options_wordMuteLimit, }, }); }