@wilcosp/rex
Version:
Rex is an automated command manager for discord js
327 lines (326 loc) • 12.8 kB
JavaScript
/*!
* 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;
}