Enhance tag management with cooldown feature and related updates
- Added a `cooldownSeconds` field to the `Tag` model, allowing for customizable cooldown periods between tag responses. - Updated tag command handling to incorporate cooldown logic, preventing spam and improving user experience. - Enhanced the WebUI to support cooldown configuration for tags, including input validation and localization for cooldown messages. - Refactored tag-related service functions to manage cooldowns effectively, ensuring accurate tracking and enforcement. - Improved localization for new cooldown-related messages in both English and German.
This commit is contained in:
@@ -157,6 +157,19 @@ describe('dashboard schemas', () => {
|
||||
allowedChannelIds: []
|
||||
});
|
||||
expect(parsed.name).toBe('rules');
|
||||
expect(parsed.cooldownSeconds).toBe(15);
|
||||
});
|
||||
|
||||
it('accepts custom tag cooldown', () => {
|
||||
const parsed = TagDashboardCreateSchema.parse({
|
||||
name: 'rules',
|
||||
content: 'Please read the rules',
|
||||
responseType: 'TEXT',
|
||||
cooldownSeconds: 30,
|
||||
allowedRoleIds: [],
|
||||
allowedChannelIds: []
|
||||
});
|
||||
expect(parsed.cooldownSeconds).toBe(30);
|
||||
});
|
||||
|
||||
it('validates starboard patches', () => {
|
||||
|
||||
@@ -516,6 +516,8 @@ export const TagDashboardSchema = z.object({
|
||||
components: MessageComponentsV2Schema.nullable().optional(),
|
||||
responseType: TagResponseTypeSchema,
|
||||
triggerWord: z.string().max(100).nullable().optional(),
|
||||
/** Seconds between auto-responder /tag replies; 0 disables. Default 15. */
|
||||
cooldownSeconds: z.number().int().min(0).max(3600).default(15),
|
||||
allowedRoleIds: z.array(z.string()),
|
||||
allowedChannelIds: z.array(z.string())
|
||||
});
|
||||
|
||||
@@ -566,12 +566,15 @@ const de: Dictionary = {
|
||||
'tag.info.uses': 'Aufrufe: {count}',
|
||||
'tag.info.trigger': 'Trigger: `{word}`',
|
||||
'tag.info.noTrigger': 'Kein Auto-Responder.',
|
||||
'tag.info.cooldown': 'Cooldown: {seconds}s',
|
||||
'tag.info.noCooldown': 'Cooldown: aus',
|
||||
'tag.info.roles': 'Rollen: {roles}',
|
||||
'tag.info.allRoles': 'Rollen: alle',
|
||||
'tag.info.channels': 'Kanäle: {channels}',
|
||||
'tag.info.allChannels': 'Kanäle: alle',
|
||||
'tag.error.not_found': 'Tag nicht gefunden.',
|
||||
'tag.error.not_allowed': 'Du darfst diesen Tag hier nicht nutzen.',
|
||||
'tag.error.cooldown': 'Cooldown aktiv. Versuche es in {seconds} Sekunden erneut.',
|
||||
'tag.error.invalid_name': 'Ungültiger Tag-Name (1–32 Zeichen, a-z, 0-9, _, -).',
|
||||
'tag.error.content_required': 'Text-Tags benötigen Inhalt.',
|
||||
'tag.error.embed_required': 'Embed-Tags benötigen Titel oder Beschreibung.',
|
||||
@@ -1179,12 +1182,15 @@ const en: Dictionary = {
|
||||
'tag.info.uses': 'Uses: {count}',
|
||||
'tag.info.trigger': 'Trigger: `{word}`',
|
||||
'tag.info.noTrigger': 'No auto-responder.',
|
||||
'tag.info.cooldown': 'Cooldown: {seconds}s',
|
||||
'tag.info.noCooldown': 'Cooldown: off',
|
||||
'tag.info.roles': 'Roles: {roles}',
|
||||
'tag.info.allRoles': 'Roles: all',
|
||||
'tag.info.channels': 'Channels: {channels}',
|
||||
'tag.info.allChannels': 'Channels: all',
|
||||
'tag.error.not_found': 'Tag not found.',
|
||||
'tag.error.not_allowed': 'You are not allowed to use this tag here.',
|
||||
'tag.error.cooldown': 'Cooldown active. Try again in {seconds} seconds.',
|
||||
'tag.error.invalid_name': 'Invalid tag name (1–32 chars, a-z, 0-9, _, -).',
|
||||
'tag.error.content_required': 'Text tags require content.',
|
||||
'tag.error.embed_required': 'Embed tags require a title or description.',
|
||||
|
||||
Reference in New Issue
Block a user