const { SlashCommandBuilder, MessageFlags } = require( "discord.js" ); const { requireAdminAccess } = require( "../../utils/permissions" ); const { reconcileProfileAchievements, auditProfileSystem } = require( "../../utils/profileSystem" ); /* * ============================================================ * COMMAND * ============================================================ */ module.exports = { data: new SlashCommandBuilder() .setName( "profileadmin" ) .setDescription( "Profile and achievement administration." ) /* * ================================================= * RECONCILE * ================================================= */ .addSubcommand( subcommand => subcommand .setName( "reconcile" ) .setDescription( "Re-evaluate stored statistics for achievements." ) .addUserOption( option => option .setName( "user" ) .setDescription( "Only reconcile this user's profile." ) .setRequired( false ) ) .addBooleanOption( option => option .setName( "dry-run" ) .setDescription( "Show what would change without unlocking anything." ) .setRequired( false ) ) ) /* * ================================================= * AUDIT * ================================================= */ .addSubcommand( subcommand => subcommand .setName( "audit" ) .setDescription( "Audit the profile and achievement system." ) ), /* * ======================================================== * EXECUTE * ======================================================== */ async execute( interaction ) { /* * Runtime authorization. * * This intentionally replaces: * * .setDefaultMemberPermissions( * PermissionFlagsBits.Administrator * ) * * so BOT_AUTHOR_ID can also invoke the command. */ if ( !await requireAdminAccess( interaction ) ) { return; } const subcommand = interaction.options .getSubcommand(); switch ( subcommand ) { case "reconcile": return runReconcile( interaction ); case "audit": return runAudit( interaction ); default: return interaction.reply({ content: "Unknown profile administration action.", flags: MessageFlags.Ephemeral }); } } }; /* * ============================================================ * RECONCILE * ============================================================ */ async function runReconcile( interaction ) { const target = interaction.options.getUser( "user" ); const dryRun = interaction.options.getBoolean( "dry-run" ) ?? false; /* * This can touch multiple Mongo documents, * so acknowledge the interaction first. */ await interaction.deferReply({ flags: MessageFlags.Ephemeral }); try { const result = await reconcileProfileAchievements( interaction.guildId, { userId: target?.id ?? null, dryRun } ); const lines = [ dryRun ? "### ๐Ÿ”Ž Profile Reconciliation โ€” Dry Run" : "### โœ… Profile Reconciliation Complete", "", target ? `Target: ${target}` : "Target: **Entire Guild**", "", `Profiles checked: **${result.profilesChecked ?? 0}**`, `Achievement unlocks found: **${result.unlocksFound ?? 0}**` ]; if ( !dryRun ) { lines.push( `Achievements unlocked: **${result.unlocksApplied ?? 0}**` ); } if ( result.skippedEventOnly !== undefined ) { lines.push( `Event-only checks skipped: **${result.skippedEventOnly}**` ); } if ( Array.isArray( result.details ) && result.details.length > 0 ) { const preview = result.details .slice( 0, 15 ) .map( entry => { if ( typeof entry === "string" ) { return `โ€ข ${entry}`; } return ( `โ€ข <@${entry.userId}> โ€” ` + `${entry.achievementName ?? entry.achievementId}` ); } ); lines.push( "", "### Changes", ...preview ); if ( result.details.length > preview.length ) { lines.push( "", `*...and ${result.details.length - preview.length} more.*` ); } } return interaction.editReply({ content: lines.join( "\n" ) }); } catch (error) { console.error( "[ProfileAdmin] Reconciliation failed:", error ); return interaction.editReply({ content: "Profile reconciliation failed. Check the bot logs for details." }); } } /* * ============================================================ * AUDIT * ============================================================ */ async function runAudit( interaction ) { await interaction.deferReply({ flags: MessageFlags.Ephemeral }); try { const result = await auditProfileSystem( interaction.guildId ); const lines = [ "### ๐Ÿงพ Profile System Audit", "", `Profile documents: **${result.profileDocuments ?? 0}**`, `Achievement documents: **${result.achievementDocuments ?? 0}**`, `Active achievement definitions: **${result.activeAchievements ?? 0}**`, `Legacy achievement definitions: **${result.legacyAchievements ?? 0}**`, `Guild badges: **${result.badges ?? 0}**`, `Claimed badges: **${result.claimedBadges ?? 0}**`, `Available badges: **${result.availableBadges ?? 0}**` ]; if ( Array.isArray( result.warnings ) && result.warnings.length > 0 ) { lines.push( "", "### โš ๏ธ Warnings", ...result.warnings.map( warning => `โ€ข ${warning}` ) ); } else { lines.push( "", "โœ… No obvious profile-system issues were found." ); } return interaction.editReply({ content: lines.join( "\n" ) }); } catch (error) { console.error( "[ProfileAdmin] Audit failed:", error ); return interaction.editReply({ content: "Profile audit failed. Check the bot logs for details." }); } }