/** * command_parser.js * * Provides functionality for parsing commands for the Fylgja bot */ const logger = require('../utils/logger'); const FILE_NAME = 'command_parser.js'; // Import language patterns and synonyms const commandPatterns = require('./command_patterns'); /** * Parse a natural language command into a structured command object * * @param {string} commandText - The natural language command text * @returns {Promise} Result object with success flag and parsed command or error message */ const parseCommand = async (commandText) => { try { logger.debug(`${FILE_NAME}: Parsing command: ${commandText}`); if (!commandText || typeof commandText !== 'string') { return { success: false, message: 'Empty or invalid command.' }; } // Convert to lowercase for case-insensitive matching const normalizedCommand = commandText.toLowerCase().trim(); // TODO // Handle help command separately if (normalizedCommand === 'help') { return { success: true, command: { action: 'general', module: 'help', params: [] } }; } // Try to match command against known patterns for (const pattern of commandPatterns) { const match = matchPattern(normalizedCommand, pattern); if (match) { logger.debug(`${FILE_NAME}: Command matched pattern: ${pattern.name}`); return { success: true, command: match }; } } // If we reach here, no pattern matched logger.warn(`${FILE_NAME}: No pattern matched for command: ${commandText}`); return { success: false, message: "I couldn't understand that command. Try `/fylgja help` for examples." }; } catch (error) { logger.error(`${FILE_NAME}: Error parsing command: ${error.message}`); logger.debug(`${FILE_NAME}: Error stack: ${error.stack}`); return { success: false, message: `Error parsing command: ${error.message}` }; } }; /** * Match a command against a pattern * * @param {string} command - The normalized command text * @param {Object} pattern - The pattern object to match against * @returns {Object|null} Parsed command object or null if no match */ const matchPattern = (command, pattern) => { // Check if the command matches the regex pattern const match = pattern.regex.exec(command); if (!match) { return null; } // Extract parameters based on the pattern's parameter mapping const params = []; for (const paramIndex of pattern.params) { if (match[paramIndex]) { params.push(match[paramIndex].trim()); } } // Return the structured command return { action: pattern.action, module: pattern.module, params }; }; module.exports = { parseCommand };