Reformatted source files (print width: 180)

This commit is contained in:
mmacierzanka committed 2021-08-20 21:31:15 +02:00
1 parent 54c4c38d62
commit f57c3b3f86
8 files changed
+94 -403

No files matched your search

+1 -9
View File
@@ -5,12 +5,4 @@ import { MessageEmbed } from "discord.js";
import { ObjectID, InputParameter } from "./src/Parameter.js"; import { ObjectID, InputParameter } from "./src/Parameter.js";
export default Bot; export default Bot;
export { export { Bot, Command, MessageEmbed, ParameterResolvable, ParameterType, ObjectID, InputParameter };
Bot,
Command,
MessageEmbed,
ParameterResolvable,
ParameterType,
ObjectID,
InputParameter,
};
+16 -66
View File
@@ -1,11 +1,5 @@
import axios from "axios"; import axios from "axios";
import { import { Client, CommandInteraction, GuildMember, Intents, Message } from "discord.js";
Client,
CommandInteraction,
GuildMember,
Intents,
Message,
} from "discord.js";
import { EventEmitter } from "events"; import { EventEmitter } from "events";
import * as http from "http"; import * as http from "http";
import { Command } from "./Command.js"; import { Command } from "./Command.js";
@@ -13,22 +7,12 @@ import { CommandManager } from "./CommandManager.js";
import { OperationSuccess, PermissionsError } from "./errors.js"; import { OperationSuccess, PermissionsError } from "./errors.js";
import { HelpMessage } from "./Help.js"; import { HelpMessage } from "./Help.js";
import { SystemMessageManager } from "./SystemMessage.js"; import { SystemMessageManager } from "./SystemMessage.js";
import { import { CommandMessageStructure, InitOptions, HelpMessageParams } from "./types.js";
CommandMessageStructure,
InitOptions,
HelpMessageParams,
} from "./types.js";
export declare interface Bot { export declare interface Bot {
on(event: "READY", listener: Function): this; on(event: "READY", listener: Function): this;
on(event: "MESSAGE", listener: (m: Message) => void): this; on(event: "MESSAGE", listener: (m: Message) => void): this;
on( on(event: "COMMAND", listener: (m: Message | CommandInteraction, cmdMsg: CommandMessageStructure) => void): this;
event: "COMMAND",
listener: (
m: Message | CommandInteraction,
cmdMsg: CommandMessageStructure
) => void
): this;
on(event: "ERROR", listener: (e: any) => void): this; on(event: "ERROR", listener: (e: any) => void): this;
} }
@@ -78,10 +62,7 @@ export class Bot extends EventEmitter {
], ],
} }
); );
this.commands = new CommandManager( this.commands = new CommandManager(options.prefix, options.argumentSeparator);
options.prefix,
options.argumentSeparator
);
this.token = options.token; this.token = options.token;
this.applicationId = options.applicationId; this.applicationId = options.applicationId;
this.messages = { this.messages = {
@@ -106,29 +87,17 @@ export class Bot extends EventEmitter {
async start(port?: number, register?: boolean): Promise<boolean> { async start(port?: number, register?: boolean): Promise<boolean> {
try { try {
console.log(`\nBot name: ${this.name}`); console.log(`\nBot name: ${this.name}`);
console.log( console.log(`Prefix: ${this.commands.prefix || "/ (only slash commands)"} \n`);
`Prefix: ${
this.commands.prefix || "/ (only slash commands)"
} \n`
);
if (this.token === "") { if (this.token === "") {
throw new ReferenceError( throw new ReferenceError('No token specified. Please pass your Discord application token as an argument to the "start" method or in the constructor');
'No token specified. Please pass your Discord application token as an argument to the "start" method or in the constructor'
);
} }
if (port) { if (port) {
process.stdout.write( process.stdout.write(`Creating http server on port ${port}... `);
`Creating http server on port ${port}... `
);
http.createServer().listen(port); http.createServer().listen(port);
console.log("✔"); console.log("✔");
} }
if (this.messages.help.enabled === true) { if (this.messages.help.enabled === true) {
const helpMsg: Command = new HelpMessage( const helpMsg: Command = new HelpMessage(this.commands, this.messages.help, this.name);
this.commands,
this.messages.help,
this.name
);
this.commands.add(helpMsg); this.commands.add(helpMsg);
} }
process.stdout.write("Connecting to Discord... "); process.stdout.write("Connecting to Discord... ");
@@ -139,9 +108,7 @@ export class Bot extends EventEmitter {
process.stdout.write("Registering commands... "); process.stdout.write("Registering commands... ");
await axios.put( await axios.put(
`https://discord.com/api/v8/applications/${this.applicationId}/commands`, `https://discord.com/api/v8/applications/${this.applicationId}/commands`,
this.commands.list this.commands.list.filter((c) => !c.guilds && c.slash).map((c) => (!c.guilds ? c.toCommandObject() : {})),
.filter((c) => !c.guilds && c.slash)
.map((c) => (!c.guilds ? c.toCommandObject() : {})),
{ headers: { Authorization: `Bot ${this.token}` } } { headers: { Authorization: `Bot ${this.token}` } }
); );
const guilds: any = {}; const guilds: any = {};
@@ -158,11 +125,9 @@ export class Bot extends EventEmitter {
}); });
}); });
for (let i in guilds) { for (let i in guilds) {
await axios.put( await axios.put(`https://discord.com/api/v8/applications/${this.applicationId}/guilds/${i}/commands`, guilds[i], {
`https://discord.com/api/v8/applications/${this.applicationId}/guilds/${i}/commands`, headers: { Authorization: `Bot ${this.token}` },
guilds[i], });
{ headers: { Authorization: `Bot ${this.token}` } }
);
} }
console.log("✔\n"); console.log("✔\n");
} else { } else {
@@ -177,16 +142,9 @@ export class Bot extends EventEmitter {
if (cmdMsg) { if (cmdMsg) {
this.emit("COMMAND", m, cmdMsg); this.emit("COMMAND", m, cmdMsg);
await cmdMsg.command.start(m, cmdMsg.parameters); await cmdMsg.command.start(m, cmdMsg.parameters);
} else if ( } else if (this.commands.prefix && m.content.startsWith(this.commands.prefix)) {
this.commands.prefix &&
m.content.startsWith(this.commands.prefix)
) {
this.emit("MESSAGE", m); this.emit("MESSAGE", m);
await this.messages.system.send( await this.messages.system.send("NOT_FOUND", { phrase: m.content, user: m.member || undefined }, m);
"NOT_FOUND",
{ phrase: m.content, user: m.member || undefined },
m
);
} else { } else {
this.emit("MESSAGE", m); this.emit("MESSAGE", m);
} }
@@ -201,11 +159,7 @@ export class Bot extends EventEmitter {
m m
); );
} else if (e instanceof OperationSuccess) { } else if (e instanceof OperationSuccess) {
await this.messages.system.send( await this.messages.system.send("SUCCESS", undefined, m);
"SUCCESS",
undefined,
m
);
} else { } else {
await this.messages.system.send( await this.messages.system.send(
"ERROR", "ERROR",
@@ -251,11 +205,7 @@ export class Bot extends EventEmitter {
i as CommandInteraction i as CommandInteraction
); );
} else if (e instanceof OperationSuccess) { } else if (e instanceof OperationSuccess) {
await this.messages.system.send( await this.messages.system.send("SUCCESS", undefined, i as CommandInteraction);
"SUCCESS",
undefined,
i as CommandInteraction
);
} else { } else {
await this.messages.system.send( await this.messages.system.send(
"ERROR", "ERROR",
+23 -89
View File
@@ -1,17 +1,6 @@
//IMPORTS //IMPORTS
import { import { Permissions, Message, MessageEmbed, CommandInteraction, GuildMember, ReplyMessageOptions } from "discord.js";
Permissions, import { CommandBuilder, ParameterResolvable, PermissionCheckTypes } from "./types.js";
Message,
MessageEmbed,
CommandInteraction,
GuildMember,
ReplyMessageOptions,
} from "discord.js";
import {
CommandBuilder,
ParameterResolvable,
PermissionCheckTypes,
} from "./types.js";
import { OperationSuccess, PermissionsError } from "./errors.js"; import { OperationSuccess, PermissionsError } from "./errors.js";
import { DefaultParameter, InputParameter, Parameter } from "./Parameter.js"; import { DefaultParameter, InputParameter, Parameter } from "./Parameter.js";
@@ -29,17 +18,9 @@ export class Command {
slash: boolean; slash: boolean;
announceSuccess: boolean; announceSuccess: boolean;
private function: ( private function: (
params: ( params: (query: string, returnType?: "value" | "object") => ParameterResolvable | InputParameter | null,
query: string,
returnType?: "value" | "object"
) => ParameterResolvable | InputParameter | null,
interaction?: Message | CommandInteraction interaction?: Message | CommandInteraction
) => ) => void | string | MessageEmbed | ReplyMessageOptions | Promise<void | string | MessageEmbed | ReplyMessageOptions>;
| void
| string
| MessageEmbed
| ReplyMessageOptions
| Promise<void | string | MessageEmbed | ReplyMessageOptions>;
/** /**
* Command constructor * Command constructor
@@ -68,20 +49,12 @@ export class Command {
this.aliases = Command.processPhrase(options.aliases); this.aliases = Command.processPhrase(options.aliases);
this.description = options.description || "No description"; this.description = options.description || "No description";
this.usage = options.usage || this.generateUsageFromArguments(); this.usage = options.usage || this.generateUsageFromArguments();
this.permissionCheck = this.permissionCheck = options.permissionCheck == "ALL" || options.permissionCheck == "ANY" ? options.permissionCheck : "ANY";
options.permissionCheck == "ALL" || options.permissionCheck == "ANY" this.permissions = options.permissions ? new Permissions(options.permissions) : undefined;
? options.permissionCheck
: "ANY";
this.permissions = options.permissions
? new Permissions(options.permissions)
: undefined;
this.guilds = options.guilds; this.guilds = options.guilds;
this.visible = options.visible !== undefined ? options.visible : true; this.visible = options.visible !== undefined ? options.visible : true;
this.slash = options.slash !== undefined ? options.slash : true; this.slash = options.slash !== undefined ? options.slash : true;
this.announceSuccess = this.announceSuccess = options.announceSuccess !== undefined ? options.announceSuccess : true;
options.announceSuccess !== undefined
? options.announceSuccess
: true;
this.function = options.function; this.function = options.function;
if (!/^[\w-]{1,32}$/.test(this.name)) { if (!/^[\w-]{1,32}$/.test(this.name)) {
throw new Error(`Incorrect command name: ${this.name}`); throw new Error(`Incorrect command name: ${this.name}`);
@@ -97,35 +70,16 @@ export class Command {
* @param {InputParameter[]} [cmdParams] - list of processed parameters passed in a Discord message * @param {InputParameter[]} [cmdParams] - list of processed parameters passed in a Discord message
* @returns *Promise<void>* * @returns *Promise<void>*
*/ */
async start( async start(interaction?: Message | CommandInteraction, cmdParams?: InputParameter[]): Promise<void> {
interaction?: Message | CommandInteraction, const paramFindFn = function (query: string, returnType?: "value" | "object") {
cmdParams?: InputParameter[] return returnType === "object" ? cmdParams?.find((p) => p.name === query) || null : cmdParams?.find((p) => p.name === query)?.value || null;
): Promise<void> {
const paramFindFn = function (
query: string,
returnType?: "value" | "object"
) {
return returnType === "object"
? cmdParams?.find((p) => p.name === query) || null
: cmdParams?.find((p) => p.name === query)?.value || null;
}; };
const memberPermissions: Readonly<Permissions> = const memberPermissions: Readonly<Permissions> = (interaction?.member?.permissions as Permissions) || new Permissions();
(interaction?.member?.permissions as Permissions) || if (!this.permissions || (this.permissionCheck == "ALL" ? memberPermissions.has(this.permissions, true) : memberPermissions.any(this.permissions, true))) {
new Permissions();
if (
!this.permissions ||
(this.permissionCheck == "ALL"
? memberPermissions.has(this.permissions, true)
: memberPermissions.any(this.permissions, true))
) {
if (interaction instanceof CommandInteraction) { if (interaction instanceof CommandInteraction) {
await interaction.deferReply(); await interaction.deferReply();
} }
const fnResult = await this.function.call( const fnResult = await this.function.call(this, paramFindFn, interaction);
this,
paramFindFn,
interaction
);
if ( if (
fnResult instanceof Object && fnResult instanceof Object &&
("content" in (fnResult as any) || ("content" in (fnResult as any) ||
@@ -134,34 +88,24 @@ export class Command {
"components" in (fnResult as any) || "components" in (fnResult as any) ||
"sticker" in (fnResult as any)) "sticker" in (fnResult as any))
) { ) {
if (interaction instanceof Message) if (interaction instanceof Message) await interaction.reply(fnResult as ReplyMessageOptions);
await interaction.reply(fnResult as ReplyMessageOptions); else if (interaction instanceof CommandInteraction) await interaction.editReply(fnResult as ReplyMessageOptions);
else if (interaction instanceof CommandInteraction)
await interaction.editReply(
fnResult as ReplyMessageOptions
);
} else if (typeof fnResult == "string") { } else if (typeof fnResult == "string") {
if (interaction instanceof Message) if (interaction instanceof Message) await interaction?.reply({ content: fnResult });
await interaction?.reply({ content: fnResult });
else if (interaction instanceof CommandInteraction) else if (interaction instanceof CommandInteraction)
await interaction.editReply({ await interaction.editReply({
content: fnResult, content: fnResult,
}); });
} else if (fnResult instanceof MessageEmbed) { } else if (fnResult instanceof MessageEmbed) {
if (interaction instanceof Message) if (interaction instanceof Message) await interaction?.reply({ embeds: [fnResult] });
await interaction?.reply({ embeds: [fnResult] }); else if (interaction instanceof CommandInteraction) await interaction.editReply({ embeds: [fnResult] });
else if (interaction instanceof CommandInteraction)
await interaction.editReply({ embeds: [fnResult] });
} else if (this.announceSuccess) { } else if (this.announceSuccess) {
throw new OperationSuccess(this); throw new OperationSuccess(this);
} else if (interaction instanceof CommandInteraction) { } else if (interaction instanceof CommandInteraction) {
await interaction.deleteReply(); await interaction.deleteReply();
} }
} else { } else {
throw new PermissionsError( throw new PermissionsError(this, interaction?.member as GuildMember);
this,
interaction?.member as GuildMember
);
} }
} }
@@ -175,14 +119,10 @@ export class Command {
options = this.parameters.map((p) => { options = this.parameters.map((p) => {
let type = 3; let type = 3;
if (!/^[\w-]{1,32}$/.test(p.name)) { if (!/^[\w-]{1,32}$/.test(p.name)) {
throw new Error( throw new Error(`Failed to register ${p.name} parameter for ${this.name}: The option name is incorrect`);
`Failed to register ${p.name} parameter for ${this.name}: The option name is incorrect`
);
} }
if ((p.description || "No description").length > 100) { if ((p.description || "No description").length > 100) {
throw new Error( throw new Error(`Failed to register ${p.name} parameter for ${this.name}: The description is too long`);
`Failed to register ${p.name} parameter for ${this.name}: The description is too long`
);
} }
if (p.type == "boolean") type = 5; if (p.type == "boolean") type = 5;
else if (p.type == "user") type = 6; else if (p.type == "user") type = 6;
@@ -206,9 +146,7 @@ export class Command {
}; };
} }
private static processPhrase( private static processPhrase(phrase?: string | string[]): string[] | undefined {
phrase?: string | string[]
): string[] | undefined {
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("_");
@@ -232,11 +170,7 @@ export class Command {
let usageTemplate: string = ""; let usageTemplate: string = "";
this.parameters && this.parameters &&
this.parameters.map((e) => { this.parameters.map((e) => {
usageTemplate += `[${e.name} (${ usageTemplate += `[${e.name} (${e.choices ? e.choices.map((c) => c.name).join(" / ") : e.type}${e.optional ? ", optional" : ""})] `;
e.choices
? e.choices.map((c) => c.name).join(" / ")
: e.type
}${e.optional ? ", optional" : ""})] `;
}); });
return usageTemplate; return usageTemplate;
} }
+17 -54
View File
@@ -1,12 +1,6 @@
import { CommandInteraction, Message } from "discord.js"; import { CommandInteraction, Message } from "discord.js";
import { MissingParameterError } from "./errors.js"; import { MissingParameterError } from "./errors.js";
import { import { BooleanParameter, InputParameter, NumberParameter, ObjectParameter, StringParameter } from "./Parameter.js";
BooleanParameter,
InputParameter,
NumberParameter,
ObjectParameter,
StringParameter,
} from "./Parameter.js";
import { Command } from "./Command.js"; import { Command } from "./Command.js";
import { CommandMessageStructure, PhraseOccurrenceData } from "./types.js"; import { CommandMessageStructure, PhraseOccurrenceData } from "./types.js";
@@ -53,17 +47,13 @@ export class CommandManager {
if (!(command instanceof Command)) { if (!(command instanceof Command)) {
throw new TypeError("Inavlid argument type"); throw new TypeError("Inavlid argument type");
} }
const nameOccurrence: PhraseOccurrenceData | null = const nameOccurrence: PhraseOccurrenceData | null = this.findPhraseOccurrence(command.name);
this.findPhraseOccurrence(command.name);
if (nameOccurrence) { if (nameOccurrence) {
throw new Error( throw new Error(`The name "${command.name}" has already been registered as ${nameOccurrence.type} in the "${nameOccurrence.command.name}" command.`);
`The name "${command.name}" has already been registered as ${nameOccurrence.type} in the "${nameOccurrence.command.name}" command.`
);
} }
command.aliases && command.aliases &&
command.aliases.map((a, i, ar) => { command.aliases.map((a, i, ar) => {
const aliasOccurrence: PhraseOccurrenceData | null = const aliasOccurrence: PhraseOccurrenceData | null = this.findPhraseOccurrence(a);
this.findPhraseOccurrence(a);
if (aliasOccurrence) { if (aliasOccurrence) {
console.warn( 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.` `[⚠ 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.`
@@ -92,15 +82,10 @@ export class CommandManager {
const command = this.get(name); const command = this.get(name);
if (command) { if (command) {
const argumentsText = content.replace(name, ""); const argumentsText = content.replace(name, "");
const paramsList = argumentsText const paramsList = argumentsText.split(this.argumentSeparator).map((a) => {
.split(this.argumentSeparator)
.map((a) => {
return a.replace(" ", ""); return a.replace(" ", "");
}); });
if ( if ((paramsList[0] == "" || paramsList[0] == " ") && paramsList.length == 1) {
(paramsList[0] == "" || paramsList[0] == " ") &&
paramsList.length == 1
) {
paramsList.splice(0, 1); paramsList.splice(0, 1);
} }
const parameters: InputParameter[] = []; const parameters: InputParameter[] = [];
@@ -115,29 +100,19 @@ export class CommandManager {
case "channel": case "channel":
case "role": case "role":
case "user": case "user":
parameters.push( parameters.push(new ObjectParameter(p, paramsList[i]));
new ObjectParameter(p, paramsList[i])
);
break; break;
case "string": case "string":
parameters.push( parameters.push(new StringParameter(p, paramsList[i]));
new StringParameter(p, paramsList[i])
);
break; break;
case "boolean": case "boolean":
parameters.push( parameters.push(new BooleanParameter(p, paramsList[i]));
new BooleanParameter(p, paramsList[i])
);
break; break;
case "number": case "number":
parameters.push( parameters.push(new NumberParameter(p, paramsList[i]));
new NumberParameter(p, paramsList[i])
);
break; break;
default: default:
parameters.push( parameters.push(new InputParameter(p, paramsList[i]));
new InputParameter(p, paramsList[i])
);
break; break;
} }
}); });
@@ -158,9 +133,7 @@ export class CommandManager {
* @param {CommandInteraction} interaction - interaction object * @param {CommandInteraction} interaction - interaction object
* @returns *CommandMessagesStructure* | *null* * @returns *CommandMessagesStructure* | *null*
*/ */
fetchFromInteraction( fetchFromInteraction(interaction: CommandInteraction): CommandMessageStructure | null {
interaction: CommandInteraction
): CommandMessageStructure | null {
const cmd = this.get(interaction.commandName); const cmd = this.get(interaction.commandName);
if (cmd) { if (cmd) {
if (interaction.options?.data) { if (interaction.options?.data) {
@@ -178,29 +151,19 @@ export class CommandManager {
case "channel": case "channel":
case "role": case "role":
case "user": case "user":
parameters.push( parameters.push(new ObjectParameter(p, inputParam?.value));
new ObjectParameter(p, inputParam?.value)
);
break; break;
case "string": case "string":
parameters.push( parameters.push(new StringParameter(p, inputParam?.value));
new StringParameter(p, inputParam?.value)
);
break; break;
case "boolean": case "boolean":
parameters.push( parameters.push(new BooleanParameter(p, inputParam?.value));
new BooleanParameter(p, inputParam?.value)
);
break; break;
case "number": case "number":
parameters.push( parameters.push(new NumberParameter(p, inputParam?.value));
new NumberParameter(p, inputParam?.value)
);
break; break;
default: default:
parameters.push( parameters.push(new InputParameter(p, inputParam?.value));
new InputParameter(p, inputParam?.value)
);
break; break;
} }
}); });
+9 -42
View File
@@ -4,11 +4,7 @@ import { CommandManager } from "./CommandManager.js";
import { HelpMessageParams } from "./types.js"; import { HelpMessageParams } from "./types.js";
export class HelpMessage extends Command { export class HelpMessage extends Command {
constructor( constructor(cmdManager: CommandManager, params: HelpMessageParams, botName?: string) {
cmdManager: CommandManager,
params: HelpMessageParams,
botName?: string
) {
super({ super({
name: "help", name: "help",
usage: params.usage, usage: params.usage,
@@ -17,8 +13,7 @@ export class HelpMessage extends Command {
parameters: [ parameters: [
{ {
name: "command_name", name: "command_name",
description: description: "Name of the command that you want to get details about",
"Name of the command that you want to get details about",
optional: true, optional: true,
type: "string", type: "string",
}, },
@@ -30,35 +25,17 @@ export class HelpMessage extends Command {
helpMsg.setFooter(botName || ""); helpMsg.setFooter(botName || "");
if (helpMsg != null) { if (helpMsg != null) {
if (param("command_name")) { if (param("command_name")) {
const cmd: Command | null = cmdManager.get( const cmd: Command | null = cmdManager.get(param("command_name")?.toString() || "");
param("command_name")?.toString() || ""
);
if (cmd) { if (cmd) {
helpMsg.setTitle( helpMsg.setTitle(`${cmd.name} ${cmd.visible ? "" : "[HIDDEN]"}`);
`${cmd.name} ${cmd.visible ? "" : "[HIDDEN]"}`
);
helpMsg.setDescription(cmd.description); helpMsg.setDescription(cmd.description);
if (cmd.usage) if (cmd.usage) helpMsg.addField("Usage:", `${cmdManager.prefix || "/"}${cmd.name} ${cmd.usage}`, false);
helpMsg.addField( if (cmd.permissions && cmd.permissions.toArray(false).length > 0) {
"Usage:",
`${cmdManager.prefix || "/"}${cmd.name} ${
cmd.usage
}`,
false
);
if (
cmd.permissions &&
cmd.permissions.toArray(false).length > 0
) {
let permList: string = ""; let permList: string = "";
cmd.permissions.toArray(false).map((p) => { cmd.permissions.toArray(false).map((p) => {
permList += p + "\n"; permList += p + "\n";
}); });
helpMsg.addField( helpMsg.addField("Permissions:", permList, false);
"Permissions:",
permList,
false
);
} }
if (cmd.aliases && cmd.aliases.length > 0) { if (cmd.aliases && cmd.aliases.length > 0) {
let aList: string = ""; let aList: string = "";
@@ -68,11 +45,7 @@ export class HelpMessage extends Command {
helpMsg.addField("Aliases:", aList, false); helpMsg.addField("Aliases:", aList, false);
} }
} else { } else {
throw new ReferenceError( throw new ReferenceError(`Command "${param("command_name")}" does not exist`);
`Command "${param(
"command_name"
)}" does not exist`
);
} }
} else { } else {
helpMsg.setTitle(params.title); helpMsg.setTitle(params.title);
@@ -80,13 +53,7 @@ export class HelpMessage extends Command {
cmdManager.list.map((c) => { cmdManager.list.map((c) => {
if (c.visible) { if (c.visible) {
helpMsg.addField( helpMsg.addField(`${cmdManager.prefix || "/"}${c.name} ${c.usage}`, c.description, false);
`${cmdManager.prefix || "/"}${c.name} ${
c.usage
}`,
c.description,
false
);
} }
}); });
} }
+10 -53
View File
@@ -1,14 +1,4 @@
import { import { CategoryChannel, Guild, GuildMember, NewsChannel, Role, StageChannel, StoreChannel, TextChannel, VoiceChannel } from "discord.js";
CategoryChannel,
Guild,
GuildMember,
NewsChannel,
Role,
StageChannel,
StoreChannel,
TextChannel,
VoiceChannel,
} from "discord.js";
import { ParameterType, ParameterResolvable, Choice } from "./types.js"; import { ParameterType, ParameterResolvable, Choice } from "./types.js";
export interface ParameterSchema { export interface ParameterSchema {
name: string; name: string;
@@ -31,9 +21,7 @@ export class Parameter {
this.type = options.type; this.type = options.type;
this.choices = options.choices; this.choices = options.choices;
if (!/^[\w-]{1,32}$/.test(this.name)) { if (!/^[\w-]{1,32}$/.test(this.name)) {
throw new Error( throw new Error(`Parameter name ${this.name} doesn't match the pattern`);
`Parameter name ${this.name} doesn't match the pattern`
);
} }
if (this.description.length > 100) { if (this.description.length > 100) {
throw new Error(`Parameter ${this.name}: Description too long`); throw new Error(`Parameter ${this.name}: Description too long`);
@@ -65,16 +53,10 @@ export class StringParameter extends InputParameter {
throw new Error(`Parameter type mismatch`); throw new Error(`Parameter type mismatch`);
} }
if (parameter.choices) { if (parameter.choices) {
const match = parameter.choices.filter( const match = parameter.choices.filter((c) => c.name.toLowerCase() === value?.toString().toLowerCase() || c.value.toLowerCase() === value?.toString().toLowerCase());
(c) =>
c.name.toLowerCase() === value?.toString().toLowerCase() ||
c.value.toLowerCase() === value?.toString().toLowerCase()
);
if (match.length === 0) { if (match.length === 0) {
throw new Error( throw new Error(
`Parameter "${ `Parameter "${parameter.name}" has incorrect value. Please enter one of the following values: ${parameter.choices
parameter.name
}" has incorrect value. Please enter one of the following values: ${parameter.choices
.map((c) => [c.name, c.value]) .map((c) => [c.name, c.value])
.flat(1) .flat(1)
.join(", ")}` .join(", ")}`
@@ -97,9 +79,7 @@ export class BooleanParameter extends InputParameter {
} else if (value?.toString().toLowerCase() === "false") { } else if (value?.toString().toLowerCase() === "false") {
super(parameter, false); super(parameter, false);
} else { } else {
throw new Error( throw new Error(`Cannot convert "${parameter.name}" parameter to boolean. Please enter either "true" or "false".`);
`Cannot convert "${parameter.name}" parameter to boolean. Please enter either "true" or "false".`
);
} }
} }
} }
@@ -113,12 +93,7 @@ export class NumberParameter extends InputParameter {
} }
export class ObjectParameter extends InputParameter { export class ObjectParameter extends InputParameter {
constructor(parameter: Parameter, value: ParameterResolvable) { constructor(parameter: Parameter, value: ParameterResolvable) {
if ( if (parameter.type != "channel" && parameter.type != "mentionable" && parameter.type != "user" && parameter.type != "role") {
parameter.type != "channel" &&
parameter.type != "mentionable" &&
parameter.type != "user" &&
parameter.type != "role"
) {
throw new Error(`Parameter type mismatch`); throw new Error(`Parameter type mismatch`);
} }
super(parameter, new ObjectID(value?.toString() || "")); super(parameter, new ObjectID(value?.toString() || ""));
@@ -132,32 +107,14 @@ export class ObjectID {
async toObject( async toObject(
guild: Guild, guild: Guild,
type: "channel" | "user" | "role" type: "channel" | "user" | "role"
): Promise< ): Promise<Role | TextChannel | VoiceChannel | CategoryChannel | GuildMember | NewsChannel | StoreChannel | StageChannel | null> {
| Role
| TextChannel
| VoiceChannel
| CategoryChannel
| GuildMember
| NewsChannel
| StoreChannel
| StageChannel
| null
> {
switch (type) { switch (type) {
case "channel": case "channel":
return ( return (await guild.channels.fetch(this.id.toString() || "")) || null;
(await guild.channels.fetch(this.id.toString() || "")) ||
null
);
case "role": case "role":
return ( return (await guild.roles.fetch(this.id.toString() || "")) || null;
(await guild.roles.fetch(this.id.toString() || "")) || null
);
case "user": case "user":
return ( return (await guild.members.fetch(this.id.toString() || "")) || null;
(await guild.members.fetch(this.id.toString() || "")) ||
null
);
} }
} }
} }
+13 -60
View File
@@ -1,11 +1,4 @@
import { import { ColorResolvable, CommandInteraction, GuildMember, Message, MessageEmbed, User } from "discord.js";
ColorResolvable,
CommandInteraction,
GuildMember,
Message,
MessageEmbed,
User,
} from "discord.js";
import { Command } from "./Command.js"; import { Command } from "./Command.js";
import { PermissionsError } from "./errors.js"; import { PermissionsError } from "./errors.js";
@@ -73,19 +66,14 @@ export class SystemMessageManager {
* @param {Message | CommandInteraction} [interaction] - if specified, the generated message will be sent in this channel * @param {Message | CommandInteraction} [interaction] - if specified, the generated message will be sent in this channel
* @returns *Promise<MessageEmbed | Message | void>* * @returns *Promise<MessageEmbed | Message | void>*
*/ */
async send( async send(type: MessageType, data?: SystemMessageData, interaction?: Message | CommandInteraction): Promise<MessageEmbed | Message | void> {
type: MessageType,
data?: SystemMessageData,
interaction?: Message | CommandInteraction
): Promise<MessageEmbed | Message | void> {
if (this[type]) { if (this[type]) {
if (this[type].enabled === false) { if (this[type].enabled === false) {
return; return;
} }
const embed = new MessageEmbed(); const embed = new MessageEmbed();
embed.setTitle(this[type].title); embed.setTitle(this[type].title);
if (this[type].bottomText) if (this[type].bottomText) embed.setDescription(this[type].bottomText || "");
embed.setDescription(this[type].bottomText || "");
embed.setColor(this[type].accentColor || "#000"); embed.setColor(this[type].accentColor || "#000");
if (this[type].showTimestamp) embed.setTimestamp(); if (this[type].showTimestamp) embed.setTimestamp();
if (this[type].footer) embed.setFooter(this[type].footer || ""); if (this[type].footer) embed.setFooter(this[type].footer || "");
@@ -93,33 +81,17 @@ export class SystemMessageManager {
switch (type) { switch (type) {
case "ERROR": case "ERROR":
if (data.command) { if (data.command) {
embed.addField( embed.addField("Command name:", data.command.name, false);
"Command name:",
data.command.name,
false
);
} }
if (data.error) { if (data.error) {
if (data.error instanceof Error) { if (data.error instanceof Error) {
embed.addField( embed.addField("Error details:", data.error.toString(), false);
"Error details:",
data.error.toString(),
false
);
} else if (typeof data.error == "string") { } else if (typeof data.error == "string") {
embed.addField( embed.addField("Error details:", data.error, false);
"Error details:",
data.error,
false
);
} }
} }
if (data.user) { if (data.user) {
embed.addField( embed.addField("User:", data.user.toString(), false);
"User:",
data.user.toString(),
false
);
} }
break; break;
case "NOT_FOUND": case "NOT_FOUND":
@@ -129,30 +101,16 @@ export class SystemMessageManager {
break; break;
case "PERMISSION": case "PERMISSION":
if (data.user) { if (data.user) {
embed.addField( embed.addField("User:", data.user.toString(), false);
"User:",
data.user.toString(),
false
);
} }
if (data.command) { if (data.command) {
embed.addField( embed.addField("Command name:", data.command.name, false);
"Command name:",
data.command.name,
false
);
if (data.command.permissions) { if (data.command.permissions) {
let permList: string = ""; let permList: string = "";
data.command.permissions data.command.permissions.toArray(false).map((p) => {
.toArray(false)
.map((p) => {
permList += p + "\n"; permList += p + "\n";
}); });
embed.addField( embed.addField("Required permissions:", permList, false);
"Required permissions:",
permList,
false
);
} }
} }
break; break;
@@ -168,13 +126,8 @@ export class SystemMessageManager {
}, this.deleteTimeout || 0); }, this.deleteTimeout || 0);
} }
return message; return message;
} else if ( } else if (interaction && interaction instanceof CommandInteraction) {
interaction && interaction.replied || interaction.deferred ? await interaction.editReply({ embeds: [embed] }) : await interaction.reply({ embeds: [embed] });
interaction instanceof CommandInteraction
) {
interaction.replied || interaction.deferred
? await interaction.editReply({ embeds: [embed] })
: await interaction.reply({ embeds: [embed] });
} else { } else {
return embed; return embed;
} }
+5 -30
View File
@@ -1,9 +1,4 @@
import { import { ClientOptions, ColorResolvable, CommandInteraction, ReplyMessageOptions } from "discord.js";
ClientOptions,
ColorResolvable,
CommandInteraction,
ReplyMessageOptions,
} from "discord.js";
import { InputParameter, ObjectID, ParameterSchema } from "./Parameter.js"; import { InputParameter, ObjectID, 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";
@@ -31,17 +26,9 @@ export interface CommandBuilder {
slash?: boolean; slash?: boolean;
announceSuccess?: boolean; announceSuccess?: boolean;
function: ( function: (
params: ( params: (query: string, returnType?: "value" | "object") => ParameterResolvable | InputParameter | null,
query: string,
returnType?: "value" | "object"
) => ParameterResolvable | InputParameter | null,
interaction?: Message | CommandInteraction interaction?: Message | CommandInteraction
) => ) => void | string | MessageEmbed | ReplyMessageOptions | Promise<void | string | MessageEmbed | ReplyMessageOptions>;
| void
| string
| MessageEmbed
| ReplyMessageOptions
| Promise<void | string | MessageEmbed | ReplyMessageOptions>;
} }
export interface PhraseOccurrenceData { export interface PhraseOccurrenceData {
command: Command; command: Command;
@@ -59,20 +46,8 @@ export interface HelpMessageParams {
description: string; description: string;
usage: string; usage: string;
} }
export type ParameterType = export type ParameterType = "string" | "boolean" | "number" | "user" | "role" | "channel" | "mentionable";
| "string" export type ParameterResolvable = string | boolean | number | ObjectID | undefined;
| "boolean"
| "number"
| "user"
| "role"
| "channel"
| "mentionable";
export type ParameterResolvable =
| string
| boolean
| number
| ObjectID
| undefined;
export interface Choice { export interface Choice {
name: string; name: string;
value: string; value: string;