UNPKG

@wilcosp/rex

Version:

Rex is an automated command manager for discord js

327 lines (326 loc) 12.8 kB
/*! * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ import { ApplicationCommandOptionType, ApplicationCommandType, } from "discord-api-types/v10"; import { LocalsEqual } from "../helpers/locale.js"; import { RexAutoCompleteInteraction } from "../interactions/slashCommands/autocomplete.js"; import { RexSlashCommandInteraction } from "../interactions/slashCommands/slashCommand.js"; import { RexSlashCommandBase } from "./commandBase.js"; export class RexSlashCommand extends RexSlashCommandBase { get commandInfo() { const ref = this._commandInfo?.deref(); if (ref) { return ref; } let mention = []; if (this.groupParent) { mention.push(this.groupParent); } if (this.subParent) { mention.push(this.subParent); } mention.push(this.name); const info = { id: this._commandId, name: this.name, options: this._options, type: ApplicationCommandType.ChatInput, mention: `</${mention.join(" ")}:${this._commandId}>`, description: this._description, nsfw: this.nsfw, descriptionLocalizations: this._descriptionLocals ? new Map(this._descriptionLocals) : undefined, nameLocalizations: this._nameLocals ? new Map(this._nameLocals) : undefined, }; this._commandInfo = new WeakRef(info); return info; } addOption(option) { this._options ?? (this._options = []); this._options.push(getOption(option)); return this; } addOptions(...options) { this._options ?? (this._options = []); options.flat().forEach(option => { this._options.push(getOption(option)); }); return this; } setOptions(...options) { this._options = options.flat().map(o => getOption(o)); return this; } setCommandId(id, { group, sub } = {}) { this._commandInfo = undefined; this.groupParent = group; this.subParent = sub; return super.setCommandId(id); } setExecute(fun) { return super.setExecute(fun); } setAutoCompleteFun(fun) { this._autocomplete = fun; return this; } run(aCom, commands) { if (this._execute) { return this._execute.apply(this.commandInfo, [ new RexSlashCommandInteraction(aCom, { deferEphemeral: this.deferEphemeral, autoDefer: this.autoDefer, debounceDelay: this.debounceDelay, useFailOver: this.useFailover }), ]); } return aCom.reply("no execution function was configured"); } runAutoComplete(auto, commands) { if (this._autocomplete) { return this._autocomplete.apply(null, [new RexAutoCompleteInteraction(auto)]); } } toCommand() { if (!this._execute) { throw Error(`the execute function of ${this.name} is not present`); } return { ...super.toCommand(), options: this._options, }; } toSlashSubCommand() { if (!this._execute) { throw Error(`the execute function of ${this.name} is not present`); } return { name: this.name, description: this._description, type: ApplicationCommandOptionType.Subcommand, options: this._options, name_localizations: this._nameLocals ? Object.fromEntries(this._nameLocals) : undefined, description_localizations: this._descriptionLocals ? Object.fromEntries(this._descriptionLocals) : undefined, }; } equalToCommand(aCom) { if (!super.equalToCommand(aCom)) return false; if (aCom.options && aCom.options.length > 0) { if (!this._options || this._options.length < 1) return false; if (!equalOptions(aCom.options, this._options)) return false; } if (this._options && this._options.length > 0 && (!aCom.options || aCom.options.length < 1)) return false; return true; } equalToSubSlashCommand(opt) { if (opt.description != this._description || opt.name != this.name) return false; if (this._options) { if (!opt.options) return false; if (!equalOptions(opt.options, this._options)) return false; } if (opt.options && !this._options) { return false; } const nameLocals = opt.nameLocalizations ?? opt.name_localizations; if (nameLocals) { if (!this._nameLocals) { return false; } if (!LocalsEqual(nameLocals, Object.fromEntries(this._nameLocals))) { return false; } } if (!nameLocals && this._nameLocals) { return false; } const descLocals = opt.descriptionLocalizations ?? opt.description_localizations; if (descLocals) { if (!this._descriptionLocals) { return false; } if (!LocalsEqual(descLocals, Object.fromEntries(this._descriptionLocals))) { return false; } } if (!descLocals && this._descriptionLocals) { return false; } return true; } } function equalOptions(existing, options) { if ((options?.length ?? 0) != existing.length ?? 0) return false; if ((options?.length ?? 0) < 1 && (existing.length ?? 0) < 1) return true; if (options) { for (let i = 0; i < options.length; i++) { const curOption = options[i]; const existinOption = existing[i]; switch (existinOption.type) { case ApplicationCommandOptionType.String: if (curOption.type != ApplicationCommandOptionType.String) return false; break; case ApplicationCommandOptionType.Integer: if (curOption.type != ApplicationCommandOptionType.Integer) return false; break; case ApplicationCommandOptionType.Boolean: if (curOption.type != ApplicationCommandOptionType.Boolean) return false; break; case ApplicationCommandOptionType.User: if (curOption.type != ApplicationCommandOptionType.User) return false; break; case ApplicationCommandOptionType.Channel: if (curOption.type != ApplicationCommandOptionType.Channel) return false; break; case ApplicationCommandOptionType.Role: if (curOption.type != ApplicationCommandOptionType.Role) return false; break; case ApplicationCommandOptionType.Mentionable: if (curOption.type != ApplicationCommandOptionType.Mentionable) return false; break; case ApplicationCommandOptionType.Number: if (curOption.type != ApplicationCommandOptionType.Number) return false; break; case ApplicationCommandOptionType.Attachment: if (curOption.type != ApplicationCommandOptionType.Attachment) return false; break; default: throw TypeError(`type of ${existinOption.type} isn't supported`); } if (curOption.name != existinOption.name) return false; if (curOption.description != existinOption.description) return false; if ((curOption.required ?? false) != (existinOption.required ?? false)) return false; if ((curOption.autocomplete ?? false) !== (existinOption.autocomplete ?? false)) return false; if (curOption.min_value != (existinOption.minValue ?? existinOption.min_value)) return false; if (curOption.max_value != (existinOption.maxValue ?? existinOption.max_value)) return false; if (!curOption.autocomplete && !existinOption.autocomplete) { if (curOption.choices) { if (!existinOption.choices) { return false; } if (!compareChoices(existinOption.choices, curOption.choices)) { return false; } } else { if (existinOption.choices) { return false; } } } const namelocals = existinOption.name_localizations ?? existinOption.nameLocalizations; if (!namelocals && curOption.name_localizations) { return false; } if (namelocals) { if (!curOption.name_localizations) { return false; } if (!LocalsEqual(namelocals, curOption.name_localizations)) { return false; } } const descriptionLocals = existinOption.descriptionLocalizations ?? existinOption.description_localizations; if (!descriptionLocals && curOption.description_localizations) { return false; } if (descriptionLocals) { if (!curOption.description_localizations) return false; if (!LocalsEqual(descriptionLocals, curOption.description_localizations)) { return false; } } if (curOption.min_value != (existinOption.minValue ?? existinOption.min_value)) { return false; } if (curOption.max_value != (existinOption.maxValue ?? existinOption.max_value)) { return false; } if ((curOption.min_length ?? 0) != (existinOption.minLength ?? existinOption.min_length ?? 0)) { return false; } if ((curOption.max_length ?? Number.MAX_SAFE_INTEGER) != (existinOption.maxLength ?? existinOption.max_length ?? Number.MAX_SAFE_INTEGER)) { return false; } const existingChannelTypes = existinOption.channelTypes ?? existinOption.channel_types; const curChannelTypes = curOption.channel_types; if (curChannelTypes && curChannelTypes.length > 0) { if (!existingChannelTypes || existingChannelTypes.length < 1) { return false; } for (const channelType of existingChannelTypes) { if (!curChannelTypes.includes(channelType)) { return false; } } } if (existingChannelTypes && existingChannelTypes.length > 0) { if (!curChannelTypes || curChannelTypes.length < 1) return false; } } } return true; } function compareChoices(aComChoices, choices) { if (aComChoices.length != choices.length) { return false; } for (const [key, value] of choices.entries()) { const cur = aComChoices[key]; if (!cur) { return false; } if (cur.name != value.name && cur.value != value.value) { return false; } const nameLocals = cur.nameLocalizations ?? cur.name_localizations; if (value.name_localizations && !nameLocals) return false; if (nameLocals) { if (!value.name_localizations) return false; if (!LocalsEqual(nameLocals, value.name_localizations)) return false; } } return true; } function getOption(option) { const json = option.toJSON(); if (isOption(json)) { return json; } if (isOption(option)) { return option; } throw TypeError(`${option} isn't a valid option`); } function isOption(option) { if (Object.values(ApplicationCommandOptionType).includes(option?.type ?? -1) && option?.name && option?.description) { return true; } return false; }