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 = {}; 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.' }); }