Files
AuroraBot-discord/bot/modules/moderation/moderation.view.ts
2026-01-08 16:09:26 +01:00

242 lines
7.5 KiB
TypeScript

import { EmbedBuilder, Colors, time, TimestampStyles } from "discord.js";
import type { ModerationCase } from "./moderation.types";
/**
* Get color based on case type
*/
function getCaseColor(type: string): number {
switch (type) {
case 'warn': return Colors.Yellow;
case 'timeout': return Colors.Orange;
case 'kick': return Colors.Red;
case 'ban': return Colors.DarkRed;
case 'note': return Colors.Blue;
case 'prune': return Colors.Grey;
default: return Colors.Grey;
}
}
/**
* Get emoji based on case type
*/
function getCaseEmoji(type: string): string {
switch (type) {
case 'warn': return '⚠️';
case 'timeout': return '🔇';
case 'kick': return '👢';
case 'ban': return '🔨';
case 'note': return '📝';
case 'prune': return '🧹';
default: return '📋';
}
}
/**
* Display a single case
*/
export function getCaseEmbed(moderationCase: ModerationCase): EmbedBuilder {
const emoji = getCaseEmoji(moderationCase.type);
const color = getCaseColor(moderationCase.type);
const embed = new EmbedBuilder()
.setTitle(`${emoji} Case ${moderationCase.caseId}`)
.setColor(color)
.addFields(
{ name: 'Type', value: moderationCase.type.toUpperCase(), inline: true },
{ name: 'Status', value: moderationCase.active ? '🟢 Active' : '⚫ Resolved', inline: true },
{ name: '\u200B', value: '\u200B', inline: true },
{ name: 'User', value: `${moderationCase.username} (${moderationCase.userId})`, inline: false },
{ name: 'Moderator', value: moderationCase.moderatorName, inline: true },
{ name: 'Date', value: time(moderationCase.createdAt, TimestampStyles.ShortDateTime), inline: true }
)
.addFields({ name: 'Reason', value: moderationCase.reason })
.setTimestamp(moderationCase.createdAt);
// Add resolution info if resolved
if (!moderationCase.active && moderationCase.resolvedAt) {
embed.addFields(
{ name: '\u200B', value: '**Resolution**' },
{ name: 'Resolved At', value: time(moderationCase.resolvedAt, TimestampStyles.ShortDateTime), inline: true }
);
if (moderationCase.resolvedReason) {
embed.addFields({ name: 'Resolution Reason', value: moderationCase.resolvedReason });
}
}
// Add metadata if present
if (moderationCase.metadata && Object.keys(moderationCase.metadata).length > 0) {
const metadataStr = JSON.stringify(moderationCase.metadata, null, 2);
if (metadataStr.length < 1024) {
embed.addFields({ name: 'Additional Info', value: `\`\`\`json\n${metadataStr}\n\`\`\`` });
}
}
return embed;
}
/**
* Display a list of cases
*/
export function getCasesListEmbed(
cases: ModerationCase[],
title: string,
description?: string
): EmbedBuilder {
const embed = new EmbedBuilder()
.setTitle(title)
.setColor(Colors.Blue)
.setTimestamp();
if (description) {
embed.setDescription(description);
}
if (cases.length === 0) {
embed.setDescription('No cases found.');
return embed;
}
// Group by type for better display
const casesByType: Record<string, ModerationCase[]> = {};
for (const c of cases) {
if (!casesByType[c.type]) {
casesByType[c.type] = [];
}
casesByType[c.type]!.push(c);
}
// Add fields for each type
for (const [type, typeCases] of Object.entries(casesByType)) {
const emoji = getCaseEmoji(type);
const caseList = typeCases.slice(0, 5).map(c => {
const status = c.active ? '🟢' : '⚫';
const date = time(c.createdAt, TimestampStyles.ShortDate);
return `${status} **${c.caseId}** - ${c.reason.substring(0, 50)}${c.reason.length > 50 ? '...' : ''} (${date})`;
}).join('\n');
embed.addFields({
name: `${emoji} ${type.toUpperCase()} (${typeCases.length})`,
value: caseList || 'None',
inline: false
});
if (typeCases.length > 5) {
embed.addFields({
name: '\u200B',
value: `_...and ${typeCases.length - 5} more_`,
inline: false
});
}
}
return embed;
}
/**
* Display user's active warnings
*/
export function getWarningsEmbed(warnings: ModerationCase[], username: string): EmbedBuilder {
const embed = new EmbedBuilder()
.setTitle(`⚠️ Active Warnings for ${username}`)
.setColor(Colors.Yellow)
.setTimestamp();
if (warnings.length === 0) {
embed.setDescription('No active warnings.');
return embed;
}
embed.setDescription(`**Total Active Warnings:** ${warnings.length}`);
for (const warning of warnings.slice(0, 10)) {
const date = time(warning.createdAt, TimestampStyles.ShortDateTime);
embed.addFields({
name: `${warning.caseId} - ${date}`,
value: `**Moderator:** ${warning.moderatorName}\n**Reason:** ${warning.reason}`,
inline: false
});
}
if (warnings.length > 10) {
embed.addFields({
name: '\u200B',
value: `_...and ${warnings.length - 10} more warnings. Use \`/cases\` to view all._`,
inline: false
});
}
return embed;
}
/**
* Success message after warning a user
*/
export function getWarnSuccessEmbed(caseId: string, username: string, reason: string): EmbedBuilder {
return new EmbedBuilder()
.setTitle('✅ Warning Issued')
.setDescription(`**${username}** has been warned.`)
.addFields(
{ name: 'Case ID', value: caseId, inline: true },
{ name: 'Reason', value: reason, inline: false }
)
.setColor(Colors.Green)
.setTimestamp();
}
/**
* Success message after adding a note
*/
export function getNoteSuccessEmbed(caseId: string, username: string): EmbedBuilder {
return new EmbedBuilder()
.setTitle('✅ Note Added')
.setDescription(`Staff note added for **${username}**.`)
.addFields({ name: 'Case ID', value: caseId, inline: true })
.setColor(Colors.Green)
.setTimestamp();
}
/**
* Success message after clearing a warning
*/
export function getClearSuccessEmbed(caseId: string): EmbedBuilder {
return new EmbedBuilder()
.setTitle('✅ Warning Cleared')
.setDescription(`Case **${caseId}** has been resolved.`)
.setColor(Colors.Green)
.setTimestamp();
}
/**
* Error embed for moderation operations
*/
export function getModerationErrorEmbed(message: string): EmbedBuilder {
return new EmbedBuilder()
.setTitle('❌ Error')
.setDescription(message)
.setColor(Colors.Red)
.setTimestamp();
}
/**
* Warning embed to send to user via DM
*/
export function getUserWarningEmbed(
serverName: string,
reason: string,
caseId: string,
warningCount: number
): EmbedBuilder {
return new EmbedBuilder()
.setTitle('⚠️ You have received a warning')
.setDescription(`You have been warned in **${serverName}**.`)
.addFields(
{ name: 'Reason', value: reason, inline: false },
{ name: 'Case ID', value: caseId, inline: true },
{ name: 'Total Warnings', value: warningCount.toString(), inline: true }
)
.setColor(Colors.Yellow)
.setTimestamp()
.setFooter({ text: 'Please review the server rules to avoid further action.' });
}