UNPKG

djs-message-commands

Version:

Build easy, safe, and testable message commands for discord.js

264 lines (263 loc) 9.38 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.MessageCommandBuilder = void 0; const builders_1 = require("@discordjs/builders"); const _1 = require("./"); class MessageCommandBuilder { /** * The name of the command. */ name; /** * The description of the command. */ description; /** * Any aliases the command may be executed with. */ aliases; /** * The options/arguments that can be supplied to this command. */ options; /** * The role IDs permitted to execute this command. */ roleIds; /** * The permissions permitted to execute this command. */ permissions; constructor(data) { this.name = data?.name ?? "No name implemented"; this.description = data?.description ?? "No description implemented"; this.aliases = data?.aliases ?? []; this.options = data?.options ?? []; this.roleIds = data?.roleIds ?? []; this.permissions = data?.permissions ?? []; } /** * Sets the name of the command. Cannot be empty. * @param name The name of the command. * @returns The builder instance. */ setName(name) { if (name === "") { throw new Error("Command name must be at least one character long."); } this.name = name; return this; } /** * Sets the description of the command. Cannot be empty. * @param description The description of the command. * @returns The builder instance. */ setDescription(description) { if (description === "") { throw new Error("Command description must be at least one character long."); } this.description = description; return this; } /** * Sets any aliases you wish to supply for the command. * @param aliases The aliases of the command. * @returns The builder instance. */ setAliases(aliases) { if (aliases.length <= 0) { throw new Error("There must be at least one alias provided in the array."); } if (aliases.some(a => a === "")) { throw new Error("Aliases must be at least one character long."); } this.aliases = aliases; return this; } /** * Sets the roles allowed to execute this command. If a role doesn't exist in the guild, it will be ignored. * @param ids The role IDs permitted to execute this command. * @returns The builder instance. */ setRoles(ids) { if (ids.length <= 0) { throw new Error("There must be at least one role ID provided in the array."); } this.roleIds = ids; return this; } /** * Sets the permissions allowed to execute this command. * @param permissions The permissions required to execute this command. * @returns The builder instance. */ setPermissions(permissions) { if (permissions.length <= 0) { throw new Error("There must be at least one permission provided in the array."); } this.permissions = permissions; return this; } /** * Adds a choice-able string option to the command. * @param composer A function that returns an instance of the option. * @returns The builder instance. */ addStringOption(composer) { const option = composer(new _1.MessageCommandStringOption()); this.options.push(option); return this; } /** * Adds a choice-able number option to the command. * @param composer A function that returns an instance of the option. * @returns The builder instance. */ addNumberOption(composer) { const option = composer(new _1.MessageCommandNumberOption()); this.options.push(option); return this; } /** * Adds a boolean option to the command. * @param composer A function that returns an instance of the option. * @returns The builder instance. */ addBooleanOption(composer) { const option = composer(new _1.MessageCommandBooleanOption()); this.options.push(option); return this; } /** * Adds a member mentionable option to the command. * @param composer A function that returns an instance of the option. * @returns The builder instance. */ addMemberOption(composer) { const option = composer(new _1.MessageCommandMemberOption()); this.options.push(option); return this; } /** * Adds a channel mentionable option to the command. * @param composer A function that returns an instance of the option. * @returns The builder instance. */ addChannelOption(composer) { const option = composer(new _1.MessageCommandChannelOption()); this.options.push(option); return this; } /** * Adds a role mentionable option to the command. * @param composer A function that returns an instance of the option. * @returns The builder instance. */ addRoleOption(composer) { const option = composer(new _1.MessageCommandRoleOption()); this.options.push(option); return this; } /** * A utility method to convert the command into a regular expression. Useful for debugging. * @param prefix The guild's message prefix. * @returns The command's builder converted to RegExp. */ toRegex(prefix) { const aliases = this.aliases.length > 0 ? `|${this.aliases.join("|")}` : ""; let regex = `${prefix}(${this.name}${aliases})`; for (const option of this.options) { regex += `\\s+`; if (option instanceof _1.MessageCommandOptionChoiceable) { if (option.choices.length <= 0) { switch (option.type) { case "text" /* STRING */: regex += `\"(.+)\"`; break; case "number" /* NUMBER */: regex += `(\\d+)`; break; } } else { regex += `\"(${option.choices.map(c => c[1]).join("|")})\"`; } continue; } switch (option.type) { case "true/false" /* BOOLEAN */: regex += `(true|false)`; break; case "member" /* MEMBER */: regex += `<@!?(\\d{17,19})>`; break; case "channel" /* CHANNEL */: regex += `<#(\\d{17,19})>`; break; case "role" /* ROLE */: regex += `<@&(\\d{17,19})>`; } } return new RegExp(`^${regex}$`, "gm"); } /** * Validates the message with the command. This checks for permissions, roles, and arguments supplied to the command. * @param message The message to validate. * @returns The parsed options and potential errors. */ validate(message) { let errors; const parsedOptions = []; const args = message.content.trim().split(/\s+/).slice(1); for (const perm of this.permissions) { if (!message.member.permissions.has(perm)) { if (!errors) errors = []; errors.push({ message: `Missing permission: ${perm}`, type: "MISSING_PERMISSIONS", }); } } for (const id of this.roleIds) { if (!message.guild.roles.cache.has(id)) { continue; } if (!message.member.roles.cache.has(id)) { if (!errors) errors = []; errors.push({ message: `Missing role: ${(0, builders_1.roleMention)(id)}`, type: "MISSING_ROLES", }); } } if (args.length === this.options.length) { for (let i = 0; i < this.options.length; i++) { const option = this.options[i]; const result = option.validate(args[i]); if (result === undefined) { if (!errors) errors = []; errors.push({ message: `Invalid option type: ${option.name} in ${this.name}`, type: "INVALID_ARG_TYPE", }); continue; } parsedOptions.push(result); } } else { if (!errors) errors = []; errors.push({ message: `Missing arguments -> Expected: ${this.options.length}, Got: ${args.length}`, type: "MISSING_ARGS", }); } return [errors, parsedOptions]; } } exports.MessageCommandBuilder = MessageCommandBuilder;