// src/handlers/adminHandler.js const logger = require('../logger'); const whatsapp = require('../services/whatsappService'); const { User } = require('../database'); const config = require('../config'); // State to track pending admin actions requiring confirmation // Key: adminJid, Value: { action: 'confirm_clear', semester: '...', timeoutId: ... } const adminState = {}; const CONFIRMATION_TIMEOUT = 60000; // 60 seconds /** * Clears the pending state for an admin. * @param {string} jid - Admin JID. */ function clearAdminState(jid) { if (adminState[jid]) { clearTimeout(adminState[jid].timeoutId); // Clear the timeout delete adminState[jid]; logger.info({ adminJid: jid }, `[AdminHandler] Cleared pending admin state.`); } } /** * Handles commands sent by recognized admins, including confirmation steps. * Returns true if an admin command (or confirmation) was processed, false otherwise. */ async function handleAdminCommand(jid, messageContent) { logger.debug({ adminJid: jid, command: messageContent }, `[AdminHandler] Processing potential admin command.`); const pendingAction = adminState[jid]; // --- Step 1: Check if awaiting confirmation --- if (pendingAction) { const confirmation = messageContent.trim().toLowerCase(); const semesterToDelete = pendingAction.semester; // Get semester from stored state if (pendingAction.action === 'confirm_clear') { if (confirmation === 'yes') { logger.warn({ adminJid: jid, semester: semesterToDelete }, `[AdminHandler] Confirmation 'yes' received for .clear`); clearAdminState(jid); // Clear state before performing action try { const deleteResult = await User.deleteMany({ semester: { $regex: new RegExp(`^${semesterToDelete}$`, 'i') } }); const replyText = `✅ Admin: Successfully deleted ${deleteResult.deletedCount} records matching semester "${semesterToDelete}".`; logger.warn({ result: deleteResult, semester: semesterToDelete }, `[AdminHandler] .clear command executed successfully.`); await whatsapp.sendMessageWithTyping(jid, { text: replyText }); } catch (cmdError) { logger.error({ err: cmdError, semester: semesterToDelete }, `[AdminHandler] .clear command failed during execution.`); await whatsapp.sendMessageWithTyping(jid, { text: `❌ Admin: Error executing .clear command for semester "${semesterToDelete}" after confirmation. Check logs.` }); } } else { // Includes 'no' or any other reply logger.info({ adminJid: jid, semester: pendingAction.semester, reply: confirmation }, `[AdminHandler] .clear command aborted by admin or invalid confirmation.`); clearAdminState(jid); await whatsapp.sendMessageWithTyping(jid, { text: `❌ Admin: Aborted deletion for semester "${semesterToDelete}".` }); } } else { // Handle other potential pending actions here if added later logger.warn({ adminJid: jid, pendingAction }, `[AdminHandler] Unknown pending action found.`); clearAdminState(jid); // Clear unknown state } return true; // Confirmation message was processed } // --- Step 2: Check for new commands if not awaiting confirmation --- // ** .clear command ** if (messageContent.startsWith('.clear ')) { const parts = messageContent.split(' '); if (parts.length === 2 && parts[1]) { const semesterToDelete = parts[1].trim(); logger.warn({ adminJid: jid, semester: semesterToDelete }, `[AdminHandler] .clear command received. Requesting confirmation.`); // Set pending state with timeout adminState[jid] = { action: 'confirm_clear', semester: semesterToDelete, timeoutId: setTimeout(() => { if (adminState[jid]?.action === 'confirm_clear') { // Check if still pending this action logger.warn({ adminJid: jid, semester: semesterToDelete }, `[AdminHandler] Confirmation for .clear timed out.`); delete adminState[jid]; // Clear state on timeout whatsapp.sendMessageWithTyping(jid, { text: `⏰ Admin: Confirmation request for deleting semester "${semesterToDelete}" timed out.` }).catch(err => logger.error({err}, "Failed to send timeout message")); } }, CONFIRMATION_TIMEOUT) }; // Ask for confirmation const promptText = `❓ *Confirmation Needed* ❓\n\nAre you sure you want to delete ALL student data for semester *${semesterToDelete}*? This cannot be undone.\n\nReply with *Yes* or *No*. (Expires in 60 seconds)`; await whatsapp.sendMessageWithTyping(jid, { text: promptText }); } else { // Invalid format await whatsapp.sendMessageWithTyping(jid, { text: `❌ Admin: Invalid .clear command format. Use: \`.clear \` (e.g., \`.clear 3rd\`)` }); } return true; // .clear command attempt was handled } // --- Add other admin commands here --- // else if (messageContent.startsWith('.some_other_command')) { // logger.info({ adminJid: jid }, `[AdminHandler] Handling other admin command.`); // ... handle command ... // return true; // } // If no known admin command matched logger.debug({ adminJid: jid, command: messageContent }, `[AdminHandler] Not a recognized admin command.`); return false; // No admin command was processed } module.exports = { handleAdminCommand };