feat: アンテナに保持するノート数をポリシーに追加 (MisskeyIO#499)
This commit is contained in:
parent
a24e93ec6c
commit
c0dbdd78c1
|
@ -1700,6 +1700,7 @@ _role:
|
||||||
alwaysMarkNsfw: "Always mark files as NSFW"
|
alwaysMarkNsfw: "Always mark files as NSFW"
|
||||||
pinMax: "Maximum number of pinned notes"
|
pinMax: "Maximum number of pinned notes"
|
||||||
antennaMax: "Maximum number of antennas"
|
antennaMax: "Maximum number of antennas"
|
||||||
|
antennaNotesMax: "Maximum number of notes stored in antennas"
|
||||||
wordMuteMax: "Maximum number of characters allowed in word mutes"
|
wordMuteMax: "Maximum number of characters allowed in word mutes"
|
||||||
webhookMax: "Maximum number of Webhooks"
|
webhookMax: "Maximum number of Webhooks"
|
||||||
clipMax: "Maximum number of Clips"
|
clipMax: "Maximum number of Clips"
|
||||||
|
|
|
@ -6630,6 +6630,10 @@ export interface Locale extends ILocale {
|
||||||
* アンテナの作成可能数
|
* アンテナの作成可能数
|
||||||
*/
|
*/
|
||||||
"antennaMax": string;
|
"antennaMax": string;
|
||||||
|
/**
|
||||||
|
* アンテナに保持する最大ノート数
|
||||||
|
*/
|
||||||
|
"antennaNotesMax": string;
|
||||||
/**
|
/**
|
||||||
* ワードミュートの最大文字数
|
* ワードミュートの最大文字数
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -1715,6 +1715,7 @@ _role:
|
||||||
alwaysMarkNsfw: "ファイルにNSFWを常に付与"
|
alwaysMarkNsfw: "ファイルにNSFWを常に付与"
|
||||||
pinMax: "ノートのピン留めの最大数"
|
pinMax: "ノートのピン留めの最大数"
|
||||||
antennaMax: "アンテナの作成可能数"
|
antennaMax: "アンテナの作成可能数"
|
||||||
|
antennaNotesMax: "アンテナに保持する最大ノート数"
|
||||||
wordMuteMax: "ワードミュートの最大文字数"
|
wordMuteMax: "ワードミュートの最大文字数"
|
||||||
webhookMax: "Webhookの作成可能数"
|
webhookMax: "Webhookの作成可能数"
|
||||||
clipMax: "クリップの作成可能数"
|
clipMax: "クリップの作成可能数"
|
||||||
|
|
|
@ -17,6 +17,7 @@ import { UtilityService } from '@/core/UtilityService.js';
|
||||||
import { bindThis } from '@/decorators.js';
|
import { bindThis } from '@/decorators.js';
|
||||||
import type { GlobalEvents } from '@/core/GlobalEventService.js';
|
import type { GlobalEvents } from '@/core/GlobalEventService.js';
|
||||||
import { FanoutTimelineService } from '@/core/FanoutTimelineService.js';
|
import { FanoutTimelineService } from '@/core/FanoutTimelineService.js';
|
||||||
|
import { RoleService } from '@/core/RoleService.js';
|
||||||
import type { OnApplicationShutdown } from '@nestjs/common';
|
import type { OnApplicationShutdown } from '@nestjs/common';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
|
@ -40,6 +41,7 @@ export class AntennaService implements OnApplicationShutdown {
|
||||||
private utilityService: UtilityService,
|
private utilityService: UtilityService,
|
||||||
private globalEventService: GlobalEventService,
|
private globalEventService: GlobalEventService,
|
||||||
private fanoutTimelineService: FanoutTimelineService,
|
private fanoutTimelineService: FanoutTimelineService,
|
||||||
|
private roleService: RoleService,
|
||||||
) {
|
) {
|
||||||
this.antennasFetched = false;
|
this.antennasFetched = false;
|
||||||
this.antennas = [];
|
this.antennas = [];
|
||||||
|
@ -102,8 +104,10 @@ export class AntennaService implements OnApplicationShutdown {
|
||||||
|
|
||||||
const redisPipeline = this.redisForTimelines.pipeline();
|
const redisPipeline = this.redisForTimelines.pipeline();
|
||||||
|
|
||||||
|
const { antennaNotesLimit } = await this.roleService.getUserPolicies(noteUser.id);
|
||||||
|
|
||||||
for (const antenna of matchedAntennas) {
|
for (const antenna of matchedAntennas) {
|
||||||
this.fanoutTimelineService.push(`antennaTimeline:${antenna.id}`, note.id, 200, redisPipeline);
|
this.fanoutTimelineService.push(`antennaTimeline:${antenna.id}`, note.id, antennaNotesLimit, redisPipeline);
|
||||||
this.globalEventService.publishAntennaStream(antenna.id, 'note', note);
|
this.globalEventService.publishAntennaStream(antenna.id, 'note', note);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -57,6 +57,7 @@ export type RolePolicies = {
|
||||||
alwaysMarkNsfw: boolean;
|
alwaysMarkNsfw: boolean;
|
||||||
pinLimit: number;
|
pinLimit: number;
|
||||||
antennaLimit: number;
|
antennaLimit: number;
|
||||||
|
antennaNotesLimit: number;
|
||||||
wordMuteLimit: number;
|
wordMuteLimit: number;
|
||||||
webhookLimit: number;
|
webhookLimit: number;
|
||||||
clipLimit: number;
|
clipLimit: number;
|
||||||
|
@ -92,6 +93,7 @@ export const DEFAULT_POLICIES: RolePolicies = {
|
||||||
alwaysMarkNsfw: false,
|
alwaysMarkNsfw: false,
|
||||||
pinLimit: 5,
|
pinLimit: 5,
|
||||||
antennaLimit: 5,
|
antennaLimit: 5,
|
||||||
|
antennaNotesLimit: 200,
|
||||||
wordMuteLimit: 200,
|
wordMuteLimit: 200,
|
||||||
webhookLimit: 3,
|
webhookLimit: 3,
|
||||||
clipLimit: 10,
|
clipLimit: 10,
|
||||||
|
@ -366,6 +368,7 @@ export class RoleService implements OnApplicationShutdown, OnModuleInit {
|
||||||
alwaysMarkNsfw: calc('alwaysMarkNsfw', vs => vs.some(v => v === true)),
|
alwaysMarkNsfw: calc('alwaysMarkNsfw', vs => vs.some(v => v === true)),
|
||||||
pinLimit: calc('pinLimit', vs => Math.max(...vs)),
|
pinLimit: calc('pinLimit', vs => Math.max(...vs)),
|
||||||
antennaLimit: calc('antennaLimit', vs => Math.max(...vs)),
|
antennaLimit: calc('antennaLimit', vs => Math.max(...vs)),
|
||||||
|
antennaNotesLimit: calc('antennaNotesLimit', vs => Math.max(...vs)),
|
||||||
wordMuteLimit: calc('wordMuteLimit', vs => Math.max(...vs)),
|
wordMuteLimit: calc('wordMuteLimit', vs => Math.max(...vs)),
|
||||||
webhookLimit: calc('webhookLimit', vs => Math.max(...vs)),
|
webhookLimit: calc('webhookLimit', vs => Math.max(...vs)),
|
||||||
clipLimit: calc('clipLimit', vs => Math.max(...vs)),
|
clipLimit: calc('clipLimit', vs => Math.max(...vs)),
|
||||||
|
|
|
@ -247,6 +247,10 @@ export const packedRolePoliciesSchema = {
|
||||||
type: 'integer',
|
type: 'integer',
|
||||||
optional: false, nullable: false,
|
optional: false, nullable: false,
|
||||||
},
|
},
|
||||||
|
antennaNotesLimit: {
|
||||||
|
type: 'integer',
|
||||||
|
optional: false, nullable: false,
|
||||||
|
},
|
||||||
wordMuteLimit: {
|
wordMuteLimit: {
|
||||||
type: 'integer',
|
type: 'integer',
|
||||||
optional: false, nullable: false,
|
optional: false, nullable: false,
|
||||||
|
|
|
@ -96,6 +96,7 @@ export const ROLE_POLICIES = [
|
||||||
'alwaysMarkNsfw',
|
'alwaysMarkNsfw',
|
||||||
'pinLimit',
|
'pinLimit',
|
||||||
'antennaLimit',
|
'antennaLimit',
|
||||||
|
'antennaNotesLimit',
|
||||||
'wordMuteLimit',
|
'wordMuteLimit',
|
||||||
'webhookLimit',
|
'webhookLimit',
|
||||||
'clipLimit',
|
'clipLimit',
|
||||||
|
|
|
@ -556,6 +556,25 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
</div>
|
</div>
|
||||||
</MkFolder>
|
</MkFolder>
|
||||||
|
|
||||||
|
<MkFolder v-if="matchQuery([i18n.ts._role._options.antennaNotesMax, 'antennaNotesLimit'])">
|
||||||
|
<template #label>{{ i18n.ts._role._options.antennaNotesMax }}</template>
|
||||||
|
<template #suffix>
|
||||||
|
<span v-if="role.policies.antennaNotesLimit.useDefault" :class="$style.useDefaultLabel">{{ i18n.ts._role.useBaseValue }}</span>
|
||||||
|
<span v-else>{{ role.policies.antennaNotesLimit.value }}</span>
|
||||||
|
<span :class="$style.priorityIndicator"><i :class="getPriorityIcon(role.policies.antennaNotesLimit)"></i></span>
|
||||||
|
</template>
|
||||||
|
<div class="_gaps">
|
||||||
|
<MkSwitch v-model="role.policies.antennaNotesLimit.useDefault" :readonly="readonly">
|
||||||
|
<template #label>{{ i18n.ts._role.useBaseValue }}</template>
|
||||||
|
</MkSwitch>
|
||||||
|
<MkInput v-model="role.policies.antennaNotesLimit.value" :disabled="role.policies.antennaNotesLimit.useDefault" type="number" :readonly="readonly">
|
||||||
|
</MkInput>
|
||||||
|
<MkRange v-model="role.policies.antennaNotesLimit.priority" :min="0" :max="2" :step="1" easing :textConverter="(v) => v === 0 ? i18n.ts._role._priority.low : v === 1 ? i18n.ts._role._priority.middle : v === 2 ? i18n.ts._role._priority.high : ''">
|
||||||
|
<template #label>{{ i18n.ts._role.priority }}</template>
|
||||||
|
</MkRange>
|
||||||
|
</div>
|
||||||
|
</MkFolder>
|
||||||
|
|
||||||
<MkFolder v-if="matchQuery([i18n.ts._role._options.wordMuteMax, 'wordMuteLimit'])">
|
<MkFolder v-if="matchQuery([i18n.ts._role._options.wordMuteMax, 'wordMuteLimit'])">
|
||||||
<template #label>{{ i18n.ts._role._options.wordMuteMax }}</template>
|
<template #label>{{ i18n.ts._role._options.wordMuteMax }}</template>
|
||||||
<template #suffix>
|
<template #suffix>
|
||||||
|
|
|
@ -204,6 +204,13 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
</MkInput>
|
</MkInput>
|
||||||
</MkFolder>
|
</MkFolder>
|
||||||
|
|
||||||
|
<MkFolder v-if="matchQuery([i18n.ts._role._options.antennaNotesMax, 'antennaNotesLimit'])">
|
||||||
|
<template #label>{{ i18n.ts._role._options.antennaNotesMax }}</template>
|
||||||
|
<template #suffix>{{ policies.antennaNotesLimit }}</template>
|
||||||
|
<MkInput v-model="policies.antennaNotesLimit" type="number">
|
||||||
|
</MkInput>
|
||||||
|
</MkFolder>
|
||||||
|
|
||||||
<MkFolder v-if="matchQuery([i18n.ts._role._options.wordMuteMax, 'wordMuteLimit'])">
|
<MkFolder v-if="matchQuery([i18n.ts._role._options.wordMuteMax, 'wordMuteLimit'])">
|
||||||
<template #label>{{ i18n.ts._role._options.wordMuteMax }}</template>
|
<template #label>{{ i18n.ts._role._options.wordMuteMax }}</template>
|
||||||
<template #suffix>{{ policies.wordMuteLimit }}</template>
|
<template #suffix>{{ policies.wordMuteLimit }}</template>
|
||||||
|
|
|
@ -4824,6 +4824,7 @@ export type components = {
|
||||||
alwaysMarkNsfw: boolean;
|
alwaysMarkNsfw: boolean;
|
||||||
pinLimit: number;
|
pinLimit: number;
|
||||||
antennaLimit: number;
|
antennaLimit: number;
|
||||||
|
antennaNotesLimit: number;
|
||||||
wordMuteLimit: number;
|
wordMuteLimit: number;
|
||||||
webhookLimit: number;
|
webhookLimit: number;
|
||||||
clipLimit: number;
|
clipLimit: number;
|
||||||
|
|
Loading…
Reference in New Issue