105 lines
No EOL
2.8 KiB
JavaScript
105 lines
No EOL
2.8 KiB
JavaScript
/**
|
|
* 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<Object>} 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
|
|
}; |