parent
d2204fd5c8
commit
d1807ee5dc
6 changed files with 48 additions and 2 deletions
|
@ -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
|
||||||
|
|
|
@ -962,6 +962,7 @@ _role:
|
||||||
canManageCustomEmojis: "カスタム絵文字の管理"
|
canManageCustomEmojis: "カスタム絵文字の管理"
|
||||||
driveCapacity: "ドライブ容量"
|
driveCapacity: "ドライブ容量"
|
||||||
antennaMax: "アンテナの作成可能数"
|
antennaMax: "アンテナの作成可能数"
|
||||||
|
wordMuteMax: "ワードミュートの最大文字数"
|
||||||
_condition:
|
_condition:
|
||||||
isLocal: "ローカルユーザー"
|
isLocal: "ローカルユーザー"
|
||||||
isRemote: "リモートユーザー"
|
isRemote: "リモートユーザー"
|
||||||
|
|
|
@ -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')),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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(/^\/(.+)\/(.*)$/);
|
||||||
|
|
|
@ -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 },
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue