All files / src/handlers AdminCommandHandler.js

97.91% Statements 47/48
85.71% Branches 12/14
100% Functions 10/10
97.82% Lines 45/46

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139              16x       2x   2x 1x         3x 1x 2x 1x         2x 2x 1x 1x       1x 1x 1x   1x                     1x     1x 1x         4x   4x 4x 3x 3x 9x 6x   3x     3x 3x 3x 3x 3x 3x       4x                               4x       4x   4x 4x 3x 3x 6x 9x       4x                                               4x       7x
/**
 * AdminCommandHandler - Handles administrative commands
 * Provides system information and help commands for debugging and user guidance
 * These utilities help operators monitor bot health and assist users with command syntax
 */
class AdminCommandHandler {
    constructor(bot) {
        this.bot = bot;
    }
 
    async handleModeratorCommand(message, member, content) {
        Iif (content === '!ping') {
            await this.handlePing(message);
        } else if (content === '!help') {
            await this.handleModeratorHelp(message);
        }
    }
 
    async handleMemberCommand(message, member, content) {
        if (content === '!ping') {
            await this.handlePing(message);
        } else if (content === '!help') {
            await this.handleMemberHelp(message);
        }
    }
 
    async handlePing(message) {
        try {
            const botRunId = this.bot.getRunId();
            const uptime = Math.round(process.uptime());
            const timestamp = new Date().toISOString();
            
            // Gather system metrics for deployment monitoring and troubleshooting
            // These metrics help operators understand bot performance and resource usage
            const nodeVersion = process.version;
            const memoryUsage = process.memoryUsage();
            const memoryMB = Math.round(memoryUsage.rss / 1024 / 1024);
            
            await message.reply(`🏓 **Pong!**
 
**Deployment Info:**
🆔 **Run ID:** \`${botRunId}\`
⏰ **Started:** ${timestamp}
⚡ **Uptime:** ${uptime}s
💾 **Memory:** ${memoryMB}MB
🟢 **Node.js:** ${nodeVersion}
 
**Status:** Bot is running and responsive!`);
 
            console.log(`🏓 Ping command executed by ${message.author.tag} - Run ID: ${botRunId}`);
 
        } catch (error) {
            console.error('Error handling ping command:', error);
            await message.reply('❌ An error occurred while processing the ping command.');
        }
    }
 
    async handleMemberHelp(message) {
        const proposalConfig = this.bot.getProposalManager().proposalConfig;
        
        let proposalInfo = '';
        if (proposalConfig) {
            proposalInfo = '\n**🗳️ How to Participate:**\n';
            Object.entries(proposalConfig).forEach(([type, config]) => {
                proposalInfo += `- **${type} proposals**: Post in <#${config.debateChannelId}> using format ${config.formats.map(f => `**${f}**:`).join(' or ')}\n`;
                proposalInfo += `  Need ${config.supportThreshold} ✅ reactions to advance to voting\n`;
            });
            proposalInfo += '\n**Voting**: React ✅ (support) or ❌ (oppose) in vote channels\n';
            
            // Add moderator-specific information if moderator type exists
            Eif (proposalConfig.moderator) {
                proposalInfo += '\n**👑 Moderator Management:**\n';
                proposalInfo += `- **Request moderator role**: Post in <#${proposalConfig.moderator.debateChannelId}> using **Add Moderator**: @username\n`;
                proposalInfo += `- **Remove moderator role**: Post using **Remove Moderator**: @username\n`;
                proposalInfo += `  Need ${proposalConfig.moderator.supportThreshold} ✅ reactions to advance to voting\n`;
                proposalInfo += '  Passed votes will directly add/remove moderator roles\n';
            }
        }
 
        const helpText = `**🤖 Member Bot Commands**
 
**Proposal Information:**
\`!proposals\` - View pending proposals needing support
\`!activevotes\` - View currently active votes  
\`!voteinfo <vote_message_id>\` - Get detailed info about a specific vote
 
**Event Information:**
\`!events\` - View upcoming events (all regions here, area-specific in regional/local channels)
 
**Community Information:**
\`!moderators\` - View current server moderators
\`!help\` - Show this help message
${proposalInfo}
**📋 View passed proposals in the resolutions channels**`;
 
        await message.reply(helpText);
    }
 
    async handleModeratorHelp(message) {
        const proposalConfig = this.bot.getProposalManager().proposalConfig;
        
        let proposalInfo = '';
        if (proposalConfig) {
            proposalInfo = '\n**🗳️ Proposal System:**\nThe bot automatically monitors:\n';
            Object.entries(proposalConfig).forEach(([type, config]) => {
                proposalInfo += `- **${type}**: <#${config.debateChannelId}> (${config.supportThreshold} ✅) → <#${config.voteChannelId}> → <#${config.resolutionsChannelId}>\n`;
                proposalInfo += `  Formats: ${config.formats.map(f => `**${f}**:`).join(', ')}\n`;
            });
        }
 
        const helpText = `**🤖 Moderator Bot Commands**
 
**Proposal Management:**
\`!proposals\` - View pending proposals needing support
\`!activevotes\` - View currently active votes
\`!voteinfo <vote_message_id>\` - Get detailed info about a specific vote
\`!forcevote <vote_message_id>\` - Force end an active vote (emergency)
 
**Event Management:**
\`!addevent @RegionRole @LocationRole "Event Name" | YYYY-MM-DD HH:MM | <link>\` - Add new event
\`!quietaddevent @RegionRole @LocationRole "Event Name" | YYYY-MM-DD HH:MM | <link>\` - Add event without notifications
\`!removeevent @RegionRole @LocationRole "Event Name" | YYYY-MM-DD HH:MM\` - Remove an event
Examples: 
- Add: \`!addevent @London @CentralLondon "Community Meeting" | 2024-08-25 18:00 | https://facebook.com/events/123\`
- Quiet Add: \`!quietaddevent @London @CentralLondon "Private Meeting" | 2024-08-25 18:00 | https://zoom.us/j/123\`
- Remove: \`!removeevent @London @CentralLondon "Community Meeting" | 2024-08-25 18:00\`
 
**Community Information:**
\`!moderators\` - View current server moderators  
\`!ping\` - Check bot status and deployment info
\`!help\` - Show this help message
${proposalInfo}
**👥 Members can use \`!proposals\`, \`!activevotes\`, and \`!voteinfo\` in their bot channel.**`;
 
        await message.reply(helpText);
    }
}
 
module.exports = AdminCommandHandler;