vnftjs
Version:
Discord CommandHandler for TypeScript or JavaScript
200 lines (179 loc) • 5.72 kB
text/typescript
import { Client, Message, ColorResolvable } from "discord.js";
import { Command } from "./Command";
import { Script } from "./Script";
import { fetchJS } from "vnft-tools";
import * as fs from "fs";
import * as path from "path";
/**
* @extends {Client}
*/
export class CommandHandler extends Client {
commands: Command[];
scripts: Script[];
scriptsTriggered: boolean;
prefix: string;
helpColor: ColorResolvable;
debug: boolean;
/**
* The constructor of the CommandHandler class.
* @constructor
*/
constructor() {
super();
this.commands = [];
this.scripts = [];
this.prefix = ".";
this.debug = false;
this.on("message", message => this.commandListener(message));
this.on("ready", () => this.scriptTrigger());
}
/**
* Gets executed at each message.
* Checks an Message for a Command and executes it if one has been found.
* @param {Message} message - The Discord Message that should be checked for a Command.
*/
commandListener(message: Message) {
let regexPrefix = this.prefix.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
let requestReg = new RegExp(`^${regexPrefix}(.*?)(\\s|$)`);
let request = message.content.match(requestReg);
if (!request) return false;
let commandName = request[1].toLowerCase();
let command: Command = this.commands.find(c => {
let inAlias = c.alias.map(s => s.toLowerCase()).includes(commandName);
let isName = c.name.toLowerCase() == commandName;
return inAlias || isName;
});
if (command && this.debug && command.path !== "") {
this.reload(command.path);
command = this.commands.find(c => {
let inAlias = c.alias.map(s => s.toLowerCase()).includes(commandName);
let isName = c.name.toLowerCase() == commandName;
return inAlias || isName;
});
}
if (command) {
command.execute(this, message);
}
}
/**
* Adds a Command to the List of known Commands
* @param {Command} command - The Command that should be added.
*/
addCommand(command: Command) {
let name = command.name;
let alias = command.alias.length > 0 ? ` + ${command.alias.join(", ")}` : "";
console.log(`loading ${name}${alias}`);
if (!command.funct) {
console.log(`${name} doesn't have a funct, it doesn't do anything when called!`);
}
this.commands.push(command);
}
/**
* Adds a Script to the List of known Scripts. Instantly triggers it if the Discord Client has already logged in.
* @param {Script} script - The Script that should be added.
*/
addScript(script: Script) {
this.scripts.push(script);
if (this.readyTimestamp !== null) {
script.trigger(this);
}
}
/**
* Triggers all scripts that hasn't been triggered yet
*/
scriptTrigger() {
let notTriggeredScripts = this.scripts.filter(s => s.triggered == false);
for (let script of notTriggeredScripts) {
script.trigger(this);
}
}
/**
* Loads all exported Commands inside of the given Path
* (goes also through the subfolders)
* @param target_path - The Path that should be crawled for exported Commands
* @example
* const path = require("path");
* client.loadCommands(path.join(__dirname,"commands"));
*/
loadCommands(target_path: string) {
let exists = fs.existsSync(target_path);
if (!exists) return false;
if (target_path.match(/^\.\//)) {
target_path = path.join(process.cwd(), target_path.replace(/^\.\//, ""));
}
let isDir = fs.statSync(target_path).isDirectory();
if (isDir) {
let allJS = fetchJS(target_path);
for (let file of allJS) {
let commands: Command | Command[] = require(file);
if (!Array.isArray(commands)) {
commands = [commands];
}
for (let command of commands) {
if (command.type == "Command") {
command.path = file;
this.addCommand(command);
}
}
}
}
}
/**
* Adds all exported Scripts inside of the given Path
* @param target_path - The Path that should be crawled for exported Scripts
*/
loadScripts(target_path: string) {
let exists = fs.existsSync(target_path);
if (!exists) return false;
if (target_path.match(/^\.\//)) {
target_path = path.join(process.cwd(), target_path.replace(/^\.\//, ""));
}
let isDir = fs.statSync(target_path).isDirectory();
if (isDir) {
let allJS = fetchJS(target_path);
for (let file of allJS) {
let scripts: Script | Script[] = require(file);
if (!Array.isArray(scripts)) {
scripts = [scripts];
}
for (let script of scripts) {
if (script.type == "Script") {
this.addScript(script);
}
}
}
}
}
/**
* adds the .help command
*/
enableHelp() {
this.addCommand(require("./help"));
}
/**
* turns debug mode on
*/
enableDebug() {
this.debug = true;
}
reload(file) {
delete require.cache[require.resolve(file)];
this.commands = this.commands.filter(c => c.path != file);
let commands: Command | Command[] = require(file);
if (!Array.isArray(commands)) {
commands = [commands];
}
for (let command of commands) {
if (command.type == "Command") {
command.path = file;
this.addCommand(command);
}
}
}
full_destroy() {
this.destroy();
for (let script of this.scripts) {
script.stop();
}
}
}