|
|
/** * Base module that all modules extend */
let { logger } = require('../logging'); let message = require('../message'); let { isFunction, getObjectKeysToPrototype } = require('../utility'); let { getConfig, sanitizeConfig } = require('../config');
class AbstractModule { /* Name of the module used in help documentation and logging. */ name = "AbstractModule";
/* Short description of the module functionality. */ description = "Base Module That All Other Modules Extend";
/* A helpful multiline string that defines the module usage */ helpAndUsage = `Example: !abstract_module <command>
!abstract_module <boo> : scares people`
/* The exported command used to invoke the module directly. */ command = "abstract_module";
/* The default method to call when a command word is not recognized. */ defaultCommand = null;
/* The module should be hidden from help and command dialogs. */ hidden = false;
/* This module should receive all messages, regardless of whether the module was directly referenced with a command. */ canHandleIndirectMessages = false;
/* Indicates if the modules needs access to the global config */ needGlobalConfig = false;
/* Indicates if the module requires a readable config file. */ needConfig = false;
/* internal */
/* The global config passed in */ _global_config = null;
/* The loaded config file, if it exists. */ _config = null;
constructor(name, description, command) { this.name = name; this.description = description; this.command = command; this._recognizedCommands = []; this._recognizedCommandMap = new Map(); }
addRecognizedCommand(command, methodName) { this._recognizedCommands.push(command); this._recognizedCommandMap.set(command, methodName); }
getRecognizedCommands() { return this._recognizedCommandMap.keys(); }
getConfigFilePath() { return process.env.NODE_PATH + '/data/' + this.name.toLowerCase().replace(' ', '_') + '-config.json'; }
getConfigSensitiveFields() { return []; }
getGlobal(key, defaultValue = null) { if (this._global_config !== null && typeof this._global_config[key] !== 'undefined') { return this._global_config[key]; } return defaultValue }
get(key, defaultValue = null) { if (this._config !== null && typeof this._config[key] !== 'undefined') { return this._config[key]; } return defaultValue }
/** * Default functionality for receiving and processing a message. * * Override this if the module needs to do more complicated message processing. */ handleMessage(event, room, callback) { logger.debug("[%s] [%s] [%s]", this.name, room.name, event.event.content.body);
let messageBody = event.event.content.body; let bodyParts = messageBody.split(' '); let trigger = bodyParts[0]; let command = bodyParts[1]; var args = []; if (bodyParts.length > 2) { args = bodyParts.slice(2); }
logger.debug("Attempting to call %s with %s", command, args); let responseMessage = this.processMessage(command, ...args);
callback( room, responseMessage ); }
/* Call the command method with the args */ processMessage(command, ...args) { if (this._recognizedCommands.includes(command)) { logger.debug("Calling %s with %s", this._recognizedCommandMap.get(command), args); return this[this._recognizedCommandMap.get(command)](...args); } else { if (this.defaultCommand != null) { logger.debug("Attempting to use default command %s", this.defaultCommand); try { let newArgs = [command].concat(...args); logger.debug("Calling %s with %s", this._recognizedCommandMap.get(this.defaultCommand), newArgs); return this[this._recognizedCommandMap.get(this.defaultCommand)](...newArgs); } catch (e) { logger.error("Error while calling default command %s %s", this.defaultCommand, e); return this.cmd_help(); } } else { logger.debug("Unrecognized command %s", command); return this.cmd_help(); } } }
/* Basic cmd methods */
/* return basic help information,. */ cmd_help(...args) { return message.createBasic(this.helpAndUsage); }
/** * Return the basic config file * * @param {...any} args */ cmd_config(...args) { if (this._config != null) { let configBody = JSON.stringify(sanitizeConfig(this._config, this.getConfigSensitiveFields()), null, 2) return message.createMarkdown(configBody, "```" + configBody + "```"); } return null; } }
let abstractModulePrototype = Object.getPrototypeOf(new AbstractModule('', '', ''));
/* Initialization of a module. */ function init(mod, globalConfig) { logger.debug("Initializing module %s", mod.name); if (mod.needConfig) { logger.debug("Loading config file %s", mod.getConfigFilePath()); try { mod._config = getConfig(mod.getConfigFilePath(), mod.getConfigSensitiveFields()); } catch (e) { logger.error("Module %s needs a valid config file at %s", mod.name, mod.getConfigFilePath()); process.exit(1); } } if (mod.needGlobalConfig) { logger.debug("Bound global config to module %s", mod.name); mod._global_config = globalConfig; } logger.debug("Detecting command methods."); let commandMethods = getObjectKeysToPrototype(mod, abstractModulePrototype, (key) => { return key.startsWith('cmd_') && isFunction(mod[key]); }) // let commandMethods = objectKeys.filter();
logger.debug("Identified command methods: %s", commandMethods); commandMethods.forEach((commandMethodName) => { let command = commandMethodName.substring(4); mod.addRecognizedCommand(command, commandMethodName); }) logger.debug("Bound command methods for %s as %s", mod.name, mod.getRecognizedCommands()); }
exports.AbstractModule = AbstractModule exports.initModule = init;
|