@sapphire/framework
Version:
Discord bot framework built for advanced and amazing bots.
259 lines (257 loc) • 13 kB
JavaScript
"use strict";
const require_lib_types_Enums = require('../types/Enums.cjs');
const require_lib_utils_application_commands_getNeededParameters = require('../utils/application-commands/getNeededParameters.cjs');
const require_lib_utils_application_commands_registriesErrors = require('../utils/application-commands/registriesErrors.cjs');
const require_lib_utils_application_commands_ApplicationCommandRegistries = require('../utils/application-commands/ApplicationCommandRegistries.cjs');
const require_lib_parsers_Args = require('../parsers/Args.cjs');
const require_lib_precondition_resolvers_clientPermissions = require('../precondition-resolvers/clientPermissions.cjs');
const require_lib_utils_preconditions_PreconditionContainerArray = require('../utils/preconditions/PreconditionContainerArray.cjs');
const require_lib_precondition_resolvers_cooldown = require('../precondition-resolvers/cooldown.cjs');
const require_lib_precondition_resolvers_nsfw = require('../precondition-resolvers/nsfw.cjs');
const require_lib_precondition_resolvers_runIn = require('../precondition-resolvers/runIn.cjs');
const require_lib_precondition_resolvers_userPermissions = require('../precondition-resolvers/userPermissions.cjs');
require('../precondition-resolvers/index.cjs');
const require_lib_utils_strategies_FlagUnorderedStrategy = require('../utils/strategies/FlagUnorderedStrategy.cjs');
let __sapphire_pieces = require("@sapphire/pieces");
let __sapphire_utilities = require("@sapphire/utilities");
let discord_js = require("discord.js");
let __sapphire_lexure = require("@sapphire/lexure");
//#region src/lib/structures/Command.ts
const ChannelTypes = Object.values(discord_js.ChannelType).filter((type) => typeof type === "number");
const GuildChannelTypes = ChannelTypes.filter((type) => type !== discord_js.ChannelType.DM && type !== discord_js.ChannelType.GroupDM);
var Command = class extends __sapphire_pieces.AliasPiece {
/**
* @since 1.0.0
* @param context The context.
* @param options Optional Command settings.
*/
constructor(context, options = {}) {
const name = options.name ?? context.name;
super(context, {
...options,
name: name.toLowerCase()
});
this.applicationCommandRegistry = require_lib_utils_application_commands_ApplicationCommandRegistries.acquire(this.name);
this.rawName = name;
this.description = options.description ?? "";
this.detailedDescription = options.detailedDescription ?? "";
this.strategy = new require_lib_utils_strategies_FlagUnorderedStrategy.FlagUnorderedStrategy(options);
this.fullCategory = options.fullCategory ?? this.location.directories;
this.typing = options.typing ?? true;
this.lexer = new __sapphire_lexure.Lexer({ quotes: options.quotes ?? [
["\"", "\""],
["“", "”"],
["「", "」"],
["«", "»"]
] });
if (options.generateDashLessAliases) {
const dashLessAliases = [];
if (this.name.includes("-")) dashLessAliases.push(this.name.replace(/-/g, ""));
for (const alias of this.aliases) if (alias.includes("-")) dashLessAliases.push(alias.replace(/-/g, ""));
this.aliases = [...this.aliases, ...dashLessAliases];
}
if (options.generateUnderscoreLessAliases) {
const underscoreLessAliases = [];
if (this.name.includes("_")) underscoreLessAliases.push(this.name.replace(/_/g, ""));
for (const alias of this.aliases) if (alias.includes("_")) underscoreLessAliases.push(alias.replace(/_/g, ""));
this.aliases = [...this.aliases, ...underscoreLessAliases];
}
this.preconditions = new require_lib_utils_preconditions_PreconditionContainerArray.PreconditionContainerArray(options.preconditions);
this.parseConstructorPreConditions(options);
}
/**
* The message pre-parse method. This method can be overridden by plugins to define their own argument parser.
* @param message The message that triggered the command.
* @param parameters The raw parameters as a single string.
* @param context The command-context used in this execution.
*/
messagePreParse(message, parameters, context) {
const args = new __sapphire_lexure.ArgumentStream(new __sapphire_lexure.Parser(this.strategy).run(this.lexer.run(parameters)));
return new require_lib_parsers_Args.Args(message, this, args, context);
}
/**
* The main category for the command, if any.
*
* This getter retrieves the first value of {@link Command.fullCategory}, if it has at least one item, otherwise it
* returns `null`.
*
* @note You can set {@link Command.Options.fullCategory} to override the built-in category resolution.
*/
get category() {
return this.fullCategory.at(0) ?? null;
}
/**
* The sub-category for the command, if any.
*
* This getter retrieves the second value of {@link Command.fullCategory}, if it has at least two items, otherwise
* it returns `null`.
*
* @note You can set {@link Command.Options.fullCategory} to override the built-in category resolution.
*/
get subCategory() {
return this.fullCategory.at(1) ?? null;
}
/**
* The parent category for the command.
*
* This getter retrieves the last value of {@link Command.fullCategory}, if it has at least one item, otherwise it
* returns `null`.
*
* @note You can set {@link Command.Options.fullCategory} to override the built-in category resolution.
*/
get parentCategory() {
return this.fullCategory.at(-1) ?? null;
}
/**
* Defines the JSON.stringify behavior of the command.
*/
toJSON() {
return {
...super.toJSON(),
description: this.description,
detailedDescription: this.detailedDescription,
category: this.category
};
}
/**
* Type-guard that ensures the command supports message commands by checking if the handler for it is present
*/
supportsMessageCommands() {
return (0, __sapphire_utilities.isFunction)(Reflect.get(this, "messageRun"));
}
/**
* Type-guard that ensures the command supports chat input commands by checking if the handler for it is present
*/
supportsChatInputCommands() {
return (0, __sapphire_utilities.isFunction)(Reflect.get(this, "chatInputRun"));
}
/**
* Type-guard that ensures the command supports context menu commands by checking if the handler for it is present
*/
supportsContextMenuCommands() {
return (0, __sapphire_utilities.isFunction)(Reflect.get(this, "contextMenuRun"));
}
/**
* Type-guard that ensures the command supports handling autocomplete interactions by checking if the handler for it is present
*/
supportsAutocompleteInteractions() {
return (0, __sapphire_utilities.isFunction)(Reflect.get(this, "autocompleteRun"));
}
async reload() {
const { store } = this;
const registry = this.applicationCommandRegistry;
for (const nameOrId of registry.chatInputCommands) if (store.aliases.get(nameOrId) === this) store.aliases.delete(nameOrId);
for (const nameOrId of registry.contextMenuCommands) if (store.aliases.get(nameOrId) === this) store.aliases.delete(nameOrId);
registry.chatInputCommands.clear();
registry.contextMenuCommands.clear();
registry.guildIdsToFetch.clear();
registry["apiCalls"].length = 0;
await super.reload();
const updatedPiece = store.get(this.name);
if (!updatedPiece) return;
const updatedRegistry = updatedPiece.applicationCommandRegistry;
if (updatedPiece.registerApplicationCommands) try {
await updatedPiece.registerApplicationCommands(updatedRegistry);
} catch (err) {
require_lib_utils_application_commands_registriesErrors.emitPerRegistryError(err, updatedPiece);
return;
}
if (!updatedRegistry["apiCalls"].length) return;
if (require_lib_utils_application_commands_ApplicationCommandRegistries.getDefaultBehaviorWhenNotIdentical() === require_lib_types_Enums.RegisterBehavior.BulkOverwrite) {
await require_lib_utils_application_commands_ApplicationCommandRegistries.handleBulkOverwrite(store, this.container.client.application.commands);
return;
}
const { applicationCommands, globalCommands, guildCommands } = await require_lib_utils_application_commands_getNeededParameters.getNeededRegistryParameters(updatedRegistry.guildIdsToFetch);
await updatedRegistry["runAPICalls"](applicationCommands, globalCommands, guildCommands);
for (const nameOrId of updatedRegistry.chatInputCommands) store.aliases.set(nameOrId, updatedPiece);
for (const nameOrId of updatedRegistry.contextMenuCommands) store.aliases.set(nameOrId, updatedPiece);
}
/**
* Parses the command's options and processes them, calling {@link Command#parseConstructorPreConditionsRunIn},
* {@link Command#parseConstructorPreConditionsNsfw},
* {@link Command#parseConstructorPreConditionsRequiredClientPermissions}, and
* {@link Command#parseConstructorPreConditionsCooldown}.
* @since 2.0.0
* @param options The command options given from the constructor.
*/
parseConstructorPreConditions(options) {
this.parseConstructorPreConditionsRunIn(options);
this.parseConstructorPreConditionsNsfw(options);
this.parseConstructorPreConditionsRequiredClientPermissions(options);
this.parseConstructorPreConditionsRequiredUserPermissions(options);
this.parseConstructorPreConditionsCooldown(options);
}
/**
* Appends the `NSFW` precondition if {@link Command.Options.nsfw} is set to true.
* @param options The command options given from the constructor.
*/
parseConstructorPreConditionsNsfw(options) {
require_lib_precondition_resolvers_nsfw.parseConstructorPreConditionsNsfw(options.nsfw, this.preconditions);
}
/**
* Appends the `RunIn` precondition based on the values passed, defaulting to `null`, which doesn't add a
* precondition.
* @param options The command options given from the constructor.
*/
parseConstructorPreConditionsRunIn(options) {
require_lib_precondition_resolvers_runIn.parseConstructorPreConditionsRunIn(options.runIn, this.resolveConstructorPreConditionsRunType.bind(this), this.preconditions);
}
/**
* Appends the `ClientPermissions` precondition when {@link Command.Options.requiredClientPermissions} resolves to a
* non-zero bitfield.
* @param options The command options given from the constructor.
*/
parseConstructorPreConditionsRequiredClientPermissions(options) {
require_lib_precondition_resolvers_clientPermissions.parseConstructorPreConditionsRequiredClientPermissions(options.requiredClientPermissions, this.preconditions);
}
/**
* Appends the `UserPermissions` precondition when {@link Command.Options.requiredUserPermissions} resolves to a
* non-zero bitfield.
* @param options The command options given from the constructor.
*/
parseConstructorPreConditionsRequiredUserPermissions(options) {
require_lib_precondition_resolvers_userPermissions.parseConstructorPreConditionsRequiredUserPermissions(options.requiredUserPermissions, this.preconditions);
}
/**
* Appends the `Cooldown` precondition when {@link Command.Options.cooldownLimit} and
* {@link Command.Options.cooldownDelay} are both non-zero.
* @param options The command options given from the constructor.
*/
parseConstructorPreConditionsCooldown(options) {
require_lib_precondition_resolvers_cooldown.parseConstructorPreConditionsCooldown(this, options.cooldownLimit, options.cooldownDelay, options.cooldownScope, options.cooldownFilteredUsers, this.preconditions);
}
/**
* Resolves the {@link Command.Options.runIn} option into a {@link Command.RunInTypes} array.
* @param types The types to resolve.
* @returns The resolved types, or `null` if no types were resolved.
*/
resolveConstructorPreConditionsRunType(types) {
if ((0, __sapphire_utilities.isNullish)(types)) return null;
if (typeof types === "number") return [types];
if (typeof types === "string") switch (types) {
case "DM": return [discord_js.ChannelType.DM];
case "GUILD_TEXT": return [discord_js.ChannelType.GuildText];
case "GUILD_VOICE": return [discord_js.ChannelType.GuildVoice];
case "GUILD_NEWS": return [discord_js.ChannelType.GuildAnnouncement];
case "GUILD_NEWS_THREAD": return [discord_js.ChannelType.AnnouncementThread];
case "GUILD_PUBLIC_THREAD": return [discord_js.ChannelType.PublicThread];
case "GUILD_PRIVATE_THREAD": return [discord_js.ChannelType.PrivateThread];
case "GUILD_ANY": return GuildChannelTypes;
default: return null;
}
if (types.length === 0) throw new Error(`${this.constructor.name}[${this.name}]: "runIn" was specified as an empty array.`);
if (types.length === 1) return this.resolveConstructorPreConditionsRunType(types[0]);
const resolved = /* @__PURE__ */ new Set();
for (const typeResolvable of types) for (const type of this.resolveConstructorPreConditionsRunType(typeResolvable) ?? []) resolved.add(type);
if (resolved.size === ChannelTypes.length) return null;
return [...resolved].sort((a, b) => a - b);
}
static runInTypeIsSpecificsObject(types) {
if (!(0, __sapphire_utilities.isObject)(types)) return false;
const specificTypes = types;
return Boolean(specificTypes.chatInputRun || specificTypes.messageRun || specificTypes.contextMenuRun);
}
};
//#endregion
exports.Command = Command;
//# sourceMappingURL=Command.cjs.map