commandbot
Version:
A framework that helps you create your own Discord bot easier.
301 lines (300 loc) • 13.9 kB
JavaScript
;
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.ChatCommand = void 0;
const discord_js_1 = require("discord.js");
const Parameter_js_1 = require("../structures/Parameter.js");
const commandsTypes_js_1 = require("./commandsTypes.js");
const PermissionGuildCommand_js_1 = require("./base/PermissionGuildCommand.js");
const generateUsageFromArguments_js_1 = require("../utils/generateUsageFromArguments.js");
const SubCommand_js_1 = require("./SubCommand.js");
const SubCommandGroup_js_1 = require("./SubCommandGroup.js");
const state_js_1 = require("../state.js");
const InputManager_js_1 = require("../structures/InputManager.js");
/**
* A representation of CHAT_INPUT command (also known as a slash command)
* @class
* @extends {PermissionGuildCommand}
*/
class ChatCommand extends PermissionGuildCommand_js_1.PermissionGuildCommand {
/**
* ChatCommand constructor
* @constructor
* @param {CommandManager} manager - a manager that this command belongs to
* @param {ChatCommandInit} options - {@link ChatCommandInit} object containing all options needed to create a {@link ChatCommand}
*/
constructor(manager, options) {
var _a, _b;
super(manager, "CHAT", {
name: options.name,
function: options.function,
announceSuccess: options.announceSuccess,
guilds: options.guilds,
permissions: options.permissions,
dm: options.dm,
ephemeral: options.ephemeral,
});
/**
* Subcommands and groups of this command
* @type {Array<ChildCommandResolvable>}
* @private
* @readonly
*/
this._children = [];
if (options.parameters == "no_input" || !options.parameters) {
this.parameters = [];
}
else if (options.parameters == "simple") {
this.parameters = [new Parameter_js_1.DefaultParameter(this)];
}
else {
this.parameters = options.parameters.map((ps) => new Parameter_js_1.Parameter(this, ps));
}
this.aliases = options.aliases ? (Array.isArray(options.aliases) ? options.aliases : [options.aliases]) : undefined;
this.description = (_a = options.description) !== null && _a !== void 0 ? _a : "No description";
this.usage = (_b = options.usage) !== null && _b !== void 0 ? _b : (0, generateUsageFromArguments_js_1.generateUsageFromArguments)(this);
this.visible = options.visible !== undefined ? options.visible : true;
this.slash = options.slash !== undefined ? options.slash : true;
if (!commandsTypes_js_1.CommandRegExps.chatName.test(this.name)) {
throw new Error(`"${this.name}" is not a valid command name (regexp: ${commandsTypes_js_1.CommandRegExps.chatName})`);
}
if (this.description && !commandsTypes_js_1.CommandRegExps.chatDescription.test(this.description)) {
throw new Error(`The description of "${this.name}" doesn't match the regular expression ${commandsTypes_js_1.CommandRegExps.chatDescription}`);
}
if (this.aliases) {
if (Array.isArray(this.aliases)) {
this.aliases.map((a) => {
if (!commandsTypes_js_1.CommandRegExps.chatName.test(a)) {
throw new Error(`"${a}" is not a valid alias name (regexp: ${commandsTypes_js_1.CommandRegExps.chatName})`);
}
});
}
else {
if (!commandsTypes_js_1.CommandRegExps.chatName.test(this.aliases)) {
throw new Error(`"${this.aliases}" is not a valid alias name (regexp: ${commandsTypes_js_1.CommandRegExps.chatName})`);
}
}
}
if (this.aliases && this.aliases.length > 0 && this.aliases.find((a) => this.manager.get(a, this.type))) {
throw new Error(`One of aliases from "${this.name}" command is already a registered name in the manager and cannot be reused.`);
}
}
/**
* Returns *true* if the command has subcommands attached
* @type {boolean}
*/
get hasSubCommands() {
return this._children.length > 0;
}
/**
* Returns list of attached subcommands
* @type {Array<ChildCommandResolvable>}
* @readonly
*/
get children() {
return Object.freeze([...this._children]);
}
/**
* Invoke the command
* @param {InputManager} input - input data manager
* @returns {Promise<void>}
* @public
* @async
*/
start(input) {
const _super = Object.create(null, {
start: { get: () => super.start }
});
return __awaiter(this, void 0, void 0, function* () {
if (!this.slash && input.interaction instanceof discord_js_1.Interaction) {
throw new Error("This command is not available as a slash command");
}
yield _super.start.call(this, input);
});
}
/**
* Attaches subcommand or subcommand group to this ChatCommand
* @param {T} type - subcommand type
* @param {ChildCommandInit<T>} options - initialization options
* @returns {ChildCommands<T>} A computed subcommand object
* @public
* @remarks After appending a subcommand or a subcommand group the main command can only be invoked using prefix interactions
*/
append(type, options) {
const command = type === "COMMAND"
? new SubCommand_js_1.SubCommand(this, options)
: type === "GROUP"
? new SubCommandGroup_js_1.SubCommandGroup(this, options)
: null;
if (!command) {
throw new Error("Incorrect command type");
}
if (state_js_1.applicationState.running) {
console.warn(`[❌ ERROR] Cannot add command "${command.name}" while the application is running.`);
return command;
}
this._children.push(command);
return command;
}
/**
*
* @param {Array<CommandInteractionOption>} options - parameter options
* @param {Interaction | Message} interaction - Discord interaction
* @returns {?InputManager} an {@link InputManager} containing all interaction-related data or *null*
* @public
*/
fetchSubcommand(options, interaction) {
if (!this.hasSubCommands)
return null;
if (options[0]) {
if (options[0].type === "SUB_COMMAND_GROUP") {
const grName = options[0].name;
const group = this._children.filter((c) => c instanceof SubCommandGroup_js_1.SubCommandGroup).find((c) => c.name === grName);
const scOpt = options[0].options;
if (group && scOpt) {
const scName = scOpt[0].name;
const cmd = group.children.filter((c) => c instanceof SubCommand_js_1.SubCommand).find((c) => c.name === scName);
if (cmd && scOpt[0].options) {
return new InputManager_js_1.InputManager(cmd, interaction, cmd.parameters.map((p, index) => {
var _a, _b, _c, _d, _e, _f;
if (p.type === "user" || p.type === "role" || p.type === "channel" || p.type === "mentionable") {
return new Parameter_js_1.InputParameter(p, new Parameter_js_1.ObjectID((_c = (_b = (_a = scOpt[0].options) === null || _a === void 0 ? void 0 : _a[index].value) === null || _b === void 0 ? void 0 : _b.toString()) !== null && _c !== void 0 ? _c : "", p.type, (_d = interaction.guild) !== null && _d !== void 0 ? _d : undefined));
}
else {
return new Parameter_js_1.InputParameter(p, (_f = (_e = scOpt[0].options) === null || _e === void 0 ? void 0 : _e[index].value) !== null && _f !== void 0 ? _f : null);
}
}));
}
else {
return null;
}
}
else {
return null;
}
}
else if (options[0].type === "SUB_COMMAND") {
const cmd = this._children.filter((c) => c instanceof SubCommand_js_1.SubCommand).find((c) => c.name === options[0].name);
if (cmd) {
return new InputManager_js_1.InputManager(cmd, interaction, cmd.parameters.map((p, index) => {
var _a, _b, _c, _d, _e, _f;
if (p.type === "user" || p.type === "role" || p.type === "channel" || p.type === "mentionable") {
return new Parameter_js_1.InputParameter(p, new Parameter_js_1.ObjectID((_c = (_b = (_a = options[0].options) === null || _a === void 0 ? void 0 : _a[index].value) === null || _b === void 0 ? void 0 : _b.toString()) !== null && _c !== void 0 ? _c : "", p.type, (_d = interaction.guild) !== null && _d !== void 0 ? _d : undefined));
}
else {
return new Parameter_js_1.InputParameter(p, (_f = (_e = options[0].options) === null || _e === void 0 ? void 0 : _e[index].value) !== null && _f !== void 0 ? _f : null);
}
}));
}
else {
return null;
}
}
else {
return null;
}
}
else {
return null;
}
}
/**
*
* @param {string} name - subcommand name
* @param {?string} [group] - name of the group (if any)
* @returns {?SubCommand} a {@link SubCommand} object or *null*
*/
getSubcommand(name, group) {
if (!this.hasSubCommands)
return null;
if (group) {
const gr = this._children.filter((c) => c instanceof SubCommandGroup_js_1.SubCommandGroup).find((g) => g.name === group);
if (gr) {
return gr.children.find((c) => c.name === name) || null;
}
else {
return null;
}
}
else {
return this._children.filter((c) => c instanceof SubCommand_js_1.SubCommand).find((c) => c.name === name) || null;
}
}
/**
* Converts {@link ChatCommand} instance to object that is recognized by the Discord API
* @returns {ChatCommandObject} Discord API object
* @public
*/
toObject() {
const obj = Object.assign(Object.assign({}, super.toObject()), { type: 1, description: this.description });
let options = [];
if (this.parameters) {
options = this.parameters
.map((p) => {
let type = 3;
switch (p.type) {
case "boolean":
type = 5;
break;
case "user":
type = 6;
break;
case "channel":
type = 7;
break;
case "role":
type = 8;
break;
case "mentionable":
type = 9;
break;
case "number":
type = 10;
break;
case "target":
throw new Error(`"target" parameter cannot be used in chat commands`);
default:
type = 3;
break;
}
const choices = [];
if (p.choices) {
p.choices.map((c) => {
choices.push({ name: c, value: c });
});
}
const optionObj = {
name: p.name,
description: p.description,
required: !p.optional,
type: p.choices ? 3 : type,
choices: choices.length > 0 ? choices : undefined,
};
return optionObj;
})
.sort((a, b) => {
if (a.required && !b.required) {
return -1;
}
else if (a.required && b.required) {
return 0;
}
else if (!a.required && b.required) {
return 1;
}
return 0;
});
obj.options = this.hasSubCommands ? this._children.map((sc) => sc.toObject()) : options;
}
return obj;
}
}
exports.ChatCommand = ChatCommand;