Archived
212 lines
7.3 KiB
TypeScript
212 lines
7.3 KiB
TypeScript
//IMPORTS
|
|
import { Permissions, PermissionResolvable, Message, GuildMember, MessageEmbed } from 'discord.js';
|
|
|
|
//TYPE DEFINITIONS
|
|
interface CommandBuilder {
|
|
name: string,
|
|
aliases?: string[] | string,
|
|
keywords?: string[] | string,
|
|
description?: string,
|
|
usage?: string,
|
|
permissions?: PermissionResolvable,
|
|
visible?: boolean
|
|
function: (message?: Message, cmdArguments?: string[]) => void | string | MessageEmbed;
|
|
}
|
|
interface CommandMessageStructure {
|
|
name: string,
|
|
arguments: string[],
|
|
command: Command | null
|
|
}
|
|
type GetMode = 'ALL' | 'PREFIX' | 'NO_PREFIX';
|
|
|
|
//ERROR CLASSES
|
|
class PermissionsError {
|
|
private command: Command;
|
|
private user: GuildMember | null;
|
|
constructor(command: Command, user?: GuildMember | null) {
|
|
this.command = command;
|
|
this.user = user || null;
|
|
}
|
|
toString() {
|
|
return `User ${this.user?.user.tag} doesn't have enough permissions to run "${this.command.name}" command`;
|
|
}
|
|
}
|
|
|
|
//CLASSES
|
|
class Command {
|
|
name: string;
|
|
aliases: string[];
|
|
keywords: string[];
|
|
description: string;
|
|
usage: string;
|
|
permissions: Permissions;
|
|
visible: boolean;
|
|
private function: (message?: Message, cmdArguments?: string[]) => void | string | MessageEmbed;
|
|
|
|
constructor(options: CommandBuilder) {
|
|
this.name = options.name.split(' ').join('_');
|
|
this.aliases = Command.processPhrase(options.aliases);
|
|
this.keywords = Command.processPhrase(options.keywords);
|
|
this.description = options.description || "No description";
|
|
this.usage = options.usage || "";
|
|
this.permissions = new Permissions(options.permissions || 0);
|
|
this.visible = options.visible || true;
|
|
this.function = options.function;
|
|
}
|
|
async start(message?: Message, cmdArguments?: string[]) {
|
|
const memberPermissions : Readonly<Permissions> = message?.member?.permissions || new Permissions(0);
|
|
if(memberPermissions.has(this.permissions, true)) {
|
|
const fnResult = await this.function(message, cmdArguments);
|
|
if(typeof fnResult == 'string') {
|
|
await message?.reply(fnResult);
|
|
}
|
|
else if(fnResult instanceof MessageEmbed) {
|
|
await message?.channel.send(fnResult);
|
|
}
|
|
}
|
|
else {
|
|
throw new PermissionsError(this, message?.member);
|
|
}
|
|
}
|
|
private static processPhrase(phrase?: string | string[]) : string[] {
|
|
if(Array.isArray(phrase)) {
|
|
const buff = phrase.map((p) => {
|
|
return p.split(' ').join('_');
|
|
});
|
|
return buff;
|
|
}
|
|
else if(typeof phrase == 'string') {
|
|
const buff = [];
|
|
buff.push(phrase.split(' ').join('_'));
|
|
return buff;
|
|
}
|
|
else {
|
|
return [];
|
|
}
|
|
}
|
|
}
|
|
class CommandsManager {
|
|
list: Command[];
|
|
|
|
constructor() {
|
|
this.list = [];
|
|
}
|
|
get(phrase: string, mode?: GetMode) : Command | null {
|
|
if(!mode) mode = 'ALL';
|
|
let command : Command | null = null;
|
|
this.list.map((c) => {
|
|
switch (mode) {
|
|
case 'PREFIX':
|
|
if(c.name == phrase) {
|
|
command = c;
|
|
}
|
|
c.aliases.map(a => {
|
|
if(a == phrase) {
|
|
command = c;
|
|
}
|
|
});
|
|
break;
|
|
case 'NO_PREFIX':
|
|
c.keywords.map(k => {
|
|
if(k == phrase) {
|
|
command = c;
|
|
}
|
|
});
|
|
break;
|
|
case 'ALL':
|
|
if(c.name == phrase) {
|
|
command = c;
|
|
}
|
|
c.aliases.map(a => {
|
|
if(a == phrase) {
|
|
command = c;
|
|
}
|
|
});
|
|
c.keywords.map(k => {
|
|
if(k == phrase) {
|
|
command = c;
|
|
}
|
|
});
|
|
break;
|
|
}
|
|
});
|
|
return command;
|
|
}
|
|
add(command: Command) : boolean {
|
|
try {
|
|
this.list.map((c) => {
|
|
if(c.name == command.name) {
|
|
throw new Error(`Command with name "${c.name}" already exists!`);
|
|
}
|
|
command.aliases.map((a) => {
|
|
if(c.aliases.indexOf(a) != -1) {
|
|
console.warn(`WARN! Alias with name "${a}" already exists in "${c.name}" command. It will be removed from the "${command.name}" command`);
|
|
const iToRemove = command.aliases.indexOf(a);
|
|
command.aliases.splice(iToRemove, 1);
|
|
}
|
|
});
|
|
command.keywords.map((k) => {
|
|
if(c.keywords.indexOf(k) != -1) {
|
|
console.warn(`WARN! Keyword "${k}" already exists in "${c.name}" command. It will be removed from the "${command.name}" command`);
|
|
const iToRemove = command.keywords.indexOf(k);
|
|
command.keywords.splice(iToRemove, 1);
|
|
}
|
|
});
|
|
});
|
|
this.list.push(command);
|
|
return true;
|
|
}
|
|
catch(e) {
|
|
console.error(`ERROR! ${e.toString()}`);
|
|
return false;
|
|
}
|
|
}
|
|
fetch(message: Message, prefix: string) : CommandMessageStructure | null {
|
|
if(!message.author.bot && message.content.startsWith(prefix)) {
|
|
let msgContent = message.content.replace(prefix, '');
|
|
const cmdName = msgContent.split(' ')[0];
|
|
const cmd: Command | null = this.get(cmdName, 'PREFIX');
|
|
msgContent = msgContent.replace(cmdName, '');
|
|
let cmdArguments: string[] = msgContent.split(',');
|
|
cmdArguments = cmdArguments.map((a) => {
|
|
return a.replace(' ', '');
|
|
});
|
|
if((cmdArguments[0] == '' || cmdArguments[0] == ' ') && cmdArguments.length == 1) {
|
|
cmdArguments = [];
|
|
}
|
|
return {
|
|
name: cmdName,
|
|
arguments: cmdArguments,
|
|
command: cmd
|
|
}
|
|
}
|
|
else if(!message.author.bot) {
|
|
const cmdName = message.content.split(' ')[0];
|
|
const cmd: Command | null = this.get(cmdName, 'NO_PREFIX');
|
|
if(cmd) {
|
|
const cmdArgumentsStr = message.content.replace(cmdName, '');
|
|
let cmdArguments: string[] = cmdArgumentsStr.split(',');
|
|
cmdArguments = cmdArguments.map((a) => {
|
|
return a.replace(' ', '');
|
|
});
|
|
if((cmdArguments[0] == '' || cmdArguments[0] == ' ') && cmdArguments.length == 1) {
|
|
cmdArguments = [];
|
|
}
|
|
return {
|
|
name: cmdName,
|
|
arguments: cmdArguments,
|
|
command: cmd
|
|
}
|
|
}
|
|
else {
|
|
return null;
|
|
}
|
|
}
|
|
else {
|
|
return null;
|
|
}
|
|
}
|
|
}
|
|
|
|
//EXPORTS
|
|
export { Command, CommandsManager, CommandMessageStructure, PermissionsError } |