Archived
EventEmitter, reformatting, system message disable option
This commit is contained in:
1 parent
7d9cdb508b
commit
2ceb32e186
4 files changed
+395
-277
No files matched your search
+92
-65
@@ -1,38 +1,40 @@
|
|||||||
//IMPORTS
|
//IMPORTS
|
||||||
import { Client, ClientOptions, Message } from 'discord.js';
|
import { Client, ClientOptions, Message } from "discord.js";
|
||||||
import { Command, CommandManager, CommandMessageStructure, PermissionsError } from './Command.js';
|
import {
|
||||||
import { HelpMessage, HelpMessageParams } from './Help.js';
|
Command,
|
||||||
import * as http from 'http';
|
CommandManager,
|
||||||
import { SystemMessageManager } from './SystemMessage.js';
|
CommandMessageStructure,
|
||||||
|
PermissionsError,
|
||||||
|
} from "./Command.js";
|
||||||
|
import { HelpMessage, HelpMessageParams } from "./Help.js";
|
||||||
|
import * as http from "http";
|
||||||
|
import { SystemMessageManager } from "./SystemMessage.js";
|
||||||
|
import { EventEmitter } from "events";
|
||||||
|
|
||||||
//TYPE DEFINITIONS
|
//TYPE DEFINITIONS
|
||||||
interface ConfigurationOptions {
|
interface ConfigurationOptions {
|
||||||
token?: string,
|
token?: string;
|
||||||
helpCommand: boolean
|
helpCommand: boolean;
|
||||||
}
|
}
|
||||||
interface ConstructorOptions {
|
interface ConstructorOptions {
|
||||||
name: string,
|
name: string;
|
||||||
prefix: string,
|
prefix: string;
|
||||||
argumentSeparator?: string
|
argumentSeparator?: string;
|
||||||
helpCommand?: boolean,
|
helpCommand?: boolean;
|
||||||
clientOptions?: ClientOptions,
|
clientOptions?: ClientOptions;
|
||||||
token?: string,
|
token?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
//MAIN CLASS
|
//MAIN CLASS
|
||||||
class Bot {
|
class Bot extends EventEmitter {
|
||||||
name: string;
|
name: string;
|
||||||
client: Client;
|
client: Client;
|
||||||
commands: CommandManager;
|
commands: CommandManager;
|
||||||
config: ConfigurationOptions;
|
config: ConfigurationOptions;
|
||||||
messages: {
|
messages: {
|
||||||
help: HelpMessageParams,
|
help: HelpMessageParams;
|
||||||
system: SystemMessageManager
|
system: SystemMessageManager;
|
||||||
}
|
};
|
||||||
on: {
|
|
||||||
message: (m: Message) => any,
|
|
||||||
command: (m: Message, cmdInfo?: CommandMessageStructure) => any
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Bot instance initializer
|
* Bot instance initializer
|
||||||
@@ -46,27 +48,28 @@ class Bot {
|
|||||||
* @param {string} [options.token] - bot token from Discord Developer Portal
|
* @param {string} [options.token] - bot token from Discord Developer Portal
|
||||||
*/
|
*/
|
||||||
constructor(options: ConstructorOptions) {
|
constructor(options: ConstructorOptions) {
|
||||||
|
super();
|
||||||
this.name = options.name;
|
this.name = options.name;
|
||||||
this.client = new Client(options.clientOptions);
|
this.client = new Client(options.clientOptions);
|
||||||
this.commands = new CommandManager(options.prefix, options.argumentSeparator);
|
this.commands = new CommandManager(
|
||||||
|
options.prefix,
|
||||||
|
options.argumentSeparator
|
||||||
|
);
|
||||||
this.config = {
|
this.config = {
|
||||||
token: options.token,
|
token: options.token,
|
||||||
helpCommand: options.helpCommand != undefined ? options.helpCommand : true
|
helpCommand:
|
||||||
}
|
options.helpCommand != undefined ? options.helpCommand : true,
|
||||||
|
};
|
||||||
this.messages = {
|
this.messages = {
|
||||||
help: {
|
help: {
|
||||||
title: 'Help',
|
title: "Help",
|
||||||
description: 'List of all available commands',
|
description: "List of all available commands",
|
||||||
color: '#ff5500',
|
color: "#ff5500",
|
||||||
usage: '[command name (optional)]',
|
usage: "[command name (optional)]",
|
||||||
bottomText: 'List of all available commands'
|
bottomText: "List of all available commands",
|
||||||
},
|
},
|
||||||
system: new SystemMessageManager(this.name)
|
system: new SystemMessageManager(this.name),
|
||||||
}
|
};
|
||||||
this.on = {
|
|
||||||
message: (m: Message) => {},
|
|
||||||
command: (m: Message, cmdInfo?: CommandMessageStructure) => {}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -75,56 +78,80 @@ class Bot {
|
|||||||
* @param {string} [token] - app token from Discord Developer Portal
|
* @param {string} [token] - app token from Discord Developer Portal
|
||||||
* @returns *Promise<boolean>*
|
* @returns *Promise<boolean>*
|
||||||
*/
|
*/
|
||||||
async start(port?: number, token?: string) : Promise<boolean> {
|
async start(port?: number, token?: string): Promise<boolean> {
|
||||||
try {
|
try {
|
||||||
console.log(`Bot name: ${this.name}`);
|
console.log(`Bot name: ${this.name}`);
|
||||||
console.log(`Prefix: ${this.commands.prefix} \n`);
|
console.log(`Prefix: ${this.commands.prefix} \n`);
|
||||||
const loginToken: string = token || this.config.token || '';
|
const loginToken: string = token || this.config.token || "";
|
||||||
if(loginToken === '') {
|
if (loginToken === "") {
|
||||||
throw new ReferenceError('No token specified. Please pass your Discord application token as an argument to the "start" method or in the constructor');
|
throw new ReferenceError(
|
||||||
|
'No token specified. Please pass your Discord application token as an argument to the "start" method or in the constructor'
|
||||||
|
);
|
||||||
}
|
}
|
||||||
if(port) {
|
if (port) {
|
||||||
console.log(`Creating http server on port ${port}...`);
|
console.log(`Creating http server on port ${port}...`);
|
||||||
http.createServer().listen(port);
|
http.createServer().listen(port);
|
||||||
}
|
}
|
||||||
console.log('Starting modules...');
|
console.log("Starting modules...");
|
||||||
if(this.config.helpCommand) {
|
if (this.config.helpCommand) {
|
||||||
const helpMsg: Command = new HelpMessage(this.commands, this.messages.help, this.name);
|
const helpMsg: Command = new HelpMessage(
|
||||||
|
this.commands,
|
||||||
|
this.messages.help,
|
||||||
|
this.name
|
||||||
|
);
|
||||||
this.commands.add(helpMsg);
|
this.commands.add(helpMsg);
|
||||||
}
|
}
|
||||||
console.log('Connecting to Discord...');
|
console.log("Connecting to Discord...");
|
||||||
if(await this.client.login(loginToken)) {
|
if (await this.client.login(loginToken)) {
|
||||||
console.log('BOT IS READY!\n');
|
this.client.on("ready", () => {
|
||||||
this.client.on('message', async m => {
|
this.emit("ready");
|
||||||
this.on.message(m);
|
});
|
||||||
const cmdMsg: CommandMessageStructure | null = this.commands.fetch(m);
|
this.client.on("message", async (m) => {
|
||||||
if(cmdMsg?.command) {
|
const cmdMsg: CommandMessageStructure | null =
|
||||||
this.on.command(m, cmdMsg);
|
this.commands.fetch(m);
|
||||||
|
if (cmdMsg?.command) {
|
||||||
|
this.emit("command", [m, cmdMsg]);
|
||||||
try {
|
try {
|
||||||
await cmdMsg.command.start(m, cmdMsg.arguments);
|
await cmdMsg.command.start(m, cmdMsg.arguments);
|
||||||
}
|
} catch (e) {
|
||||||
catch (e) {
|
if (e instanceof PermissionsError) {
|
||||||
if(e instanceof PermissionsError) {
|
this.messages.system.send(
|
||||||
this.messages.system.send('PERMISSION', { user: m.member || undefined, command: cmdMsg.command }, m.channel);
|
"PERMISSION",
|
||||||
}
|
{
|
||||||
else {
|
user: m.member || undefined,
|
||||||
this.messages.system.send('ERROR', { command: cmdMsg.command, user: m.member || undefined, error: e }, m.channel);
|
command: cmdMsg.command,
|
||||||
|
},
|
||||||
|
m.channel
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
this.messages.system.send(
|
||||||
|
"ERROR",
|
||||||
|
{
|
||||||
|
command: cmdMsg.command,
|
||||||
|
user: m.member || undefined,
|
||||||
|
error: e,
|
||||||
|
},
|
||||||
|
m.channel
|
||||||
|
);
|
||||||
console.error(e);
|
console.error(e);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
} else if (cmdMsg) {
|
||||||
else if(cmdMsg) {
|
this.messages.system.send(
|
||||||
this.messages.system.send('NOT_FOUND', { phrase: m.content, user: m.member || undefined }, m.channel);
|
"NOT_FOUND",
|
||||||
|
{ phrase: m.content, user: m.member || undefined },
|
||||||
|
m.channel
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
this.emit("message", [m]);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
} catch (e) {
|
||||||
catch (e) {
|
|
||||||
console.error(`ERROR! ${e.toString()}`);
|
console.error(`ERROR! ${e.toString()}`);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
+134
-107
@@ -1,29 +1,38 @@
|
|||||||
//IMPORTS
|
//IMPORTS
|
||||||
import { Permissions, PermissionResolvable, Message, GuildMember, MessageEmbed } from 'discord.js';
|
import {
|
||||||
|
Permissions,
|
||||||
|
PermissionResolvable,
|
||||||
|
Message,
|
||||||
|
GuildMember,
|
||||||
|
MessageEmbed,
|
||||||
|
} from "discord.js";
|
||||||
|
|
||||||
//TYPE DEFINITIONS
|
//TYPE DEFINITIONS
|
||||||
interface CommandBuilder {
|
interface CommandBuilder {
|
||||||
name: string,
|
name: string;
|
||||||
aliases?: string[] | string,
|
aliases?: string[] | string;
|
||||||
keywords?: string[] | string,
|
keywords?: string[] | string;
|
||||||
description?: string,
|
description?: string;
|
||||||
usage?: string,
|
usage?: string;
|
||||||
permissionCheck?: PermissionCheckTypes,
|
permissionCheck?: PermissionCheckTypes;
|
||||||
permissions?: PermissionResolvable,
|
permissions?: PermissionResolvable;
|
||||||
visible?: boolean
|
visible?: boolean;
|
||||||
function: (message?: Message, cmdArguments?: string[]) => void | string | MessageEmbed | Promise<void | string | MessageEmbed>;
|
function: (
|
||||||
|
message?: Message,
|
||||||
|
cmdArguments?: string[]
|
||||||
|
) => void | string | MessageEmbed | Promise<void | string | MessageEmbed>;
|
||||||
}
|
}
|
||||||
interface CommandMessageStructure {
|
interface CommandMessageStructure {
|
||||||
name: string,
|
name: string;
|
||||||
arguments: string[],
|
arguments: string[];
|
||||||
command: Command | null
|
command: Command | null;
|
||||||
}
|
}
|
||||||
interface PhraseOccurrenceData {
|
interface PhraseOccurrenceData {
|
||||||
command: Command,
|
command: Command;
|
||||||
type: 'NAME' | 'ALIAS'
|
type: "NAME" | "ALIAS";
|
||||||
}
|
}
|
||||||
type GetMode = 'ALL' | 'PREFIX' | 'NO_PREFIX';
|
type GetMode = "ALL" | "PREFIX" | "NO_PREFIX";
|
||||||
type PermissionCheckTypes = 'ALL' | 'ANY';
|
type PermissionCheckTypes = "ALL" | "ANY";
|
||||||
|
|
||||||
//ERROR CLASSES
|
//ERROR CLASSES
|
||||||
class PermissionsError {
|
class PermissionsError {
|
||||||
@@ -48,7 +57,10 @@ class Command {
|
|||||||
permissionCheck: PermissionCheckTypes;
|
permissionCheck: PermissionCheckTypes;
|
||||||
permissions: Permissions;
|
permissions: Permissions;
|
||||||
visible: boolean;
|
visible: boolean;
|
||||||
private function: (message?: Message, cmdArguments?: string[]) => void | string | MessageEmbed | Promise<void | string | MessageEmbed>;
|
private function: (
|
||||||
|
message?: Message,
|
||||||
|
cmdArguments?: string[]
|
||||||
|
) => void | string | MessageEmbed | Promise<void | string | MessageEmbed>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Command constructor
|
* Command constructor
|
||||||
@@ -65,12 +77,15 @@ class Command {
|
|||||||
* @param {Function} options.function - function that will trigger when the commands gets called
|
* @param {Function} options.function - function that will trigger when the commands gets called
|
||||||
*/
|
*/
|
||||||
constructor(options: CommandBuilder) {
|
constructor(options: CommandBuilder) {
|
||||||
this.name = options.name.split(' ').join('_');
|
this.name = options.name.split(" ").join("_");
|
||||||
this.aliases = Command.processPhrase(options.aliases);
|
this.aliases = Command.processPhrase(options.aliases);
|
||||||
this.keywords = Command.processPhrase(options.keywords);
|
this.keywords = Command.processPhrase(options.keywords);
|
||||||
this.description = options.description || "No description";
|
this.description = options.description || "No description";
|
||||||
this.usage = options.usage || "";
|
this.usage = options.usage || "";
|
||||||
this.permissionCheck = options.permissionCheck == 'ALL' || options.permissionCheck == 'ANY' ? options.permissionCheck : "ANY";
|
this.permissionCheck =
|
||||||
|
options.permissionCheck == "ALL" || options.permissionCheck == "ANY"
|
||||||
|
? options.permissionCheck
|
||||||
|
: "ANY";
|
||||||
this.permissions = new Permissions(options.permissions || 0);
|
this.permissions = new Permissions(options.permissions || 0);
|
||||||
this.visible = options.visible != undefined ? options.visible : true;
|
this.visible = options.visible != undefined ? options.visible : true;
|
||||||
this.function = options.function;
|
this.function = options.function;
|
||||||
@@ -82,41 +97,42 @@ class Command {
|
|||||||
* @param {string[]} [cmdArguments] - list of processed arguments passed in a Discord message
|
* @param {string[]} [cmdArguments] - list of processed arguments passed in a Discord message
|
||||||
* @returns *Promise<void>*
|
* @returns *Promise<void>*
|
||||||
*/
|
*/
|
||||||
async start(message?: Message, cmdArguments?: string[]) : Promise<void> {
|
async start(message?: Message, cmdArguments?: string[]): Promise<void> {
|
||||||
const memberPermissions : Readonly<Permissions> = message?.member?.permissions || new Permissions(0);
|
const memberPermissions: Readonly<Permissions> =
|
||||||
if(this.permissionCheck == 'ALL' ? memberPermissions.has(this.permissions, true) : memberPermissions.any(this.permissions, true)) {
|
message?.member?.permissions || new Permissions(0);
|
||||||
|
if (
|
||||||
|
this.permissionCheck == "ALL"
|
||||||
|
? memberPermissions.has(this.permissions, true)
|
||||||
|
: memberPermissions.any(this.permissions, true)
|
||||||
|
) {
|
||||||
const fnResult = await this.function(message, cmdArguments);
|
const fnResult = await this.function(message, cmdArguments);
|
||||||
if(typeof fnResult == 'string') {
|
if (typeof fnResult == "string") {
|
||||||
await message?.reply(fnResult);
|
await message?.reply(fnResult);
|
||||||
}
|
} else if (fnResult instanceof MessageEmbed) {
|
||||||
else if(fnResult instanceof MessageEmbed) {
|
|
||||||
await message?.channel.send(fnResult);
|
await message?.channel.send(fnResult);
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
throw new PermissionsError(this, message?.member);
|
throw new PermissionsError(this, message?.member);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static processPhrase(phrase?: string | string[]) : string[] {
|
private static processPhrase(phrase?: string | string[]): string[] {
|
||||||
if(Array.isArray(phrase)) {
|
if (Array.isArray(phrase)) {
|
||||||
const buff = phrase.map((p) => {
|
const buff = phrase.map((p) => {
|
||||||
return p.split(' ').join('_');
|
return p.split(" ").join("_");
|
||||||
});
|
});
|
||||||
buff.map(e => {
|
buff.map((e) => {
|
||||||
if(e == '' || e == ' ') {
|
if (e == "" || e == " ") {
|
||||||
const i = buff.indexOf(e);
|
const i = buff.indexOf(e);
|
||||||
buff.splice(i, 1);
|
buff.splice(i, 1);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return buff;
|
return buff;
|
||||||
}
|
} else if (typeof phrase == "string" && phrase != "" && phrase != " ") {
|
||||||
else if(typeof phrase == 'string' && phrase != '' && phrase != ' ') {
|
|
||||||
const buff = [];
|
const buff = [];
|
||||||
buff.push(phrase.split(' ').join('_'));
|
buff.push(phrase.split(" ").join("_"));
|
||||||
return buff;
|
return buff;
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -129,7 +145,7 @@ class CommandManager {
|
|||||||
constructor(prefix: string, argumentSeparator?: string) {
|
constructor(prefix: string, argumentSeparator?: string) {
|
||||||
this.list = [];
|
this.list = [];
|
||||||
this.prefix = prefix;
|
this.prefix = prefix;
|
||||||
this.argumentSeparator = argumentSeparator || ',';
|
this.argumentSeparator = argumentSeparator || ",";
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -138,39 +154,39 @@ class CommandManager {
|
|||||||
* @param {GetMode} [mode='ALL'] - specifies which types of command triggers will be used to find the command [*NO_PREFIX* - only keywords; *PREFIX* - names and aliases]
|
* @param {GetMode} [mode='ALL'] - specifies which types of command triggers will be used to find the command [*NO_PREFIX* - only keywords; *PREFIX* - names and aliases]
|
||||||
* @returns *Command* | *null*
|
* @returns *Command* | *null*
|
||||||
*/
|
*/
|
||||||
get(phrase: string, mode?: GetMode) : Command | null {
|
get(phrase: string, mode?: GetMode): Command | null {
|
||||||
if(!mode) mode = 'ALL';
|
if (!mode) mode = "ALL";
|
||||||
let command : Command | null = null;
|
let command: Command | null = null;
|
||||||
this.list.map((c) => {
|
this.list.map((c) => {
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
case 'PREFIX':
|
case "PREFIX":
|
||||||
if(c.name == phrase) {
|
if (c.name == phrase) {
|
||||||
command = c;
|
command = c;
|
||||||
}
|
}
|
||||||
c.aliases.map(a => {
|
c.aliases.map((a) => {
|
||||||
if(a == phrase) {
|
if (a == phrase) {
|
||||||
command = c;
|
command = c;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
case 'NO_PREFIX':
|
case "NO_PREFIX":
|
||||||
c.keywords.map(k => {
|
c.keywords.map((k) => {
|
||||||
if(k == phrase) {
|
if (k == phrase) {
|
||||||
command = c;
|
command = c;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
case 'ALL':
|
case "ALL":
|
||||||
if(c.name == phrase) {
|
if (c.name == phrase) {
|
||||||
command = c;
|
command = c;
|
||||||
}
|
}
|
||||||
c.aliases.map(a => {
|
c.aliases.map((a) => {
|
||||||
if(a == phrase) {
|
if (a == phrase) {
|
||||||
command = c;
|
command = c;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
c.keywords.map(k => {
|
c.keywords.map((k) => {
|
||||||
if(k == phrase) {
|
if (k == phrase) {
|
||||||
command = c;
|
command = c;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -185,27 +201,35 @@ class CommandManager {
|
|||||||
* @param {Command} command - *Command* or *HelpMessage* object
|
* @param {Command} command - *Command* or *HelpMessage* object
|
||||||
* @returns *boolean*
|
* @returns *boolean*
|
||||||
*/
|
*/
|
||||||
add(command: Command) : boolean {
|
add(command: Command): boolean {
|
||||||
try {
|
try {
|
||||||
if(!(command instanceof Command)) {
|
if (!(command instanceof Command)) {
|
||||||
throw new TypeError('Inavlid argument type');
|
throw new TypeError("Inavlid argument type");
|
||||||
}
|
}
|
||||||
const nameOccurrence: PhraseOccurrenceData | null = this.findPhraseOccurrence(command.name);
|
const nameOccurrence: PhraseOccurrenceData | null =
|
||||||
if(nameOccurrence) {
|
this.findPhraseOccurrence(command.name);
|
||||||
throw new Error(`The name "${command.name}" has already been registered as ${nameOccurrence.type} in the "${nameOccurrence.command.name}" command.`);
|
if (nameOccurrence) {
|
||||||
|
throw new Error(
|
||||||
|
`The name "${command.name}" has already been registered as ${nameOccurrence.type} in the "${nameOccurrence.command.name}" command.`
|
||||||
|
);
|
||||||
}
|
}
|
||||||
command.aliases.map(a => {
|
command.aliases.map((a) => {
|
||||||
const aliasOccurrence: PhraseOccurrenceData | null = this.findPhraseOccurrence(a);
|
const aliasOccurrence: PhraseOccurrenceData | null =
|
||||||
if(aliasOccurrence) {
|
this.findPhraseOccurrence(a);
|
||||||
console.warn(`WARN! The name "${a}" is already registered as ${aliasOccurrence.type} in the "${aliasOccurrence.command.name}" command. It will be removed from the "${command.name}" command.`);
|
if (aliasOccurrence) {
|
||||||
|
console.warn(
|
||||||
|
`WARN! The name "${a}" is already registered as ${aliasOccurrence.type} in the "${aliasOccurrence.command.name}" command. It will be removed from the "${command.name}" command.`
|
||||||
|
);
|
||||||
const iToRemove = command.aliases.indexOf(a);
|
const iToRemove = command.aliases.indexOf(a);
|
||||||
command.aliases.splice(iToRemove, 1);
|
command.aliases.splice(iToRemove, 1);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
this.list.map(c => {
|
this.list.map((c) => {
|
||||||
command.keywords.map(k => {
|
command.keywords.map((k) => {
|
||||||
if(c.keywords.indexOf(k) != -1) {
|
if (c.keywords.indexOf(k) != -1) {
|
||||||
console.warn(`WARN! The name "${k}" is already a registered KEYWORD for the "${c.name}" command. It will be removed from the "${command.name}" command`);
|
console.warn(
|
||||||
|
`WARN! The name "${k}" is already a registered KEYWORD for the "${c.name}" command. It will be removed from the "${command.name}" command`
|
||||||
|
);
|
||||||
const iToRemove = command.keywords.indexOf(k);
|
const iToRemove = command.keywords.indexOf(k);
|
||||||
command.keywords.splice(iToRemove, 1);
|
command.keywords.splice(iToRemove, 1);
|
||||||
}
|
}
|
||||||
@@ -213,8 +237,7 @@ class CommandManager {
|
|||||||
});
|
});
|
||||||
this.list.push(command);
|
this.list.push(command);
|
||||||
return true;
|
return true;
|
||||||
}
|
} catch (e) {
|
||||||
catch(e) {
|
|
||||||
console.error(`ERROR! ${e.toString()}`);
|
console.error(`ERROR! ${e.toString()}`);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -225,66 +248,70 @@ class CommandManager {
|
|||||||
* @param {Message} message - *Message* object
|
* @param {Message} message - *Message* object
|
||||||
* @returns *CommandMessagesStructure* | *null*
|
* @returns *CommandMessagesStructure* | *null*
|
||||||
*/
|
*/
|
||||||
fetch(message: Message) : CommandMessageStructure | null {
|
fetch(message: Message): CommandMessageStructure | null {
|
||||||
if(!message.author.bot && message.content.startsWith(this.prefix)) {
|
if (!message.author.bot && message.content.startsWith(this.prefix)) {
|
||||||
let msgContent = message.content.replace(this.prefix, '');
|
let msgContent = message.content.replace(this.prefix, "");
|
||||||
const cmdName = msgContent.split(' ')[0];
|
const cmdName = msgContent.split(" ")[0];
|
||||||
const cmd: Command | null = this.get(cmdName, 'PREFIX');
|
const cmd: Command | null = this.get(cmdName, "PREFIX");
|
||||||
msgContent = msgContent.replace(cmdName, '');
|
msgContent = msgContent.replace(cmdName, "");
|
||||||
let cmdArguments: string[] = msgContent.split(this.argumentSeparator);
|
let cmdArguments: string[] = msgContent.split(
|
||||||
|
this.argumentSeparator
|
||||||
|
);
|
||||||
cmdArguments = cmdArguments.map((a) => {
|
cmdArguments = cmdArguments.map((a) => {
|
||||||
return a.replace(' ', '');
|
return a.replace(" ", "");
|
||||||
});
|
});
|
||||||
if((cmdArguments[0] == '' || cmdArguments[0] == ' ') && cmdArguments.length == 1) {
|
if (
|
||||||
|
(cmdArguments[0] == "" || cmdArguments[0] == " ") &&
|
||||||
|
cmdArguments.length == 1
|
||||||
|
) {
|
||||||
cmdArguments = [];
|
cmdArguments = [];
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
name: cmdName,
|
name: cmdName,
|
||||||
arguments: cmdArguments,
|
arguments: cmdArguments,
|
||||||
command: cmd
|
command: cmd,
|
||||||
}
|
};
|
||||||
}
|
} else if (!message.author.bot) {
|
||||||
else if(!message.author.bot) {
|
const cmdName = message.content.split(" ")[0];
|
||||||
const cmdName = message.content.split(' ')[0];
|
const cmd: Command | null = this.get(cmdName, "NO_PREFIX");
|
||||||
const cmd: Command | null = this.get(cmdName, 'NO_PREFIX');
|
if (cmd) {
|
||||||
if(cmd) {
|
const cmdArgumentsStr = message.content.replace(cmdName, "");
|
||||||
const cmdArgumentsStr = message.content.replace(cmdName, '');
|
let cmdArguments: string[] = cmdArgumentsStr.split(",");
|
||||||
let cmdArguments: string[] = cmdArgumentsStr.split(',');
|
|
||||||
cmdArguments = cmdArguments.map((a) => {
|
cmdArguments = cmdArguments.map((a) => {
|
||||||
return a.replace(' ', '');
|
return a.replace(" ", "");
|
||||||
});
|
});
|
||||||
if((cmdArguments[0] == '' || cmdArguments[0] == ' ') && cmdArguments.length == 1) {
|
if (
|
||||||
|
(cmdArguments[0] == "" || cmdArguments[0] == " ") &&
|
||||||
|
cmdArguments.length == 1
|
||||||
|
) {
|
||||||
cmdArguments = [];
|
cmdArguments = [];
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
name: cmdName,
|
name: cmdName,
|
||||||
arguments: cmdArguments,
|
arguments: cmdArguments,
|
||||||
command: cmd
|
command: cmd,
|
||||||
}
|
};
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private findPhraseOccurrence(phrase?: string) : PhraseOccurrenceData | null {
|
private findPhraseOccurrence(phrase?: string): PhraseOccurrenceData | null {
|
||||||
let returnValue: PhraseOccurrenceData | null = null;
|
let returnValue: PhraseOccurrenceData | null = null;
|
||||||
this.list.map(c => {
|
this.list.map((c) => {
|
||||||
if(phrase == c.name) {
|
if (phrase == c.name) {
|
||||||
returnValue = {
|
returnValue = {
|
||||||
command: c,
|
command: c,
|
||||||
type: 'NAME'
|
type: "NAME",
|
||||||
}
|
};
|
||||||
}
|
} else if (c.aliases.indexOf(phrase || "") != -1) {
|
||||||
else if(c.aliases.indexOf(phrase || '') != -1) {
|
|
||||||
returnValue = {
|
returnValue = {
|
||||||
command: c,
|
command: c,
|
||||||
type: 'ALIAS'
|
type: "ALIAS",
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return returnValue;
|
return returnValue;
|
||||||
@@ -292,4 +319,4 @@ class CommandManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//EXPORTS
|
//EXPORTS
|
||||||
export { Command, CommandManager, CommandMessageStructure, PermissionsError }
|
export { Command, CommandManager, CommandMessageStructure, PermissionsError };
|
||||||
+55
-40
@@ -1,76 +1,91 @@
|
|||||||
import { ColorResolvable, MessageEmbed } from 'discord.js';
|
import { ColorResolvable, MessageEmbed } from "discord.js";
|
||||||
import { Command, CommandManager } from './Command.js';
|
import { Command, CommandManager } from "./Command.js";
|
||||||
|
|
||||||
interface HelpMessageParams {
|
interface HelpMessageParams {
|
||||||
title: string,
|
title: string;
|
||||||
bottomText: string
|
bottomText: string;
|
||||||
color: ColorResolvable,
|
color: ColorResolvable;
|
||||||
description: string,
|
description: string;
|
||||||
usage: string
|
usage: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
class HelpMessage extends Command {
|
class HelpMessage extends Command {
|
||||||
constructor(cmdManager: CommandManager, params: HelpMessageParams, botName?: string) {
|
constructor(
|
||||||
|
cmdManager: CommandManager,
|
||||||
|
params: HelpMessageParams,
|
||||||
|
botName?: string
|
||||||
|
) {
|
||||||
super({
|
super({
|
||||||
name: 'help',
|
name: "help",
|
||||||
usage: params.usage,
|
usage: params.usage,
|
||||||
permissions: 0,
|
permissions: 0,
|
||||||
description: params.description,
|
description: params.description,
|
||||||
function: (m, a) => {
|
function: (m, a) => {
|
||||||
const helpMsg = new MessageEmbed()
|
const helpMsg = new MessageEmbed();
|
||||||
helpMsg.setColor(params.color);
|
helpMsg.setColor(params.color);
|
||||||
helpMsg.setTimestamp();
|
helpMsg.setTimestamp();
|
||||||
helpMsg.setFooter(botName || '');
|
helpMsg.setFooter(botName || "");
|
||||||
if(helpMsg != null) {
|
if (helpMsg != null) {
|
||||||
if(a && a[0]) {
|
if (a && a[0]) {
|
||||||
const cmd: Command | null = cmdManager.get(a[0], 'ALL');
|
const cmd: Command | null = cmdManager.get(a[0], "ALL");
|
||||||
if(cmd) {
|
if (cmd) {
|
||||||
helpMsg.setTitle(`${cmd.name} ${cmd.visible ? '' : '[HIDDEN]'}`);
|
helpMsg.setTitle(
|
||||||
|
`${cmd.name} ${cmd.visible ? "" : "[HIDDEN]"}`
|
||||||
|
);
|
||||||
helpMsg.setDescription(cmd.description);
|
helpMsg.setDescription(cmd.description);
|
||||||
if(cmd.usage) helpMsg.addField('Usage:', `${cmdManager.prefix}${cmd.name} ${cmd.usage}`, false);
|
if (cmd.usage)
|
||||||
if(cmd.permissions.toArray(false).length > 0) {
|
helpMsg.addField(
|
||||||
let permList: string = '';
|
"Usage:",
|
||||||
cmd.permissions.toArray(false).map(p => {
|
`${cmdManager.prefix}${cmd.name} ${cmd.usage}`,
|
||||||
permList += p + '\n';
|
false
|
||||||
|
);
|
||||||
|
if (cmd.permissions.toArray(false).length > 0) {
|
||||||
|
let permList: string = "";
|
||||||
|
cmd.permissions.toArray(false).map((p) => {
|
||||||
|
permList += p + "\n";
|
||||||
});
|
});
|
||||||
helpMsg.addField('Permissions:', permList, false);
|
helpMsg.addField(
|
||||||
|
"Permissions:",
|
||||||
|
permList,
|
||||||
|
false
|
||||||
|
);
|
||||||
}
|
}
|
||||||
if(cmd.aliases.length > 0) {
|
if (cmd.aliases.length > 0) {
|
||||||
let aList: string = '';
|
let aList: string = "";
|
||||||
cmd.aliases.map(a => {
|
cmd.aliases.map((a) => {
|
||||||
aList += a + '\n';
|
aList += a + "\n";
|
||||||
});
|
});
|
||||||
helpMsg.addField('Aliases:', aList, false);
|
helpMsg.addField("Aliases:", aList, false);
|
||||||
}
|
}
|
||||||
if(cmd.keywords.length > 0) {
|
if (cmd.keywords.length > 0) {
|
||||||
let kwrdList: string = '';
|
let kwrdList: string = "";
|
||||||
cmd.keywords.map(k => {
|
cmd.keywords.map((k) => {
|
||||||
kwrdList += k + '\n';
|
kwrdList += k + "\n";
|
||||||
});
|
});
|
||||||
helpMsg.addField('Keywords:', kwrdList, false);
|
helpMsg.addField("Keywords:", kwrdList, false);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
throw new ReferenceError(
|
||||||
|
`Command "${a[0]}" does not exist`
|
||||||
|
);
|
||||||
}
|
}
|
||||||
else {
|
} else {
|
||||||
throw new ReferenceError(`Command "${a[0]}" does not exist`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
helpMsg.setTitle(params.title);
|
helpMsg.setTitle(params.title);
|
||||||
helpMsg.setDescription(params.bottomText);
|
helpMsg.setDescription(params.bottomText);
|
||||||
|
|
||||||
cmdManager.list.map((c) => {
|
cmdManager.list.map((c) => {
|
||||||
if(c.visible) {
|
if (c.visible) {
|
||||||
helpMsg.addField(
|
helpMsg.addField(
|
||||||
`${cmdManager.prefix}${c.name} ${c.usage}`,
|
`${cmdManager.prefix}${c.name} ${c.usage}`,
|
||||||
c.description,
|
c.description,
|
||||||
false
|
false
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return helpMsg;
|
return helpMsg;
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+114
-65
@@ -1,48 +1,59 @@
|
|||||||
import { ColorResolvable, DMChannel, GuildMember, Message, MessageEmbed, NewsChannel, TextChannel, User } from 'discord.js';
|
import {
|
||||||
import { Command, PermissionsError } from './Command.js';
|
ColorResolvable,
|
||||||
|
DMChannel,
|
||||||
|
GuildMember,
|
||||||
|
Message,
|
||||||
|
MessageEmbed,
|
||||||
|
NewsChannel,
|
||||||
|
TextChannel,
|
||||||
|
User,
|
||||||
|
} from "discord.js";
|
||||||
|
import { Command, PermissionsError } from "./Command.js";
|
||||||
|
|
||||||
type MessageType = 'PERMISSION' | 'ERROR' | 'NOT_FOUND';
|
type MessageType = "PERMISSION" | "ERROR" | "NOT_FOUND";
|
||||||
interface SystemMessageAppearance {
|
interface SystemMessageAppearance {
|
||||||
title: string,
|
title: string;
|
||||||
bottomText?: string,
|
bottomText?: string;
|
||||||
accentColor?: ColorResolvable,
|
accentColor?: ColorResolvable;
|
||||||
showTimestamp?: boolean,
|
showTimestamp?: boolean;
|
||||||
footer?: string
|
footer?: string;
|
||||||
}
|
}
|
||||||
interface SystemMessageData {
|
interface SystemMessageData {
|
||||||
command?: Command,
|
command?: Command;
|
||||||
phrase?: string,
|
phrase?: string;
|
||||||
user?: GuildMember | User,
|
user?: GuildMember | User;
|
||||||
error?: Error | PermissionsError | string
|
error?: Error | PermissionsError | string;
|
||||||
}
|
}
|
||||||
|
|
||||||
class SystemMessageManager {
|
class SystemMessageManager {
|
||||||
|
enabled: boolean;
|
||||||
PERMISSION: SystemMessageAppearance;
|
PERMISSION: SystemMessageAppearance;
|
||||||
ERROR: SystemMessageAppearance;
|
ERROR: SystemMessageAppearance;
|
||||||
NOT_FOUND: SystemMessageAppearance;
|
NOT_FOUND: SystemMessageAppearance;
|
||||||
deleteTimeout: number;
|
deleteTimeout: number;
|
||||||
|
|
||||||
constructor(botName?: string) {
|
constructor(botName?: string) {
|
||||||
|
this.enabled = true;
|
||||||
this.PERMISSION = {
|
this.PERMISSION = {
|
||||||
title: '👮♂️ Insufficient permissions',
|
title: "👮♂️ Insufficient permissions",
|
||||||
bottomText: "You don't have enough permissions to run this command",
|
bottomText: "You don't have enough permissions to run this command",
|
||||||
accentColor: '#1d1dc4',
|
accentColor: "#1d1dc4",
|
||||||
showTimestamp: true,
|
showTimestamp: true,
|
||||||
footer: botName
|
footer: botName,
|
||||||
}
|
};
|
||||||
this.ERROR = {
|
this.ERROR = {
|
||||||
title: '❌ An error occurred',
|
title: "❌ An error occurred",
|
||||||
bottomText: 'Something went wrong while processing your request.',
|
bottomText: "Something went wrong while processing your request.",
|
||||||
accentColor: '#ff0000',
|
accentColor: "#ff0000",
|
||||||
showTimestamp: true,
|
showTimestamp: true,
|
||||||
footer: botName
|
footer: botName,
|
||||||
}
|
};
|
||||||
this.NOT_FOUND = {
|
this.NOT_FOUND = {
|
||||||
title: '🔍 Command not found',
|
title: "🔍 Command not found",
|
||||||
accentColor: '#ff5500',
|
accentColor: "#ff5500",
|
||||||
showTimestamp: true,
|
showTimestamp: true,
|
||||||
footer: botName
|
footer: botName,
|
||||||
}
|
};
|
||||||
this.deleteTimeout = Infinity;
|
this.deleteTimeout = Infinity;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -53,67 +64,105 @@ class SystemMessageManager {
|
|||||||
* @param {TextChannel | DMChannel | NewsChannel} [channel] - if specified, the generated message will be sent in this channel
|
* @param {TextChannel | DMChannel | NewsChannel} [channel] - if specified, the generated message will be sent in this channel
|
||||||
* @returns *Promise<MessageEmbed | Message | void>*
|
* @returns *Promise<MessageEmbed | Message | void>*
|
||||||
*/
|
*/
|
||||||
async send(type: MessageType, data?: SystemMessageData, channel?: TextChannel | DMChannel | NewsChannel) : Promise<MessageEmbed | Message | void> {
|
async send(
|
||||||
if(this[type]) {
|
type: MessageType,
|
||||||
|
data?: SystemMessageData,
|
||||||
|
channel?: TextChannel | DMChannel | NewsChannel
|
||||||
|
): Promise<MessageEmbed | Message | void> {
|
||||||
|
if (!this.enabled) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (this[type]) {
|
||||||
const embed = new MessageEmbed();
|
const embed = new MessageEmbed();
|
||||||
embed.setTitle(this[type].title);
|
embed.setTitle(this[type].title);
|
||||||
if(this[type].bottomText) embed.setDescription(this[type].bottomText);
|
if (this[type].bottomText)
|
||||||
embed.setColor(this[type].accentColor || '#000');
|
embed.setDescription(this[type].bottomText);
|
||||||
if(this[type].showTimestamp) embed.setTimestamp();
|
embed.setColor(this[type].accentColor || "#000");
|
||||||
if(this[type].footer) embed.setFooter(this[type].footer);
|
if (this[type].showTimestamp) embed.setTimestamp();
|
||||||
if(data) {
|
if (this[type].footer) embed.setFooter(this[type].footer);
|
||||||
switch(type) {
|
if (data) {
|
||||||
case 'ERROR':
|
switch (type) {
|
||||||
if(data.command) {
|
case "ERROR":
|
||||||
embed.addField('Command name:', data.command.name, false);
|
if (data.command) {
|
||||||
|
embed.addField(
|
||||||
|
"Command name:",
|
||||||
|
data.command.name,
|
||||||
|
false
|
||||||
|
);
|
||||||
}
|
}
|
||||||
if(data.error) {
|
if (data.error) {
|
||||||
if(data.error instanceof Error || data.error instanceof PermissionsError) {
|
if (
|
||||||
embed.addField('Error details:', data.error.toString(), false);
|
data.error instanceof Error ||
|
||||||
}
|
data.error instanceof PermissionsError
|
||||||
else if(typeof data.error == 'string') {
|
) {
|
||||||
embed.addField('Error details:', data.error, false);
|
embed.addField(
|
||||||
|
"Error details:",
|
||||||
|
data.error.toString(),
|
||||||
|
false
|
||||||
|
);
|
||||||
|
} else if (typeof data.error == "string") {
|
||||||
|
embed.addField(
|
||||||
|
"Error details:",
|
||||||
|
data.error,
|
||||||
|
false
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(data.user) {
|
if (data.user) {
|
||||||
embed.addField('User:', data.user.toString(), false);
|
embed.addField(
|
||||||
|
"User:",
|
||||||
|
data.user.toString(),
|
||||||
|
false
|
||||||
|
);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'NOT_FOUND':
|
case "NOT_FOUND":
|
||||||
if(data.phrase) {
|
if (data.phrase) {
|
||||||
embed.addField('Phrase:', data.phrase, false);
|
embed.addField("Phrase:", data.phrase, false);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'PERMISSION':
|
case "PERMISSION":
|
||||||
if(data.user) {
|
if (data.user) {
|
||||||
embed.addField('User:', data.user.toString(), false);
|
embed.addField(
|
||||||
|
"User:",
|
||||||
|
data.user.toString(),
|
||||||
|
false
|
||||||
|
);
|
||||||
}
|
}
|
||||||
if(data.command) {
|
if (data.command) {
|
||||||
embed.addField('Command name:', data.command.name, false);
|
embed.addField(
|
||||||
if(data.command.permissions) {
|
"Command name:",
|
||||||
let permList: string = '';
|
data.command.name,
|
||||||
data.command.permissions.toArray(false).map(p => {
|
false
|
||||||
permList += p + '\n';
|
);
|
||||||
});
|
if (data.command.permissions) {
|
||||||
embed.addField('Required permissions:', permList, false);
|
let permList: string = "";
|
||||||
|
data.command.permissions
|
||||||
|
.toArray(false)
|
||||||
|
.map((p) => {
|
||||||
|
permList += p + "\n";
|
||||||
|
});
|
||||||
|
embed.addField(
|
||||||
|
"Required permissions:",
|
||||||
|
permList,
|
||||||
|
false
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(channel) {
|
if (channel) {
|
||||||
const message = await channel.send(embed);
|
const message = await channel.send(embed);
|
||||||
if(this.deleteTimeout != Infinity && message.deletable) {
|
if (this.deleteTimeout != Infinity && message.deletable) {
|
||||||
await message.delete({ timeout: this.deleteTimeout });
|
await message.delete({ timeout: this.deleteTimeout });
|
||||||
}
|
}
|
||||||
return message;
|
return message;
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
return embed;
|
return embed;
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else {
|
console.error("ERROR! System message: Incorrect parameter");
|
||||||
console.error('ERROR! System message: Incorrect parameter');
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in new issue
Block a user