removed InputParameter + fixed all related errors

This commit is contained in:
mmacierzanka committed 2021-09-08 22:21:19 +02:00
1 parent 38eeb6f788
commit 4724f18fdc
11 files changed
+70 -179

No files matched your search

+1 -6
View File
@@ -7,7 +7,7 @@ import { ChatCommandInit } from "./src/commands/types/ChatCommand.js";
import { HelpMessageParams } from "./src/commands/types/HelpMessage.js";
import { ParameterResolvable, ParameterType, ParameterSchema } from "./src/structures/types/Parameter.js";
import { SystemMessageAppearance, SystemMessageData } from "./src/structures/types/SystemMessage.js";
import { ObjectID, InputParameter, StringParameter, BooleanParameter, NumberParameter, ObjectParameter, Parameter } from "./src/structures/Parameter.js";
import { ObjectID, Parameter } from "./src/structures/parameter.js";
import { PermissionsError, ParameterTypeError, MissingParameterError, OperationSuccess } from "./src/errors.js";
import { CommandInteractionData } from "./src/commands/types/commands.js";
@@ -28,11 +28,6 @@ export {
SystemMessageData,
ParameterSchema,
Parameter,
InputParameter,
StringParameter,
BooleanParameter,
NumberParameter,
ObjectParameter,
PermissionsError,
ParameterTypeError,
MissingParameterError,
+6 -11
View File
@@ -1,11 +1,12 @@
import { Interaction, Message, Permissions, ReplyMessageOptions, MessageEmbed, GuildMember } from "discord.js";
import { PermissionCheckTypes } from "./types/permissions.js";
import { CommandType, BaseCommandInit, CommandFunction } from "./types/BaseCommand.js";
import { InputParameter } from "../structures/Parameter.js";
import { OperationSuccess, PermissionsError } from "../errors.js";
import { BaseCommandObject } from "../structures/types/api.js";
import { ChatCommand } from "./ChatCommand.js";
import { MessageCommand } from "./MessageCommand.js";
import { ParameterResolvable } from "../structures/types/Parameter.js";
import { TargetID } from "../structures/parameter.js";
export class BaseCommand {
/**
@@ -96,13 +97,13 @@ export class BaseCommand {
* @param {InputParameter[]} [cmdParams] - list of processed parameters passed in a Discord interaction
* @returns {Promise<void>}
*/
public async start(interaction: Message | Interaction, args?: InputParameter[]): Promise<void> {
if (interaction instanceof Interaction && !interaction.isCommand() && !interaction.isContextMenu()) return;
public async start(args: ReadonlyMap<string, ParameterResolvable> | TargetID, interaction: Message | Interaction): Promise<void> {
if (interaction instanceof Interaction && !interaction.isCommand() && !interaction.isContextMenu()) throw new TypeError(`Interaction not recognized`);
if (this.permissionChecker(interaction)) {
if (interaction instanceof Interaction) {
await interaction.deferReply();
}
await this.handleReply(interaction, await this.function.call(this, interaction, this.createAccessor(args || [])));
await this.handleReply(interaction, await this.function(args, interaction));
} else {
throw new PermissionsError(this, interaction.member as GuildMember);
}
@@ -121,14 +122,8 @@ export class BaseCommand {
return obj;
}
private createAccessor(args: InputParameter[]) {
return function (query: string, returnType?: "value" | "object") {
return returnType === "object" ? args.find((p) => p.name === query) || null : args.find((p) => p.name === query)?.value || null;
};
}
private async handleReply(interaction: Message | Interaction, result: void | string | MessageEmbed | ReplyMessageOptions) {
if (interaction instanceof Interaction && !interaction.isCommand() && !interaction.isContextMenu()) return null;
if (interaction instanceof Interaction && !interaction.isCommand() && !interaction.isContextMenu()) throw new TypeError(`Interaction not recognized`);
if (
result instanceof Object &&
("content" in (result as any) || "embeds" in (result as any) || "files" in (result as any) || "components" in (result as any) || "sticker" in (result as any))
+3 -3
View File
@@ -1,7 +1,7 @@
import { Message, Interaction } from "discord.js";
import { BaseCommand } from "./BaseCommand.js";
import { ChatCommandInit } from "./types/ChatCommand.js";
import { DefaultParameter, InputParameter, ObjectID, Parameter } from "../structures/Parameter.js";
import { DefaultParameter, ObjectID, Parameter, TargetID } from "../structures/parameter.js";
import { TextCommandObject, TextCommandOptionChoiceObject, TextCommandOptionObject } from "../structures/types/api.js";
import { ParameterResolvable } from "../structures/types/Parameter.js";
import { MissingParameterError, ParameterTypeError } from "errors.js";
@@ -88,11 +88,11 @@ export class ChatCommand extends BaseCommand {
* @param {InputParameter[]} [cmdParams] - list of processed parameters passed in a Discord interaction
* @returns {Promise<void>}
*/
public async start(interaction: Message | Interaction, cmdParams?: InputParameter[]): Promise<void> {
public async start(args: ReadonlyMap<string, ParameterResolvable> | TargetID, interaction: Message | Interaction): Promise<void> {
if (!this.slash && interaction instanceof Interaction) {
throw new Error("This command is not available as a slash command");
}
super.start(interaction, cmdParams);
super.start(args, interaction);
}
/**
+1 -1
View File
@@ -1,5 +1,5 @@
import { Interaction, Message } from "discord.js";
import { TargetID } from "structures/Parameter.js";
import { TargetID } from "structures/parameter.js";
import { CommandNotFound } from "../errors.js";
import { applicationState } from "../state.js";
import { BaseCommand } from "./BaseCommand.js";
+2 -5
View File
@@ -1,8 +1,8 @@
import { MessageEmbed, ReplyMessageOptions, Message, CommandInteraction } from "discord.js";
import { InputParameter } from "../../structures/Parameter.js";
import { ParameterResolvable } from "../../structures/types/Parameter.js";
import { PermissionCheckTypes, PermissionTypes } from "./permissions.js";
import { BaseCommand } from "../BaseCommand.js";
import { TargetID } from "structures/parameter.js";
export interface BaseCommandInit {
name: string;
@@ -17,10 +17,7 @@ export type CommandType = "CHAT" | "MESSAGE" | "USER";
export type CommandFunctionReturnTypes = void | string | MessageEmbed | ReplyMessageOptions | Promise<void | string | MessageEmbed | ReplyMessageOptions>;
export type CommandFunction = (
interaction: Message | CommandInteraction,
argumentAccessor?: (query: string, returnType?: "value" | "object") => ParameterResolvable | InputParameter | null
) => CommandFunctionReturnTypes;
export type CommandFunction = (argumentAccessor: ReadonlyMap<string, ParameterResolvable> | TargetID, interaction?: Message | CommandInteraction) => CommandFunctionReturnTypes;
export interface PhraseOccurrenceData {
command: BaseCommand;
+3 -8
View File
@@ -1,8 +1,6 @@
import { CommandInteraction, Message } from "discord.js";
import { ParameterSchema, ParameterResolvable } from "../../structures/types/Parameter.js";
import { InputParameter } from "../../structures/Parameter.js";
import { ParameterSchema } from "../../structures/types/Parameter.js";
import { PermissionCheckTypes, PermissionTypes } from "./permissions.js";
import { CommandFunctionReturnTypes } from "./BaseCommand.js";
import { CommandFunction } from "./BaseCommand.js";
/**
* @interface
@@ -82,10 +80,7 @@ export interface ChatCommandInit {
* @param {Function} p - function to fetch input parameters' values
* @param {Message | CommandInteraction} i - interaction object
*/
function: (
interaction: Message | CommandInteraction,
params?: (query: string, returnType?: "value" | "object") => ParameterResolvable | InputParameter | null
) => CommandFunctionReturnTypes;
function: CommandFunction;
}
export type GetMode = "ALL" | "PREFIX" | "NO_PREFIX";
+1 -1
View File
@@ -4,7 +4,7 @@ import { MessageCommand } from "../MessageCommand.js";
import { UserCommand } from "../UserCommand.js";
import { Interaction, Message } from "discord.js";
import { ParameterResolvable } from "structures/types/Parameter.js";
import { TargetID } from "structures/Parameter.js";
import { TargetID } from "structures/parameter.js";
export type CommandResolvable = BaseCommand | ChatCommand | MessageCommand | UserCommand;
+1 -1
View File
@@ -1,6 +1,6 @@
import { BaseCommand } from "./commands/BaseCommand.js";
import { GuildMember } from "discord.js";
import { Parameter } from "./structures/Parameter.js";
import { Parameter } from "./structures/parameter.js";
import { ParameterType } from "./structures/types/Parameter.js";
/**
+50 -58
View File
@@ -2,7 +2,7 @@ import { Client, CommandInteraction, GuildMember, Intents, Message } from "disco
import { EventEmitter } from "events";
import * as http from "http";
import { ChatCommand } from "../commands/ChatCommand.js";
import { ChatCommandManager } from "../managers/ChatCommandManager.js";
import { CommandManager } from "../commands/CommandManager";
import { CommandNotFound, OperationSuccess, PermissionsError } from "../errors.js";
import { HelpMessage } from "../commands/Help.js";
import { SystemMessageManager } from "./SystemMessage.js";
@@ -10,7 +10,6 @@ import { CommandInteractionData } from "../commands/types/commands.js";
import { InitOptions } from "./types/Bot.js";
import { HelpMessageParams } from "../commands/types/HelpMessage.js";
import { applicationState } from "../state.js";
import { MessageCommandManager } from "../managers/MessageCommandManager.js";
export declare interface Bot {
on(event: "READY", listener: Function): this;
@@ -37,16 +36,10 @@ export class Bot extends EventEmitter {
public readonly client: Client;
/**
* Instance command manager for chat commands
* Instance command manager
* @type {ChatCommandManager}
*/
public readonly chatCommands: ChatCommandManager;
/**
* Instance command manager for message context menu commands
* @type {MessageCommandManager}
*/
public readonly messageCommands: MessageCommandManager;
public readonly commands: CommandManager;
/**
* Discord bot token
@@ -105,8 +98,7 @@ export class Bot extends EventEmitter {
],
}
);
this.chatCommands = new ChatCommandManager(options.prefix, options.parameterSeparator);
this.messageCommands = new MessageCommandManager();
this.commands = new CommandManager(options.prefix, options.parameterSeparator);
this.token = options.token;
this.applicationId = options.applicationId;
this.messages = {
@@ -136,7 +128,7 @@ export class Bot extends EventEmitter {
throw new Error("This bot is already running");
}
console.log(`\nBot name: ${this.name}`);
console.log(`Prefix: ${this.chatCommands.prefix || "/ (only slash commands)"} \n`);
console.log(`Prefix: ${this.commands.prefix || "/ (only slash commands)"} \n`);
if (this.token === "") {
throw new ReferenceError('No token specified. Please pass your Discord application token as an argument to the "start" method or in the constructor');
}
@@ -146,8 +138,8 @@ export class Bot extends EventEmitter {
console.log("✔");
}
if (this.messages.help.enabled === true) {
const helpMsg: ChatCommand = new HelpMessage(this.chatCommands, this.messages.help, this.name);
this.chatCommands.add(helpMsg);
const helpMsg: ChatCommand = new HelpMessage(this.commands, this.messages.help, this.name);
this.commands.add(helpMsg);
}
applicationState.running = true;
process.stdout.write("Connecting to Discord... ");
@@ -167,7 +159,7 @@ export class Bot extends EventEmitter {
this.client.on("messageCreate", async (m) => {
let cmdMsg: CommandInteractionData | null = null;
try {
cmdMsg = this.chatCommands.fetch(m);
cmdMsg = this.commands.fetch(m);
if (cmdMsg) {
this.emit("COMMAND", m, cmdMsg);
await cmdMsg.command.start(m, cmdMsg.parameters);
@@ -207,49 +199,49 @@ export class Bot extends EventEmitter {
this.client.on("interactionCreate", async (i) => {
let cmd: CommandInteractionData | null = null;
try {
if (i.isContextMenu()) {
switch (i.targetType) {
case "MESSAGE":
cmd = this.messageCommands.fetch(i);
break;
case "USER":
break;
}
} else if (i.isCommand()) {
cmd = this.chatCommands.fetch(i);
}
if (cmd) {
this.emit("COMMAND", i, cmd);
await cmd.command.start(i, cmd.parameters);
}
// if (i.isContextMenu()) {
// switch (i.targetType) {
// case "MESSAGE":
// cmd = this.messageCommands.fetch(i);
// break;
// case "USER":
// break;
// }
// } else if (i.isCommand()) {
// cmd = this.commands.fetch(i);
// }
// if (cmd) {
// this.emit("COMMAND", i, cmd);
// await cmd.command.start(i, cmd.parameters);
// }
} catch (e) {
if (e instanceof PermissionsError) {
await this.messages.system.send(
"PERMISSION",
{
user: (i.member as GuildMember) || undefined,
command: cmd?.command,
},
i as CommandInteraction
);
this.emit("ERROR", e);
} else if (e instanceof OperationSuccess) {
await this.messages.system.send("SUCCESS", undefined, i as CommandInteraction);
} else if (e instanceof CommandNotFound) {
await this.messages.system.send("NOT_FOUND", { user: i.user, phrase: e.query }, i);
} else {
await this.messages.system.send(
"ERROR",
{
command: cmd?.command,
user: (i.member as GuildMember) || undefined,
error: e as Error,
},
i as CommandInteraction
);
this.emit("ERROR", e);
}
return;
// if (e instanceof PermissionsError) {
// await this.messages.system.send(
// "PERMISSION",
// {
// user: (i.member as GuildMember) || undefined,
// command: cmd?.command,
// },
// i as CommandInteraction
// );
// this.emit("ERROR", e);
// } else if (e instanceof OperationSuccess) {
// await this.messages.system.send("SUCCESS", undefined, i as CommandInteraction);
// } else if (e instanceof CommandNotFound) {
// await this.messages.system.send("NOT_FOUND", { user: i.user, phrase: e.query }, i);
// } else {
// await this.messages.system.send(
// "ERROR",
// {
// command: cmd?.command,
// user: (i.member as GuildMember) || undefined,
// error: e as Error,
// },
// i as CommandInteraction
// );
// this.emit("ERROR", e);
// }
// return;
}
});
return true;
+1 -84
View File
@@ -1,5 +1,5 @@
import { CategoryChannel, DMChannel, Guild, GuildMember, Message, NewsChannel, Role, StageChannel, StoreChannel, TextChannel, VoiceChannel } from "discord.js";
import { ParameterType, ParameterResolvable, ParameterSchema } from "./types/Parameter.js";
import { ParameterType, ParameterSchema } from "./types/Parameter.js";
/**
* @class Representation of command parameter
@@ -64,74 +64,6 @@ export class DefaultParameter extends Parameter {
}
}
/**
* @class Representation of input parameter (argument) coming from a message or an interaction
* @extends Parameter
*/
export class InputParameter extends Parameter {
/**
* Input value
* @type {ParameterResolvable}
*/
public readonly value: ParameterResolvable;
constructor(parameter: Parameter, value: ParameterResolvable) {
super(parameter);
this.value = value;
}
}
export class StringParameter extends InputParameter {
constructor(parameter: Parameter, value: ParameterResolvable) {
if (parameter.type != "string") {
throw new Error(`Parameter type mismatch`);
}
if (parameter.choices) {
const match = parameter.choices.filter((c) => c.toLowerCase() === value?.toString().toLowerCase());
if (match.length === 0) {
throw new Error(`Parameter "${parameter.name}" has incorrect value. Please enter one of the following values: ${parameter.choices.join(", ")}`);
} else {
super(parameter, match[0]);
return;
}
}
super(parameter, value?.toString() || "");
}
}
export class BooleanParameter extends InputParameter {
constructor(parameter: Parameter, value: ParameterResolvable) {
if (parameter.type != "boolean") {
throw new Error(`Parameter type mismatch`);
}
if (value?.toString().toLowerCase() === "true") {
super(parameter, true);
} else if (value?.toString().toLowerCase() === "false") {
super(parameter, false);
} else {
throw new Error(`Cannot convert "${parameter.name}" parameter to boolean. Please enter either "true" or "false".`);
}
}
}
export class NumberParameter extends InputParameter {
constructor(parameter: Parameter, value: ParameterResolvable) {
if (parameter.type != "number") {
throw new Error(`Parameter type mismatch`);
}
super(parameter, parseFloat(value ? value.toString() : ""));
}
}
export class ObjectParameter extends InputParameter {
constructor(parameter: Parameter, value: ParameterResolvable) {
if (parameter.type != "channel" && parameter.type != "mentionable" && parameter.type != "user" && parameter.type != "role") {
throw new Error(`Parameter type mismatch`);
}
super(parameter, new ObjectID(value?.toString() || ""));
}
}
export class ObjectID {
public readonly id: string;
@@ -154,21 +86,6 @@ export class ObjectID {
}
}
export class NullParameter extends InputParameter {
constructor(parameter: Parameter) {
if (parameter.optional === false) {
throw new Error(`Parameter "${parameter.name}" cannot be null`);
}
super(parameter, null);
}
}
// export class TargetParameter extends InputParameter {
// constructor(parameter: Parameter, targetId: TargetID) {
// super(parameter, targetId);
// }
// }
export class TargetID {
public readonly id: string;
private readonly type: "MESSAGE" | "USER";
+1 -1
View File
@@ -1,4 +1,4 @@
import { ObjectID, TargetID } from "../Parameter.js";
import { ObjectID, TargetID } from "../parameter.js";
export type ParameterType = "string" | "boolean" | "number" | "user" | "role" | "channel" | "mentionable" | "target";