const { SlashCommandBuilder, MessageFlags, EmbedBuilder } = require("discord.js"); const { reconcileUserAchievements, reconcileAllAchievements, grantMaintenanceReward, getMaintenanceRewardStatus, auditProfileData, DEFAULT_MAINTENANCE_REWARD_ID, DEFAULT_MAINTENANCE_REWARD_AMOUNT } = require( "../../utils/profileMaintenance" ); const { requireAdminAccess } = require( "../../utils/permissions" ); module.exports = { data: new SlashCommandBuilder() .setName( "profileadmin" ) .setDescription( "Administrative profile maintenance tools" ) .addSubcommand( subcommand => subcommand .setName( "reconcile" ) .setDescription( "Backfill database-trackable achievements" ) .addUserOption( option => option .setName( "user" ) .setDescription( "Only reconcile this user; omit for everyone" ) ) .addBooleanOption( option => option .setName( "dry-run" ) .setDescription( "Show what would change without writing it" ) ) ) .addSubcommand( subcommand => subcommand .setName( "audit" ) .setDescription( "Audit stored profile statistics for inconsistencies" ) ) .addSubcommand( subcommand => subcommand .setName( "maintenance-reward" ) .setDescription( "Grant an idempotent maintenance reward to stored profile users" ) .addStringOption( option => option .setName( "reward-id" ) .setDescription( `Unique reward ID; defaults to ${DEFAULT_MAINTENANCE_REWARD_ID}` ) ) .addIntegerOption( option => option .setName( "amount" ) .setDescription( `Cookies per player; defaults to ${DEFAULT_MAINTENANCE_REWARD_AMOUNT}` ) .setMinValue( 1 ) ) .addBooleanOption( option => option .setName( "dry-run" ) .setDescription( "Preview recipients without granting Cookies" ) ) ) .addSubcommand( subcommand => subcommand .setName( "maintenance-status" ) .setDescription( "Show maintenance reward claim status" ) .addStringOption( option => option .setName( "reward-id" ) .setDescription( `Reward ID; defaults to ${DEFAULT_MAINTENANCE_REWARD_ID}` ) ) ), async execute( interaction ) { /* * Allows: * * - Discord Administrators * - BOT_AUTHOR_ID from .env */ if ( !await requireAdminAccess( interaction ) ) { return; } const subcommand = interaction.options.getSubcommand(); await interaction.deferReply({ flags: MessageFlags.Ephemeral }); try { if ( subcommand === "reconcile" ) { const user = interaction.options.getUser( "user" ); const dryRun = interaction.options.getBoolean( "dry-run" ) ?? false; if (user) { const result = await reconcileUserAchievements({ guildId: interaction.guildId, userId: user.id, dryRun }); return interaction.editReply({ embeds: [ new EmbedBuilder() .setTitle( "๐Ÿ› ๏ธ Profile Reconciliation" ) .setDescription( `${dryRun ? "Dry run for" : "Reconciled"} ${user}.` ) .addFields( { name: "New unlocks", value: `**${result.unlocked}**`, inline: true }, { name: "Definitions checked", value: `**${result.checked}**`, inline: true }, { name: "Event-only skipped", value: `**${result.skippedEventOnly}**`, inline: true } ) ] }); } const summary = await reconcileAllAchievements({ guildId: interaction.guildId, dryRun }); return interaction.editReply({ embeds: [ new EmbedBuilder() .setTitle( "๐Ÿ› ๏ธ Profile Reconciliation" ) .setDescription( `${dryRun ? "Dry run completed" : "Reconciliation completed"} for stored profile users.` ) .addFields( { name: "Users", value: `**${summary.users}**`, inline: true }, { name: "New unlocks", value: `**${summary.unlocked}**`, inline: true }, { name: "Event-only checks skipped", value: `**${summary.skippedEventOnly}**`, inline: true } ) ] }); } if ( subcommand === "maintenance-reward" ) { const rewardId = interaction.options.getString( "reward-id" ) ?? DEFAULT_MAINTENANCE_REWARD_ID; const amount = interaction.options.getInteger( "amount" ) ?? DEFAULT_MAINTENANCE_REWARD_AMOUNT; /* * Safer admin default: * * If omitted, maintenance-reward previews * instead of paying immediately. * * Pass dry-run:false explicitly to execute. */ const dryRun = interaction.options.getBoolean( "dry-run" ) ?? true; const summary = await grantMaintenanceReward({ guildId: interaction.guildId, rewardId, amount, dryRun }); return interaction.editReply({ embeds: [ new EmbedBuilder() .setTitle( dryRun ? "๐Ÿงช Maintenance Reward Dry Run" : "๐ŸŽ Maintenance Reward" ) .setDescription( dryRun ? "No Cookies were granted. Run again with `dry-run:false` to execute this reward." : `Maintenance compensation **${rewardId}** has been processed.` ) .addFields( { name: "Reward ID", value: `\`${summary.rewardId}\``, inline: false }, { name: "Per player", value: `**${summary.amount.toLocaleString()} ๐Ÿช**`, inline: true }, { name: "Stored profiles", value: `**${summary.users}**`, inline: true }, { name: dryRun ? "Would receive" : "Granted", value: `**${dryRun ? summary.eligible : summary.granted}**`, inline: true }, { name: "Already claimed", value: `**${summary.alreadyClaimed}**`, inline: true }, { name: "Failed", value: `**${summary.failed}**`, inline: true } ) ] }); } if ( subcommand === "maintenance-status" ) { const rewardId = interaction.options.getString( "reward-id" ) ?? DEFAULT_MAINTENANCE_REWARD_ID; const status = await getMaintenanceRewardStatus({ guildId: interaction.guildId, rewardId }); return interaction.editReply({ embeds: [ new EmbedBuilder() .setTitle( "๐ŸŽ Maintenance Reward Status" ) .addFields( { name: "Reward ID", value: `\`${status.rewardId}\``, inline: false }, { name: "Default amount", value: `**${status.amount.toLocaleString()} ๐Ÿช**`, inline: true }, { name: "Stored profiles", value: `**${status.users}**`, inline: true }, { name: "Claimed", value: `**${status.claimed}**`, inline: true }, { name: "Remaining", value: `**${status.remaining}**`, inline: true } ) ] }); } const audit = await auditProfileData( interaction.guildId ); const issuePreview = audit.issues .slice( 0, 10 ) .join( "\n" ); return interaction.editReply({ embeds: [ new EmbedBuilder() .setTitle( "๐Ÿ”Ž Profile Data Audit" ) .addFields( { name: "Stats documents", value: `**${audit.statDocuments}**`, inline: true }, { name: "Achievement documents", value: `**${audit.achievementDocuments}**`, inline: true }, { name: "Active achievements", value: `**${audit.activeAchievements}**`, inline: true }, { name: "Global badges", value: `**${audit.badgeDocuments}** (${audit.claimedBadges} claimed)`, inline: true }, { name: "Orphan achievement docs", value: `**${audit.orphanAchievementDocs}**`, inline: true }, { name: "Issues", value: `**${audit.issueCount}**`, inline: true } ) .setDescription( issuePreview ? `First issues:\n${issuePreview}` : "No structural inconsistencies found." ) ] }); } catch (error) { console.error( `[ProfileAdmin] ${subcommand} failed:`, error ); return interaction.editReply({ embeds: [ new EmbedBuilder() .setTitle( "โŒ Profile Admin Error" ) .setDescription( "The maintenance action failed. Check the bot logs for details." ) ] }); } } };