diff --git a/src/managers/CommandManager.ts b/src/managers/CommandManager.ts index 99c3cf1..a264cdd 100644 --- a/src/managers/CommandManager.ts +++ b/src/managers/CommandManager.ts @@ -1,15 +1,19 @@ import { CommandInteraction, Message } from "discord.js"; +import { BaseCommand } from "../structures/BaseCommand.js"; import { MissingParameterError } from "../errors.js"; import { BooleanParameter, InputParameter, NumberParameter, ObjectParameter, StringParameter } from "../structures/Parameter.js"; import { TextCommand } from "../structures/TextCommand.js"; import { CommandMessageStructure, PhraseOccurrenceData } from "../types/TextCommand.js"; import { applicationState } from "../state.js"; +import { MessageCommand } from "../structures/MessageCommand.js"; /** * @class Command manager */ export class CommandManager { - private readonly _list: TextCommand[] = []; + private readonly _textCommandsList: TextCommand[] = []; + private readonly _messagesCommandsList: BaseCommand[] = []; + private readonly _userCommandsList: BaseCommand[] = []; /** * Prefix used as a way to trigger the bot using messages * @type {string} @@ -38,7 +42,7 @@ export class CommandManager { */ public get(phrase: string): TextCommand | null { let command: TextCommand | null = null; - this._list.map((c) => { + this._textCommandsList.map((c) => { if (c.name == phrase) { command = c; } @@ -57,47 +61,46 @@ export class CommandManager { * @type {Array} {@link Command} */ get list() { - return Object.freeze([...this._list]); + return Object.freeze([...this._textCommandsList]); } /** * Adds the given {@link Command} to the instance manager with initial processing - * @param {TextCommand} command - {@link Command} instance object + * @param {BaseCommand} command - {@link Command} instance object * @returns {boolean} Whether this command has been added successfully */ - public add(command: TextCommand): boolean { + public add(command: TextCommand | MessageCommand): void { try { if (applicationState.running) { - throw new Error("Cannot add command while the application is running"); + throw new Error("Cannot add a command while the application is running"); } - if (!(command instanceof TextCommand)) { - throw new TypeError("Inavlid argument type"); + if (command instanceof TextCommand) { + const nameOccurrence: PhraseOccurrenceData | null = this.findTextPhraseOccurrence(command.name); + if (nameOccurrence) { + throw new Error(`The name "${command.name}" has already been registered as ${nameOccurrence.type} in the "${nameOccurrence.command.name}" command.`); + } + command.aliases && + command.aliases.map((a, i, ar) => { + const aliasOccurrence: PhraseOccurrenceData | null = this.findTextPhraseOccurrence(a); + 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.` + ); + ar.splice(i, 1); + } + }); + command.parameters && + command.parameters.map((p) => { + if (p.type != "string" && p.choices) { + throw new Error('Parameter with defined choices must have a "string" type'); + } + }); + this._textCommandsList.push(command); + } else { + throw new TypeError("Invalid argument type"); } - const nameOccurrence: PhraseOccurrenceData | null = this.findPhraseOccurrence(command.name); - if (nameOccurrence) { - throw new Error(`The name "${command.name}" has already been registered as ${nameOccurrence.type} in the "${nameOccurrence.command.name}" command.`); - } - command.aliases && - command.aliases.map((a, i, ar) => { - const aliasOccurrence: PhraseOccurrenceData | null = this.findPhraseOccurrence(a); - 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.` - ); - ar.splice(i, 1); - } - }); - command.parameters && - command.parameters.map((p) => { - if (p.type != "string" && p.choices) { - throw new Error('Parameter with defined choices must have a "string" type'); - } - }); - this._list.push(command); - return true; } catch (e) { console.error(`[❌ ERROR] ${e}`); - return false; } } @@ -210,9 +213,9 @@ export class CommandManager { return null; } - private findPhraseOccurrence(phrase?: string): PhraseOccurrenceData | null { + private findTextPhraseOccurrence(phrase?: string): PhraseOccurrenceData | null { let returnValue: PhraseOccurrenceData | null = null; - this._list.map((c) => { + this._textCommandsList.map((c) => { if (phrase == c.name) { returnValue = { command: c, diff --git a/src/structures/MessageCommand.ts b/src/structures/MessageCommand.ts new file mode 100644 index 0000000..a6a9fbb --- /dev/null +++ b/src/structures/MessageCommand.ts @@ -0,0 +1,17 @@ +import { CommandInteraction } from "discord.js"; +import { MessageCommandInit } from "../types/MessageCommand.js"; +import { CommandFunctionReturnTypes } from "../types/BaseCommand.js"; +import { BaseCommand } from "./BaseCommand.js"; + +export class MessageCommand extends BaseCommand { + private readonly function: (i: CommandInteraction) => CommandFunctionReturnTypes; + public static nameRegExp: RegExp = /^[a-zA-Z]{1,32}$/; + + constructor(o: MessageCommandInit) { + super({ + name: o.name, + type: "MESSAGE", + }); + this.function = o.function; + } +} diff --git a/src/structures/TextCommand.ts b/src/structures/TextCommand.ts index a28aaa0..c7d45fb 100644 --- a/src/structures/TextCommand.ts +++ b/src/structures/TextCommand.ts @@ -5,6 +5,7 @@ import { ParameterResolvable } from "../types/Parameter.js"; import { PermissionCheckTypes } from "../types/permissions.js"; import { OperationSuccess, PermissionsError } from "../errors.js"; import { DefaultParameter, InputParameter, Parameter } from "./Parameter.js"; +import { CommandFunctionReturnTypes } from "../types/BaseCommand.js"; /** * @class Class that represents a command instance @@ -72,7 +73,7 @@ export class TextCommand extends BaseCommand { private readonly function: ( params: (query: string, returnType?: "value" | "object") => ParameterResolvable | InputParameter | null, interaction?: Message | CommandInteraction - ) => void | string | MessageEmbed | ReplyMessageOptions | Promise; + ) => CommandFunctionReturnTypes; public static nameRegExp: RegExp = /^[\w-]{1,32}$/; public static descriptionRegExp: RegExp = /^[a-zA-Z]{1,100}$/; diff --git a/src/types/BaseCommand.ts b/src/types/BaseCommand.ts index a4cb79c..9c98598 100644 --- a/src/types/BaseCommand.ts +++ b/src/types/BaseCommand.ts @@ -1,6 +1,10 @@ +import { MessageEmbed, ReplyMessageOptions } from "discord.js"; + export interface BaseCommandInit { name: string; type: CommandType; } export type CommandType = "CHAT" | "MESSAGE" | "USER"; + +export type CommandFunctionReturnTypes = void | string | MessageEmbed | ReplyMessageOptions | Promise; diff --git a/src/types/MessageCommand.ts b/src/types/MessageCommand.ts new file mode 100644 index 0000000..c8797be --- /dev/null +++ b/src/types/MessageCommand.ts @@ -0,0 +1,7 @@ +import { CommandInteraction } from "discord.js"; +import { CommandFunctionReturnTypes } from "./BaseCommand.js"; + +export interface MessageCommandInit { + name: string; + function: (i: CommandInteraction) => CommandFunctionReturnTypes; +} diff --git a/src/types/TextCommand.ts b/src/types/TextCommand.ts index 602e7fa..3175d18 100644 --- a/src/types/TextCommand.ts +++ b/src/types/TextCommand.ts @@ -1,8 +1,9 @@ -import { CommandInteraction, ReplyMessageOptions, PermissionResolvable, Message, MessageEmbed } from "discord.js"; +import { CommandInteraction, PermissionResolvable, Message } from "discord.js"; import { ParameterSchema, ParameterResolvable } from "./Parameter.js"; import { InputParameter } from "../structures/Parameter.js"; import { TextCommand } from "../structures/TextCommand.js"; import { PermissionCheckTypes } from "./permissions.js"; +import { CommandFunctionReturnTypes } from "./BaseCommand.js"; /** * @interface @@ -74,7 +75,7 @@ export interface TextCommandInit { function: ( params: (query: string, returnType?: "value" | "object") => ParameterResolvable | InputParameter | null, interaction?: Message | CommandInteraction - ) => void | string | MessageEmbed | ReplyMessageOptions | Promise; + ) => CommandFunctionReturnTypes; } export interface CommandMessageStructure {