Parameter types + working on slash commands

This commit is contained in:
mmacierzanka committed 2021-08-07 21:12:02 +02:00
1 parent 6b2899caad
commit 456feb703c
6 files changed
+240 -61

No files matched your search

+17 -7
View File
@@ -25,7 +25,10 @@ export declare interface Bot {
on(event: "MESSAGE", listener: (m: Message) => void): this; on(event: "MESSAGE", listener: (m: Message) => void): this;
on( on(
event: "COMMAND", event: "COMMAND",
listener: (m: Message, cmdMsg: CommandMessageStructure) => void listener: (
m: Message | CommandInteraction,
cmdMsg: CommandMessageStructure
) => void
): this; ): this;
on(event: "ERROR", listener: (e: any) => void): this; on(event: "ERROR", listener: (e: any) => void): this;
} }
@@ -124,12 +127,19 @@ export class Bot extends EventEmitter {
this.commands.list this.commands.list
.filter((c) => !!c.guilds) .filter((c) => !!c.guilds)
.map((c) => { .map((c) => {
c.guilds?.map((g) => { c.guilds?.map(async (g) => {
if (guilds[g.id]) { const guild = await this.client.guilds.fetch(g);
guilds[g.id].push(c.toCommandObject()); if (guild) {
} else { if (guilds[guild.id]) {
guilds[g.id] = []; guilds[guild.id].push(
guilds[g.id].push(c.toCommandObject()); c.toCommandObject()
);
} else {
guilds[guild.id] = [];
guilds[guild.id].push(
c.toCommandObject()
);
}
} }
}); });
}); });
+58 -25
View File
@@ -13,23 +13,23 @@ import {
ParameterResolvable, ParameterResolvable,
} from "./types.js"; } from "./types.js";
import { PermissionsError } from "./errors.js"; import { PermissionsError } from "./errors.js";
import { Parameter } from "./Parameter.js"; import { DefaultParameter, InputParameter, Parameter } from "./Parameter.js";
//CLASSES //CLASSES
export class Command { export class Command {
name: string; name: string;
parameters?: Parameter[]; parameters: Parameter[];
aliases?: string[]; aliases?: string[];
keywords?: string[]; keywords?: string[];
description: string; description: string;
usage?: string; usage?: string;
permissionCheck: PermissionCheckTypes; permissionCheck: PermissionCheckTypes;
permissions?: Permissions; permissions?: Permissions;
guilds?: Guild[]; guilds?: string[];
visible: boolean; visible: boolean;
private function: ( private function: (
interaction?: Message | CommandInteraction, interaction?: Message | CommandInteraction,
cmdParams?: ParameterResolvable[] cmdParams?: InputParameter[]
) => void | string | MessageEmbed | Promise<void | string | MessageEmbed>; ) => void | string | MessageEmbed | Promise<void | string | MessageEmbed>;
/** /**
@@ -50,7 +50,7 @@ export class Command {
this.name = options.name.split(" ").join("_"); this.name = options.name.split(" ").join("_");
this.parameters = options.parameters this.parameters = options.parameters
? options.parameters.map((p) => new Parameter(p)) ? options.parameters.map((p) => new Parameter(p))
: undefined; : [new DefaultParameter()];
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";
@@ -81,7 +81,7 @@ export class Command {
*/ */
async start( async start(
interaction?: Message | CommandInteraction, interaction?: Message | CommandInteraction,
cmdParams?: ParameterResolvable[] cmdParams?: InputParameter[]
): Promise<void> { ): Promise<void> {
if (interaction instanceof Message) { if (interaction instanceof Message) {
const memberPermissions: Readonly<Permissions> = const memberPermissions: Readonly<Permissions> =
@@ -110,30 +110,63 @@ export class Command {
? memberPermissions.has(this.permissions, true) ? memberPermissions.has(this.permissions, true)
: memberPermissions.any(this.permissions, true)) : memberPermissions.any(this.permissions, true))
) { ) {
setTimeout(async () => {
if (!interaction.replied) {
await interaction.reply({
embeds: [
new MessageEmbed()
.setColor("#ffff00")
.setTitle("🔄 Please wait..."),
],
});
}
}, 2000);
const fnResult = await this.function( const fnResult = await this.function(
interaction, interaction,
cmdParams cmdParams
); );
if (typeof fnResult == "string") { try {
await interaction.reply(fnResult); if (typeof fnResult == "string") {
} else if (fnResult instanceof MessageEmbed) { interaction.replied
await interaction.reply({ embeds: [fnResult] }); ? await interaction.editReply({
} else if (!interaction.replied) { content: fnResult,
try { embeds: [],
await interaction.reply({ })
embeds: [ : await interaction.reply({
new MessageEmbed() content: fnResult,
.setColor("#00ff00") embeds: [],
.setTitle( });
"✅ Task completed successfully" } else if (fnResult instanceof MessageEmbed) {
), interaction.replied
], ? await interaction.editReply({
}); embeds: [fnResult],
} catch (e) { })
console.log( : await interaction.reply({
"Cannot reply. The interaction has been closed" embeds: [fnResult],
); });
} else {
interaction.replied
? await interaction.editReply({
embeds: [
new MessageEmbed()
.setColor("#00ff00")
.setTitle(
"✅ Task completed successfully"
),
],
})
: await interaction.reply({
embeds: [
new MessageEmbed()
.setColor("#00ff00")
.setTitle(
"✅ Task completed successfully"
),
],
});
} }
} catch (e) {
console.error("[❌ ERROR] Cannot reply.", e);
} }
} }
} else { } else {
+117 -18
View File
@@ -1,6 +1,13 @@
import { CommandInteraction, Message } from "discord.js"; import { CommandInteraction, Message } from "discord.js";
import { MissingParameterError } from "errors.js"; import { MissingParameterError } from "./errors.js";
import { Parameter } from "Parameter.js"; import {
BooleanParameter,
DefaultParameter,
InputParameter,
NumberParameter,
Parameter,
StringParameter,
} from "./Parameter.js";
import { Command } from "./Command.js"; import { Command } from "./Command.js";
import { import {
CommandMessageStructure, CommandMessageStructure,
@@ -148,22 +155,37 @@ export class CommandManager {
) { ) {
paramsList.splice(0, 1); paramsList.splice(0, 1);
} }
let parameters: ParameterResolvable[] = paramsList; const parameters: InputParameter[] = [];
if (command.parameters) { command.parameters.map((p, i) => {
command.parameters.map((a, i) => { if (!p.optional && !paramsList[i]) {
if (!parameters[i] && !a.optional) { throw new MissingParameterError(p);
throw new MissingParameterError(a); }
} else if (parameters[i]) { switch (p.type) {
parameters[i] = Parameter.processString( case "string":
parameters[i] as string, parameters.push(
a.type new StringParameter(p, paramsList[i])
); );
} break;
}); case "boolean":
} parameters.push(
new BooleanParameter(p, paramsList[i])
);
break;
case "number":
parameters.push(
new NumberParameter(p, paramsList[i])
);
break;
default:
parameters.push(
new InputParameter(p, paramsList[i])
);
break;
}
});
return { return {
command: command, command: command,
parameters: paramsList, parameters: parameters,
}; };
} else { } else {
return null; return null;
@@ -177,11 +199,88 @@ export class CommandManager {
): CommandMessageStructure | null { ): CommandMessageStructure | null {
const cmd = this.get(interaction.commandName); const cmd = this.get(interaction.commandName);
if (cmd) { if (cmd) {
if (interaction.options?.data) { if (
const params = interaction.options.data.map((o) => o.value); cmd.parameters.length == 1 &&
cmd.parameters[0] instanceof DefaultParameter
) {
const argumentsText = interaction.options.data[0]
.value as string;
const paramsList = argumentsText
.split(this.argumentSeparator)
.map((a) => {
return a.replace(" ", "");
});
if (
(paramsList[0] == "" || paramsList[0] == " ") &&
paramsList.length == 1
) {
paramsList.splice(0, 1);
}
const parameters: InputParameter[] = [];
cmd.parameters.map((p, i) => {
if (!p.optional && !paramsList[i]) {
throw new MissingParameterError(p);
}
switch (p.type) {
case "string":
parameters.push(
new StringParameter(p, paramsList[i])
);
break;
case "boolean":
parameters.push(
new BooleanParameter(p, paramsList[i])
);
break;
case "number":
parameters.push(
new NumberParameter(p, paramsList[i])
);
break;
default:
parameters.push(
new InputParameter(p, paramsList[i])
);
break;
}
});
return { return {
command: cmd, command: cmd,
parameters: params, parameters: parameters,
};
} else if (interaction.options?.data) {
const paramsList = interaction.options.data.map((o) => o.value);
const parameters: InputParameter[] = [];
cmd.parameters.map((p, i) => {
if (!p.optional && !paramsList[i]) {
throw new MissingParameterError(p);
}
switch (p.type) {
case "string":
parameters.push(
new StringParameter(p, paramsList[i])
);
break;
case "boolean":
parameters.push(
new BooleanParameter(p, paramsList[i])
);
break;
case "number":
parameters.push(
new NumberParameter(p, paramsList[i])
);
break;
default:
parameters.push(
new InputParameter(p, paramsList[i])
);
break;
}
});
return {
command: cmd,
parameters: parameters,
}; };
} }
} else { } else {
+2 -2
View File
@@ -31,7 +31,7 @@ export class HelpMessage extends Command {
if (helpMsg != null) { if (helpMsg != null) {
if (a && a[0]) { if (a && a[0]) {
const cmd: Command | null = cmdManager.get( const cmd: Command | null = cmdManager.get(
a[0].toString(), a[0].value?.toString() || "",
"ALL" "ALL"
); );
if (cmd) { if (cmd) {
@@ -75,7 +75,7 @@ export class HelpMessage extends Command {
} }
} else { } else {
throw new ReferenceError( throw new ReferenceError(
`Command "${a[0]}" does not exist` `Command "${a[0].value}" does not exist`
); );
} }
} else { } else {
+42
View File
@@ -33,3 +33,45 @@ export class Parameter {
return a; return a;
} }
} }
export class DefaultParameter extends Parameter {
constructor() {
super({
name: "input",
description: "No description",
type: "string",
optional: true,
});
}
}
export class InputParameter extends Parameter {
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`);
}
super(parameter, value?.toString());
}
}
export class BooleanParameter extends InputParameter {
constructor(parameter: Parameter, value: ParameterResolvable) {
if (parameter.type != "boolean") {
throw new Error(`Parameter type mismatch`);
}
super(parameter, value ? true : 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() : ""));
}
}
+4 -9
View File
@@ -3,13 +3,8 @@ import {
ColorResolvable, ColorResolvable,
CommandInteraction, CommandInteraction,
Guild, Guild,
GuildMember,
NewsChannel,
Role,
TextChannel,
VoiceChannel,
} from "discord.js"; } from "discord.js";
import { ParameterSchema } from "./Parameter.js"; import { InputParameter, ParameterSchema } from "./Parameter.js";
import { PermissionResolvable, Message, MessageEmbed } from "discord.js"; import { PermissionResolvable, Message, MessageEmbed } from "discord.js";
import type { Command } from "./Command.js"; import type { Command } from "./Command.js";
@@ -32,11 +27,11 @@ export interface CommandBuilder {
usage?: string; usage?: string;
permissionCheck?: PermissionCheckTypes; permissionCheck?: PermissionCheckTypes;
permissions?: PermissionResolvable; permissions?: PermissionResolvable;
guilds?: Guild[]; guilds?: string[];
visible?: boolean; visible?: boolean;
function: ( function: (
interaction?: Message | CommandInteraction, interaction?: Message | CommandInteraction,
cmdParams?: ParameterResolvable[] cmdParams?: InputParameter[]
) => void | string | MessageEmbed | Promise<void | string | MessageEmbed>; ) => void | string | MessageEmbed | Promise<void | string | MessageEmbed>;
} }
export interface PhraseOccurrenceData { export interface PhraseOccurrenceData {
@@ -45,7 +40,7 @@ export interface PhraseOccurrenceData {
} }
export interface CommandMessageStructure { export interface CommandMessageStructure {
command: Command; command: Command;
parameters: ParameterResolvable[]; parameters: InputParameter[];
} }
export interface HelpMessageParams { export interface HelpMessageParams {
enabled: boolean; enabled: boolean;