aboutsummaryrefslogtreecommitdiffstats
path: root/server/src/serverLib/CommandManager.js
diff options
context:
space:
mode:
Diffstat (limited to 'server/src/serverLib/CommandManager.js')
-rw-r--r--server/src/serverLib/CommandManager.js201
1 files changed, 105 insertions, 96 deletions
diff --git a/server/src/serverLib/CommandManager.js b/server/src/serverLib/CommandManager.js
index 0c4f0aa..e715c6b 100644
--- a/server/src/serverLib/CommandManager.js
+++ b/server/src/serverLib/CommandManager.js
@@ -1,47 +1,71 @@
-/**
- * Commands / protocol manager- loads, validates and handles command execution
- *
- * Version: v2.0.0
- * Developer: Marzavec ( https://github.com/marzavec )
- * License: WTFPL ( http://www.wtfpl.net/txt/copying/ )
- *
- */
-
-const path = require('path');
-const didYouMean = require('didyoumean2').default;
+import {
+ basename,
+ join,
+ sep,
+ dirname,
+ relative,
+} from 'path';
+import didYouMean from 'didyoumean2';
// default command modules path
const CmdDir = 'src/commands';
+/**
+ * Commands / protocol manager- loads, validates and handles command execution
+ * @property {Array} commands - Array of currently loaded command modules
+ * @property {Array} categories - Array of command modules categories
+ * @author Marzavec ( https://github.com/marzavec )
+ * @version v2.0.0
+ * @license WTFPL ( http://www.wtfpl.net/txt/copying/ )
+ */
class CommandManager {
/**
* Create a `CommandManager` instance for handling commands/protocol
*
* @param {Object} core Reference to the global core object
*/
- constructor (core) {
+ constructor(core) {
+ /**
+ * Stored reference to the core
+ * @type {CoreApp}
+ */
this.core = core;
+
+ /**
+ * Command module storage
+ * @type {Array}
+ */
this.commands = [];
+
+ /**
+ * Command module category names (based off directory or module meta)
+ * @type {Array}
+ */
this.categories = [];
- if (!this.core.config.hasOwnProperty('logErrDetailed')) {
+
+ /**
+ * Full path to config.json file
+ * @type {String}
+ */
+ if (typeof this.core.config.logErrDetailed === 'undefined') {
this.core.config.logErrDetailed = false;
}
}
/**
* (Re)initializes name spaces for commands and starts load routine
- *
+ * @public
* @return {String} Module errors or empty if none
*/
- loadCommands () {
+ loadCommands() {
this.commands = [];
this.categories = [];
const commandImports = this.core.dynamicImports.getImport(CmdDir);
let cmdErrors = '';
- Object.keys(commandImports).forEach(file => {
- let command = commandImports[file];
- let name = path.basename(file);
+ Object.keys(commandImports).forEach((file) => {
+ const command = commandImports[file];
+ const name = basename(file);
cmdErrors += this.validateAndLoad(command, file, name);
});
@@ -50,29 +74,28 @@ class CommandManager {
/**
* Checks the module after having been `require()`ed in and reports errors
- *
* @param {Object} command reference to the newly loaded object
* @param {String} file file path to the module
* @param {String} name command (`cmd`) name
- *
+ * @private
* @return {String} Module errors or empty if none
*/
- validateAndLoad (command, file, name) {
- let error = this.validateCommand(command);
+ validateAndLoad(command, file, name) {
+ const error = this.validateCommand(command);
if (error) {
- let errText = `Failed to load '${name}': ${error}`;
+ const errText = `Failed to load command module '${name}': ${error}`;
console.log(errText);
return errText;
}
if (!command.category) {
- let base = path.join(this.core.dynamicImports.base, 'commands');
+ const base = join(this.core.dynamicImports.base, 'commands');
let category = 'Uncategorized';
- if (file.indexOf(path.sep) > -1) {
- category = path.dirname(path.relative(base, file))
- .replace(new RegExp(path.sep.replace('\\', '\\\\'), 'g'), '/');
+ if (file.indexOf(sep) > -1) {
+ category = dirname(relative(base, file))
+ .replace(new RegExp(sep.replace('\\', '\\\\'), 'g'), '/');
}
command.info.category = category;
@@ -86,7 +109,7 @@ class CommandManager {
try {
command.init(this.core);
} catch (err) {
- let errText = `Failed to initialize '${name}': ${err}`;
+ const errText = `Failed to initialize '${name}': ${err}`;
console.log(errText);
return errText;
}
@@ -99,121 +122,109 @@ class CommandManager {
/**
* Checks the module after having been `require()`ed in and reports errors
- *
* @param {Object} object reference to the newly loaded object
- *
+ * @private
* @return {String} Module errors or null if none
*/
- validateCommand (object) {
- if (typeof object !== 'object')
- return 'command setup is invalid';
-
- if (typeof object.run !== 'function')
- return 'run function is missing';
-
- if (typeof object.info !== 'object')
- return 'info object is missing';
-
- if (typeof object.info.name !== 'string')
- return 'info object is missing a valid name field';
+ validateCommand(object) {
+ if (typeof object !== 'object') { return 'command setup is invalid'; }
+ if (typeof object.run !== 'function') { return 'run function is missing'; }
+ if (typeof object.info !== 'object') { return 'info object is missing'; }
+ if (typeof object.info.name !== 'string') { return 'info object is missing a valid name field'; }
return null;
}
/**
* Pulls all command names from a passed `category`
- *
* @param {String} category [Optional] filter return results by this category
- *
+ * @public
* @return {Array} Array of command modules matching the category
*/
- all (category) {
+ all(category) {
return !category ? this.commands : this.commands.filter(
- c => c.info.category.toLowerCase() === category.toLowerCase()
- );
+ (c) => c.info.category.toLowerCase() === category.toLowerCase(),
+ );
}
/**
- * Pulls all category names
- *
- * @return {Array} Array of sub directories under CmdDir
+ * All category names
+ * @public
+ * @readonly
+ * @return {Array} Array of command category names
*/
- get categoriesList () {
+ get categoriesList() {
return this.categories;
}
/**
- * Pulls command by name or alia(s)
- *
+ * Pulls command by name or alias
* @param {String} name name or alias of command
- *
+ * @public
* @return {Object} Target command module object
*/
- get (name) {
+ get(name) {
return this.findBy('name', name)
|| this.commands.find(
- command => command.info.aliases instanceof Array &&
- command.info.aliases.indexOf(name) > -1
+ (command) => command.info.aliases instanceof Array
+ && command.info.aliases.indexOf(name) > -1,
);
}
/**
* Pulls command by arbitrary search of the `module.info` attribute
- *
* @param {String} key name or alias of command
* @param {String} value name or alias of command
- *
+ * @public
* @return {Object} Target command module object
*/
- findBy (key, value) {
- return this.commands.find(c => c.info[key] === value);
+ findBy(key, value) {
+ return this.commands.find((c) => c.info[key] === value);
}
/**
* Runs `initHooks` function on any modules that utilize the event
- *
+ * @private
* @param {Object} server main server object
*/
- initCommandHooks (server) {
- this.commands.filter(c => typeof c.initHooks !== 'undefined').forEach(
- c => c.initHooks(server)
- );
+ initCommandHooks(server) {
+ this.commands.filter((c) => typeof c.initHooks !== 'undefined').forEach(
+ (c) => c.initHooks(server),
+ );
}
/**
* Finds and executes the requested command, or fails with semi-intelligent error
- *
* @param {Object} server main server reference
* @param {Object} socket calling socket reference
* @param {Object} data command structure passed by socket (client)
- *
+ * @public
* @return {*} Arbitrary module return data
*/
- handleCommand (server, socket, data) {
+ handleCommand(server, socket, data) {
// Try to find command first
- let command = this.get(data.cmd);
+ const command = this.get(data.cmd);
if (command) {
return this.execute(command, server, socket, data);
- } else {
- // Then fail with helpful (sorta) message
- return this.handleFail(server, socket, data);
}
+
+ // Then fail with helpful (sorta) message
+ return this.handleFail(server, socket, data);
}
/**
* Requested command failure handler, attempts to find command and reports back
- *
* @param {Object} server main server reference
* @param {Object} socket calling socket reference
* @param {Object} data command structure passed by socket (client)
- *
+ * @private
* @return {*} Arbitrary module return data
*/
- handleFail (server, socket, data) {
- const maybe = didYouMean(data.cmd, this.all().map(c => c.info.name), {
+ handleFail(server, socket, data) {
+ const maybe = didYouMean(data.cmd, this.all().map((c) => c.info.name), {
threshold: 5,
- thresholdType: 'edit-distance'
+ thresholdType: 'edit-distance',
});
if (maybe) {
@@ -221,7 +232,7 @@ class CommandManager {
return this.handleCommand(server, socket, {
cmd: 'socketreply',
cmdKey: server.cmdKey,
- text: `Command not found, did you mean: \`${maybe}\`?`
+ text: `Command not found, did you mean: \`${maybe}\`?`,
});
}
@@ -229,39 +240,37 @@ class CommandManager {
return this.handleCommand(server, socket, {
cmd: 'socketreply',
cmdKey: server.cmdKey,
- text: 'Unknown command'
+ text: 'Unknown command',
});
}
/**
* Attempt to execute the requested command, fail if err or bad params
- *
* @param {Object} command target command module
* @param {Object} server main server reference
* @param {Object} socket calling socket reference
* @param {Object} data command structure passed by socket (client)
- *
+ * @private
* @return {*} Arbitrary module return data
*/
- async execute (command, server, socket, data) {
+ async execute(command, server, socket, data) {
if (typeof command.requiredData !== 'undefined') {
- let missing = [];
- for (let i = 0, len = command.requiredData.length; i < len; i++) {
- if (typeof data[command.requiredData[i]] === 'undefined')
- missing.push(command.requiredData[i]);
+ const missing = [];
+ for (let i = 0, len = command.requiredData.length; i < len; i += 1) {
+ if (typeof data[command.requiredData[i]] === 'undefined') { missing.push(command.requiredData[i]); }
}
if (missing.length > 0) {
console.log(`Failed to execute '${
- command.info.name
- }': missing required ${missing.join(', ')}\n\n`);
+ command.info.name
+ }': missing required ${missing.join(', ')}\n\n`);
this.handleCommand(server, socket, {
cmd: 'socketreply',
cmdKey: server.cmdKey,
text: `Failed to execute '${
- command.info.name
- }': missing required ${missing.join(', ')}\n\n`
+ command.info.name
+ }': missing required ${missing.join(', ')}\n\n`,
});
return null;
@@ -271,20 +280,20 @@ class CommandManager {
try {
return await command.run(this.core, server, socket, data);
} catch (err) {
- let errText = `Failed to execute '${command.info.name}': `;
-
+ const errText = `Failed to execute '${command.info.name}': `;
+
// If we have more detail enabled, then we get the trace
// if it isn't, or the property doesn't exist, then we'll get only the message
if (this.core.config.logErrDetailed === true) {
console.log(errText + err.stack);
} else {
- console.log(errText + err.toString())
+ console.log(errText + err.toString());
}
this.handleCommand(server, socket, {
cmd: 'socketreply',
cmdKey: server.cmdKey,
- text: errText + err.toString()
+ text: errText + err.toString(),
});
return null;
@@ -292,4 +301,4 @@ class CommandManager {
}
}
-module.exports = CommandManager;
+export default CommandManager;