sandcatbot-monorepo/sSandCatBot/command-handler.js

235 lines
6.1 KiB
JavaScript
Raw Permalink Normal View History

var fs = require("fs");
var path = require("path");
var is_initilized = false;
var commands = {};
var categories = {};
//main functions
function load(prefix = "s!", directory = "./commands") {
//setup global variable
this.prefix = prefix;
this.directory = directory;
//initiliaze command handler
let categories_ = [];
let aliases = [];
if (!isDirectory(directory))
fs.mkdirSync(directory);
if (categories["default"] == null)
categories["default"] = { enabled: true, commands: {} };
fs.readdirSync(directory).forEach(file => {
let absolute_path = path.resolve(`${directory}/${file}`);
if (isDirectory(absolute_path) && path.parse(absolute_path).name != "default") {
categories_.push(absolute_path);
return;
}
let required = loadCommand(absolute_path);
if (required == null)
return;
if (commands[required.name] == null) {
commands[required.name] = required;
categories[required.category].commands[required.name] = required;
}
if (required.aliases.length != 0)
aliases.push(required);
});
categories_.forEach(category => {
if (categories[path.parse(category).name] == null)
categories[path.parse(category).name] = { enabled: true, commands: {} };
fs.readdirSync(category).forEach(file => {
let absolute_path = path.resolve(`${category}/${file}`);
let required = loadCommand(absolute_path, path.parse(category).name);
if (required == null)
return;
if (commands[required.name] == null) {
commands[required.name] = required;
categories[required.category].commands[required.name] = required;
}
if (required.aliases.length != 0)
aliases.push(required);
});
});
aliases.forEach(command => {
command.aliases.forEach(alias => {
if (commands[alias] == null)
commands[alias] = command;
});
});
is_initilized = true;
}
function loadCommand(absolute_path, category = "default") {
if (!isFile(absolute_path) || path.parse(absolute_path).ext != ".js")
return;
let file = path.parse(absolute_path).base;
try {
let required = require(absolute_path);
if (!isValid(required)) {
console.log(`Command ${file} is invalid!`)
return;
}
required.path = absolute_path;
required.category = category;
return required;
} catch (err) {
console.log(`Couldnt load ${file}:\n ${err}`);
return;
}
}
function execute(bot, cmd, username, args, ...custom) {
if (!is_initilized)
return error(`The command ahndler was not initlized!`, "not_init");
if (!isCommand(cmd))
return error(`Invalid command ${cmd}!`, "invalid_command");
let cmd_info = info(cmd);
if (!cmd_info.enabled)
return error(`Command ${cmd} is currently disabled!`);
try {
let output = cmd_info.execute(bot, cmd, username, args, this, ...custom);
return success(output);
} catch (err) {
console.log(`Error while executing ${cmd} (args: [${args.join(", ")}])!`);
console.log(err.stack);
return error(`Error while executing the command!`);
}
}
function reload(command) {
if (!is_initilized)
return error(`The command ahndler was not initlized!`, "not_init");
if (command == null) {
try {
Object.keys(commands).forEach(key => {
let command = commands[key];
delete require.cache[command.path];
});
} catch (err) { }
commands = {};
categories = {};
load();
return success(`successfully reloaded all commands!`);
} else {
let cmd_info = info(command);
if (cmd_info == null)
return error(`${this.prefix}${command} doesnt exist or was not loaded before!`);
try {
let path = cmd_info.path;
let category = cmd_info.category;
let aliases = cmd_info.aliases;
aliases.forEach(alias => {
if (commands[alias] == cmd_info)
delete commands[alias];
});
delete commands[cmd_info.name];
delete categories[cmd_info.category].commands[cmd_info.name];
delete require.cache[cmd_info.path];
let required = loadCommand(path, category);
if (required == null)
return;
if (commands[required.name] == null) {
commands[required.name] = required;
categories[required.category].commands[required.name] = required;
}
if (required.aliases.length != 0) {
required.aliases.forEach(alias => {
if (commands[alias] == null)
commands[alias] = required;
});
}
return success(`Successfully reloaded ${this.prefix}${command}`);
} catch (err) {
console.log(`Error while realoding ${command}!`);
console.log(err.stack);
return error(`Couldn't reload ${this.prefix}${command}`, "reload_error");
}
}
}
//utility functions
function isCommand(command) {
return commands[command] != null;
}
function info(command) {
if (!isCommand(command))
return null;
return commands[command];
}
function getCategory(category) {
if (categories[category] != null && Object.keys(categories[category].commands).length == 0)
return null;
return categories[category];
}
function getCategories() {
return Object.keys(categories);
}
function success(message) {
return { status: "success", message };
}
function error(message, code = "unknown") {
return { status: "error", message, code };
}
function isFile(filePath) {
return fs.existsSync(filePath) && fs.statSync(filePath).isFile();
}
function isDirectory(filePath) {
return fs.existsSync(filePath) && fs.statSync(filePath).isDirectory();
}
function isValid(command) {
return command != null && typeof command.execute == "function" && typeof command.name == "string" && typeof command.description == "string" && typeof command.usage == "string" && typeof command.enabled == "boolean" && Array.isArray(command.aliases);
}
//module.exports
module.exports = load;
module.exports.reload = reload;
module.exports.execute = execute;
module.exports.isCommand = isCommand;
module.exports.getCategories = getCategories;
module.exports.getCategory = getCategory;
module.exports.info = info;
module.exports.prefix = "s!";
module.exports.directory = "./commands";