Add backup functionality with escalation rules for moderation commands
- Updated .env.example to include backup configuration options. - Modified docker-compose.yml to mount backup volume. - Enhanced Dockerfile to install PostgreSQL client. - Added EscalationRule model to Prisma schema for managing warning escalation. - Updated environment validation in env.ts to include backup settings. - Refactored job handling in jobs.ts to implement backup jobs and cleanup. - Introduced escalation commands in moderation service for managing user warnings. - Updated moderation commands to apply escalation rules based on warning count.
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
import { moderationQueue } from '../../jobs.js';
|
||||
import type { BotContext } from '../../types.js';
|
||||
import { PermissionFlagsBits, type ChatInputCommandInteraction } from 'discord.js';
|
||||
|
||||
type CreateCaseInput = {
|
||||
guildId: string;
|
||||
@@ -11,6 +12,12 @@ type CreateCaseInput = {
|
||||
};
|
||||
|
||||
export async function createCase(context: BotContext, input: CreateCaseInput) {
|
||||
await context.prisma.guild.upsert({
|
||||
where: { id: input.guildId },
|
||||
update: {},
|
||||
create: { id: input.guildId }
|
||||
});
|
||||
|
||||
const lastCase = await context.prisma.case.findFirst({
|
||||
where: { guildId: input.guildId },
|
||||
orderBy: { caseNumber: 'desc' }
|
||||
@@ -45,3 +52,79 @@ export async function scheduleTempBanExpire(
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
export async function applyWarnEscalation(
|
||||
interaction: ChatInputCommandInteraction,
|
||||
context: BotContext,
|
||||
userId: string,
|
||||
moderatorId: string
|
||||
): Promise<string | null> {
|
||||
const guildId = interaction.guildId;
|
||||
if (!guildId || !interaction.guild) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const warningCount = await context.prisma.warning.count({
|
||||
where: { guildId, userId }
|
||||
});
|
||||
|
||||
const rule = await context.prisma.escalationRule.findUnique({
|
||||
where: { guildId_warnCount: { guildId, warnCount: warningCount } }
|
||||
});
|
||||
|
||||
if (!rule || !rule.enabled) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const member = await interaction.guild.members.fetch(userId);
|
||||
const reason = rule.reason ?? `Auto escalation at ${warningCount} warnings`;
|
||||
|
||||
if (rule.action === 'TIMEOUT') {
|
||||
if (!rule.durationMs) {
|
||||
return `Escalation rule for ${warningCount} warns skipped (missing duration).`;
|
||||
}
|
||||
if (!interaction.guild.members.me?.permissions.has(PermissionFlagsBits.ModerateMembers)) {
|
||||
return `Escalation rule for ${warningCount} warns skipped (missing bot permissions).`;
|
||||
}
|
||||
await member.timeout(rule.durationMs, reason);
|
||||
await createCase(context, {
|
||||
guildId,
|
||||
targetUserId: userId,
|
||||
moderatorId,
|
||||
action: 'TIMEOUT',
|
||||
reason,
|
||||
metadata: { escalation: true, durationMs: rule.durationMs, warningCount }
|
||||
});
|
||||
return `Auto escalation applied: timeout (${rule.durationMs} ms).`;
|
||||
}
|
||||
|
||||
if (rule.action === 'KICK') {
|
||||
if (!interaction.guild.members.me?.permissions.has(PermissionFlagsBits.KickMembers)) {
|
||||
return `Escalation rule for ${warningCount} warns skipped (missing bot permissions).`;
|
||||
}
|
||||
await member.kick(reason);
|
||||
await createCase(context, {
|
||||
guildId,
|
||||
targetUserId: userId,
|
||||
moderatorId,
|
||||
action: 'KICK',
|
||||
reason,
|
||||
metadata: { escalation: true, warningCount }
|
||||
});
|
||||
return 'Auto escalation applied: kick.';
|
||||
}
|
||||
|
||||
if (!interaction.guild.members.me?.permissions.has(PermissionFlagsBits.BanMembers)) {
|
||||
return `Escalation rule for ${warningCount} warns skipped (missing bot permissions).`;
|
||||
}
|
||||
await interaction.guild.members.ban(userId, { reason });
|
||||
await createCase(context, {
|
||||
guildId,
|
||||
targetUserId: userId,
|
||||
moderatorId,
|
||||
action: 'BAN',
|
||||
reason,
|
||||
metadata: { escalation: true, warningCount }
|
||||
});
|
||||
return 'Auto escalation applied: ban.';
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user