UNPKG

@sapphire/framework

Version:

Discord bot framework built for advanced and amazing bots.

1,148 lines (1,133 loc) 170 kB
import { ChannelTypes, GuildBasedChannelTypes, TextBasedChannelTypes, AnyInteraction } from '@sapphire/discord.js-utilities'; import { ArgumentStream, IUnorderedStrategy, Lexer } from '@sapphire/lexure'; import * as _sapphire_result from '@sapphire/result'; import { Result, Option } from '@sapphire/result'; export * from '@sapphire/result'; import { Awaitable, Nullish } from '@sapphire/utilities'; export { Awaitable } from '@sapphire/utilities'; import * as discord_js from 'discord.js'; import { Message, DMChannel, CategoryChannel, NewsChannel, ThreadChannel, ChannelType, TextChannel, StageChannel, VoiceChannel, GuildMember, Role, User, ChatInputCommandInteraction, ContextMenuCommandInteraction, Collection, Snowflake, PermissionResolvable, ChatInputApplicationCommandData, UserApplicationCommandData, MessageApplicationCommandData, ApplicationCommandManager, ApplicationCommand, CommandInteraction, TextBasedChannel, PermissionsBitField, AutocompleteInteraction, PermissionsString, Interaction, ClientEvents, Client, Events as Events$1, ClientOptions, Guild, PartialDMChannel } from 'discord.js'; import { URL } from 'node:url'; import { AliasPiece, Piece, AliasPieceJSON, AliasStore, Store, StoreRegistry, LoaderStrategy } from '@sapphire/pieces'; export { AliasPiece, AliasPieceJSON, AliasPieceOptions, AliasStore, Container, LoaderError, LoaderPieceContext, MissingExportsError, Piece, PieceContext, PieceJSON, PieceLocationJSON, PieceOf, PieceOptions, Store, StoreManagerManuallyRegisteredPiece, StoreManuallyRegisteredPiece, StoreOf, StoreOptions, StoreRegistry, StoreRegistryEntries, StoreRegistryKey, StoreRegistryValue, container } from '@sapphire/pieces'; import { SlashCommandBuilder, SlashCommandSubcommandsOnlyBuilder, SlashCommandOptionsOnlyBuilder, ContextMenuCommandBuilder } from '@discordjs/builders'; import { RateLimitManager } from '@sapphire/ratelimits'; import { EventEmitter } from 'node:events'; /** * The UserError class to be emitted in the pieces. * @property name This will be `'UserError'` and can be used to distinguish the type of error when any error gets thrown * @example * ```typescript * throw new UserError({ * identifier: 'AddArgumentError', * message: 'You must write two numbers, but the second one did not match.', * context: { received: 2, expected: 3 } * }); * ``` */ declare class UserError extends Error { /** * An identifier, useful to localize emitted errors. */ readonly identifier: string; /** * User-provided context. */ readonly context: unknown; /** * Constructs an UserError. * @param options The UserError options */ constructor(options: UserError.Options); get name(): string; } declare namespace UserError { /** * The options for {@link UserError}. * @since 1.0.0 */ interface Options { /** * The identifier for this error. * @since 1.0.0 */ identifier: string; /** * The message to be passed to the Error constructor. * @since 1.0.0 */ message?: string; /** * The extra context to provide more information about this error. * @since 1.0.0 * @default null */ context?: unknown; } } declare enum Identifiers { ArgsMissing = "argsMissing", ArgsUnavailable = "argsUnavailable", ArgumentBooleanError = "booleanError", ArgumentChannelError = "channelError", ArgumentDateError = "dateError", ArgumentDateTooEarly = "dateTooEarly", ArgumentDateTooFar = "dateTooFar", ArgumentDMChannelError = "dmChannelError", ArgumentEmojiError = "emojiError", ArgumentFloatError = "floatError", ArgumentFloatTooLarge = "floatTooLarge", ArgumentFloatTooSmall = "floatTooSmall", ArgumentGuildError = "guildError", ArgumentGuildCategoryChannelError = "categoryChannelError", ArgumentGuildChannelError = "guildChannelError", ArgumentGuildChannelMissingGuildError = "guildChannelMissingGuildError", ArgumentGuildNewsChannelError = "guildNewsChannelError", ArgumentGuildNewsThreadChannelError = "guildNewsThreadChannelError", ArgumentGuildPrivateThreadChannelError = "guildPrivateThreadChannelError", ArgumentGuildPublicThreadChannelError = "guildPublicThreadChannelError", ArgumentGuildStageVoiceChannelError = "guildStageVoiceChannelError", ArgumentGuildTextChannelError = "guildTextChannelError", ArgumentGuildThreadChannelError = "guildThreadChannelError", ArgumentGuildVoiceChannelError = "guildVoiceChannelError", ArgumentHyperlinkError = "hyperlinkError", ArgumentIntegerError = "integerError", ArgumentIntegerTooLarge = "integerTooLarge", ArgumentIntegerTooSmall = "integerTooSmall", ArgumentMemberError = "memberError", ArgumentMemberMissingGuild = "memberMissingGuild", ArgumentMessageError = "messageError", ArgumentNumberError = "numberError", ArgumentNumberTooLarge = "numberTooLarge", ArgumentNumberTooSmall = "numberTooSmall", ArgumentRoleError = "roleError", ArgumentRoleMissingGuild = "roleMissingGuild", ArgumentStringTooLong = "stringTooLong", ArgumentStringTooShort = "stringTooShort", ArgumentUserError = "userError", ArgumentEnumEmptyError = "enumEmptyError", ArgumentEnumError = "enumError", CommandDisabled = "commandDisabled", PreconditionCooldown = "preconditionCooldown", /** @deprecated Use {@link PreconditionRunIn} instead. */ PreconditionDMOnly = "preconditionDmOnly", /** @deprecated Use {@link PreconditionRunIn} instead. */ PreconditionGuildNewsOnly = "preconditionGuildNewsOnly", /** @deprecated Use {@link PreconditionRunIn} instead. */ PreconditionGuildNewsThreadOnly = "preconditionGuildNewsThreadOnly", /** @deprecated Use {@link PreconditionRunIn} instead. */ PreconditionGuildOnly = "preconditionGuildOnly", /** @deprecated Use {@link PreconditionRunIn} instead. */ PreconditionGuildPrivateThreadOnly = "preconditionGuildPrivateThreadOnly", /** @deprecated Use {@link PreconditionRunIn} instead. */ PreconditionGuildPublicThreadOnly = "preconditionGuildPublicThreadOnly", /** @deprecated Use {@link PreconditionRunIn} instead. */ PreconditionGuildTextOnly = "preconditionGuildTextOnly", /** @deprecated Use {@link PreconditionRunIn} instead. */ PreconditionGuildVoiceOnly = "preconditionGuildVoiceOnly", PreconditionNSFW = "preconditionNsfw", PreconditionClientPermissions = "preconditionClientPermissions", PreconditionClientPermissionsNoClient = "preconditionClientPermissionsNoClient", PreconditionClientPermissionsNoPermissions = "preconditionClientPermissionsNoPermissions", PreconditionRunIn = "preconditionRunIn", PreconditionUserPermissions = "preconditionUserPermissions", PreconditionUserPermissionsNoPermissions = "preconditionUserPermissionsNoPermissions", /** @deprecated Use {@link PreconditionRunIn} instead. */ PreconditionThreadOnly = "preconditionThreadOnly", PreconditionUnavailable = "preconditionUnavailable", PreconditionMissingMessageHandler = "preconditionMissingMessageHandler", PreconditionMissingChatInputHandler = "preconditionMissingChatInputHandler", PreconditionMissingContextMenuHandler = "preconditionMissingContextMenuHandler" } declare function resolveEmoji(parameter: string): Result<EmojiObject, Identifiers>; interface EmojiObject { name: string | null; id: string | null; animated?: boolean; } declare enum CooldownLevel { Author = "author", Channel = "channel", Guild = "guild" } declare enum PluginHook { PreGenericsInitialization = "preGenericsInitialization", PreInitialization = "preInitialization", PostInitialization = "postInitialization", PreLogin = "preLogin", PostLogin = "postLogin" } /** * The scope the cooldown applies to. */ declare enum BucketScope { /** * Per channel cooldowns. */ Channel = 0, /** * Global cooldowns. */ Global = 1, /** * Per guild cooldowns. */ Guild = 2, /** * Per user cooldowns. */ User = 3 } declare enum RegisterBehavior { Overwrite = "OVERWRITE", LogToConsole = "LOG_TO_CONSOLE", /** * Finds all differences in the commands provided using our internal computation method, and logs them to the console, while applying them. * * @danger This can potentially cause slowdowns when booting up your bot as computing differences on big commands can take a while. * We recommend you use `OVERWRITE` instead in production. */ VerboseOverwrite = "VERBOSE_OVERWRITE", /** * Makes Sapphire handle all command registrations, removals, and updates for you. * * This mode can only be set as the **default** behavior, and cannot be set per-command. * * In this mode: * - any `idHints` set per-command are no longer respected, and can be omitted. * - any `behaviorWhenNotIdentical` that are set per-command are no longer respected, and can be omitted. * - any application commands that are *not* registered through Sapphire's {@link ApplicationCommandRegistry} are removed from the application. * - the same applies for guild commands, but only for guilds that are registered in the registry via `guildIds`. */ BulkOverwrite = "BULK_OVERWRITE" } declare enum InternalRegistryAPIType { ChatInput = 0, ContextMenu = 1 } /** * The allowed values for {@link CommandOptions.runIn} as an enum. * @since 2.0.0 */ declare enum CommandOptionsRunTypeEnum { Dm = "DM", GuildText = "GUILD_TEXT", GuildVoice = "GUILD_VOICE", GuildNews = "GUILD_NEWS", GuildNewsThread = "GUILD_NEWS_THREAD", GuildPublicThread = "GUILD_PUBLIC_THREAD", GuildPrivateThread = "GUILD_PRIVATE_THREAD", GuildAny = "GUILD_ANY" } /** * The available command pre-conditions. * @since 2.0.0 */ declare enum CommandPreConditions { Cooldown = "Cooldown", /** @deprecated Use {@link RunIn} instead. */ DirectMessageOnly = "DMOnly", RunIn = "RunIn", /** @deprecated Use {@link RunIn} instead. */ GuildNewsOnly = "GuildNewsOnly", /** @deprecated Use {@link RunIn} instead. */ GuildNewsThreadOnly = "GuildNewsThreadOnly", /** @deprecated Use {@link RunIn} instead. */ GuildOnly = "GuildOnly", /** @deprecated Use {@link RunIn} instead. */ GuildPrivateThreadOnly = "GuildPrivateThreadOnly", /** @deprecated Use {@link RunIn} instead. */ GuildPublicThreadOnly = "GuildPublicThreadOnly", /** @deprecated Use {@link RunIn} instead. */ GuildTextOnly = "GuildTextOnly", /** @deprecated Use {@link RunIn} instead. */ GuildVoiceOnly = "GuildVoiceOnly", /** @deprecated Use {@link RunIn} instead. */ GuildThreadOnly = "GuildThreadOnly", NotSafeForWork = "NSFW", ClientPermissions = "ClientPermissions", UserPermissions = "UserPermissions" } /** * The strategy options used in Sapphire. */ interface FlagStrategyOptions { /** * The accepted flags. Flags are key-only identifiers that can be placed anywhere in the command. Two different types are accepted: * * An array of strings, e.g. [`silent`]. * * A boolean defining whether the strategy should accept all keys (`true`) or none at all (`false`). * @default [] */ flags?: readonly string[] | boolean; /** * The accepted options. Options are key-value identifiers that can be placed anywhere in the command. Two different types are accepted: * * An array of strings, e.g. [`silent`]. * * A boolean defining whether the strategy should accept all keys (`true`) or none at all (`false`). * @default [] */ options?: readonly string[] | boolean; /** * The prefixes for both flags and options. * @default ['--', '-', '—'] */ prefixes?: string[]; /** * The flag separators. * @default ['=', ':'] */ separators?: string[]; } declare class ApplicationCommandRegistry { /** * The piece this registry is for. */ readonly commandName: string; /** * A set of all chat input command names and ids that point to this registry. * You should not use this field directly, but instead use {@link ApplicationCommandRegistry.globalChatInputCommandIds} */ readonly chatInputCommands: Set<string>; /** * A set of all context menu command names and ids that point to this registry. * You should not use this field directly, but instead use {@link ApplicationCommandRegistry.globalContextMenuCommandIds} */ readonly contextMenuCommands: Set<string>; /** * The guild ids that we need to fetch the commands for. */ readonly guildIdsToFetch: Set<string>; /** * The global slash command id for this command. * @deprecated This field will only show the first global command id registered for this registry. * Use {@link ApplicationCommandRegistry.globalChatInputCommandIds} instead. */ globalCommandId: string | null; /** * A set of all registered and valid global chat input command ids that point to this registry. */ readonly globalChatInputCommandIds: Set<string>; /** * A set of all registered and valid global context menu command ids that point to this registry. */ readonly globalContextMenuCommandIds: Set<string>; /** * The guild command ids for this command. * @deprecated This field will only show the first guild command id registered for this registry per guild. * Use {@link ApplicationCommandRegistry.guildIdToChatInputCommandIds} and {@link ApplicationCommandRegistry.guildIdToContextMenuCommandIds} instead. */ readonly guildCommandIds: Collection<string, string>; /** * A map of guild ids to a set of registered and valid chat input command ids that point to this registry. */ readonly guildIdToChatInputCommandIds: Collection<string, Set<string>>; /** * A map of guild ids to a set of registered and valid context menu command ids that point to this registry. */ readonly guildIdToContextMenuCommandIds: Collection<string, Set<string>>; private readonly apiCalls; constructor(commandName: string); get command(): Command<Args, CommandOptions> | undefined; registerChatInputCommand(command: ChatInputApplicationCommandData | SlashCommandBuilder | SlashCommandSubcommandsOnlyBuilder | SlashCommandOptionsOnlyBuilder | Omit<SlashCommandBuilder, 'addSubcommand' | 'addSubcommandGroup'> | ((builder: SlashCommandBuilder) => unknown), options?: ApplicationCommandRegistryRegisterOptions): this; registerContextMenuCommand(command: UserApplicationCommandData | MessageApplicationCommandData | ContextMenuCommandBuilder | ((builder: ContextMenuCommandBuilder) => unknown), options?: ApplicationCommandRegistryRegisterOptions): this; addChatInputCommandNames(...names: string[] | string[][]): this; addContextMenuCommandNames(...names: string[] | string[][]): this; addChatInputCommandIds(...commandIds: string[] | string[][]): this; addContextMenuCommandIds(...commandIds: string[] | string[][]): this; protected runAPICalls(applicationCommands: ApplicationCommandManager, globalCommands: Collection<string, ApplicationCommand>, guildCommands: Map<string, Collection<string, ApplicationCommand>>): Promise<void>; protected handleIdAddition(type: InternalRegistryAPIType, id: string, guildId?: string | null): void; private getGuildIdsToRegister; private processGuildIds; private handleAPICall; private handleCommandPresent; private logCommandDifferencesFound; private createMissingCommand; private info; private error; private warn; private debug; private trace; } declare namespace ApplicationCommandRegistry { interface RegisterOptions { /** * If this is specified, the application commands will only be registered for these guild ids. */ guildIds?: string[]; /** * If we should register the command when it is missing * @default true */ registerCommandIfMissing?: boolean; /** * Specifies what we should do when the command is present, but not identical with the data you provided * @default `ApplicationCommandRegistries.getDefaultBehaviorWhenNotIdentical()` */ behaviorWhenNotIdentical?: Exclude<RegisterBehavior, RegisterBehavior.BulkOverwrite>; /** * Specifies a list of command ids that we should check in the event of a name mismatch * @default [] */ idHints?: string[]; } } type ApplicationCommandRegistryRegisterOptions = ApplicationCommandRegistry.RegisterOptions; interface CooldownPreconditionContext extends AllFlowsPrecondition.Context { scope?: BucketScope; delay: number; limit?: number; filteredUsers?: Snowflake[]; } declare class CorePrecondition$e extends AllFlowsPrecondition { buckets: WeakMap<Command, RateLimitManager<string>>; messageRun(message: Message, command: Command, context: CooldownPreconditionContext): AllFlowsPrecondition.Result; chatInputRun(interaction: ChatInputCommandInteraction, command: Command, context: CooldownPreconditionContext): AllFlowsPrecondition.Result; contextMenuRun(interaction: ContextMenuCommandInteraction, command: Command, context: CooldownPreconditionContext): AllFlowsPrecondition.Result; private sharedRun; private getIdFromMessage; private getIdFromInteraction; private getManager; } /** * Errors thrown by preconditions * @property name This will be `'PreconditionError'` and can be used to distinguish the type of error when any error gets thrown */ declare class PreconditionError extends UserError { readonly precondition: Precondition; constructor(options: PreconditionError.Options); get name(): string; } declare namespace PreconditionError { /** * The options for {@link PreconditionError}. * @since 1.0.0 */ interface Options extends Omit<UserError.Options, 'identifier'> { /** * The precondition that caused the error. * @since 1.0.0 */ precondition: Precondition; /** * The identifier. * @since 1.0.0 * @default precondition.name */ identifier?: string; } } type PreconditionResult = Awaitable<Result<unknown, UserError>>; type AsyncPreconditionResult = Promise<Result<unknown, UserError>>; /** * The registered preconditions and their contexts, if any. When registering new ones, it is recommended to use * [module augmentation](https://www.typescriptlang.org/docs/handbook/declaration-merging.html#module-augmentation) so * custom ones are registered. * * When a key's value is `never`, it means that it does not take any context, which allows you to pass its identifier as * a bare string (e.g. `preconditions: ['NSFW']`), however, if context is required, a non-`never` type should be passed, * which will type {@link PreconditionContainerArray#append} and require an object with the name and a `context` with * the defined type. * * @example * ```typescript * declare module '@sapphire/framework' { * interface Preconditions { * // A precondition named `Moderator` which does not read `context`: * Moderator: never; * * // A precondition named `ChannelPermissions` which does read `context`: * ChannelPermissions: { * permissions: Permissions; * }; * } * } * * // [✔] These are valid: * preconditions.append('Moderator'); * preconditions.append({ name: 'Moderator' }); * preconditions.append({ * name: 'ChannelPermissions', * context: { permissions: new Permissions(8) } * }); * * // [X] These are invalid: * preconditions.append({ name: 'Moderator', context: {} }); * // ➡ `never` keys do not accept `context`. * * preconditions.append('ChannelPermissions'); * // ➡ non-`never` keys always require `context`, a string cannot be used. * * preconditions.append({ * name: 'ChannelPermissions', * context: { unknownProperty: 1 } * }); * // ➡ mismatching `context` properties, `{ unknownProperty: number }` is not * // assignable to `{ permissions: Permissions }`. * ``` */ interface Preconditions { Cooldown: CooldownPreconditionContext; DMOnly: never; Enabled: never; GuildNewsOnly: never; GuildNewsThreadOnly: never; GuildOnly: never; GuildPrivateThreadOnly: never; GuildPublicThreadOnly: never; GuildTextOnly: never; GuildVoiceOnly: never; GuildThreadOnly: never; NSFW: never; RunIn: { types: readonly ChannelType[] | RunInPreconditionCommandSpecificData; }; ClientPermissions: { permissions: PermissionsBitField; }; UserPermissions: { permissions: PermissionsBitField; }; } /** * The specific data for the precondition types for the `RunIn` precondition, when the command * specified the types for specific command types. */ interface RunInPreconditionCommandSpecificData { messageRun: readonly ChannelType[]; chatInputRun: readonly ChannelType[]; contextMenuRun: readonly ChannelType[]; } type PreconditionKeys = keyof Preconditions; type SimplePreconditionKeys = { [K in PreconditionKeys]: Preconditions[K] extends never ? K : never; }[PreconditionKeys]; interface PreconditionOptions extends Piece.Options { /** * The position for the precondition to be set at in the global precondition list. If set to `null`, this * precondition will not be set as a global one. * @default null */ position?: number | null; } interface PreconditionContext extends Record<PropertyKey, unknown> { external?: boolean; } declare class Precondition<Options extends Precondition.Options = Precondition.Options> extends Piece<Options, 'preconditions'> { readonly position: number | null; constructor(context: Precondition.LoaderContext, options?: Options); messageRun?(message: Message, command: MessageCommand, context: Precondition.Context): Precondition.Result; chatInputRun?(interaction: ChatInputCommandInteraction, command: ChatInputCommand, context: Precondition.Context): Precondition.Result; contextMenuRun?(interaction: ContextMenuCommandInteraction, command: ContextMenuCommand, context: Precondition.Context): Precondition.Result; ok(): Precondition.Result; /** * Constructs a {@link PreconditionError} with the precondition parameter set to `this`. * @param options The information. */ error(options?: Omit<PreconditionError.Options, 'precondition'>): Precondition.Result; protected fetchChannelFromInteraction(interaction: CommandInteraction): Promise<TextBasedChannel>; } declare namespace Precondition { type Options = PreconditionOptions; type LoaderContext = Piece.LoaderContext<'preconditions'>; type Context = PreconditionContext; type Result = PreconditionResult; type AsyncResult = AsyncPreconditionResult; } declare abstract class AllFlowsPrecondition extends Precondition { abstract messageRun(message: Message, command: MessageCommand, context: Precondition.Context): Precondition.Result; abstract chatInputRun(interaction: ChatInputCommandInteraction, command: ChatInputCommand, context: Precondition.Context): Precondition.Result; abstract contextMenuRun(interaction: ContextMenuCommandInteraction, command: ContextMenuCommand, context: Precondition.Context): Precondition.Result; } declare namespace AllFlowsPrecondition { type Options = PreconditionOptions; type LoaderContext = Piece.LoaderContext<'preconditions'>; type Context = PreconditionContext; type Result = PreconditionResult; type AsyncResult = AsyncPreconditionResult; } /** * Defines the result's value for a PreconditionContainer. * @since 1.0.0 */ type PreconditionContainerResult = Result<unknown, UserError>; /** * Defines the return type of the generic {@link IPreconditionContainer.messageRun}. * @since 1.0.0 */ type PreconditionContainerReturn = Awaitable<PreconditionContainerResult>; /** * Async-only version of {@link PreconditionContainerReturn}, to be used when the run method is async. * @since 1.0.0 */ type AsyncPreconditionContainerReturn = Promise<PreconditionContainerResult>; /** * An abstracted precondition container to be implemented by classes. * @since 1.0.0 */ interface IPreconditionContainer { /** * Runs a precondition container. * @since 1.0.0 * @param message The message that ran this precondition. * @param command The command the message invoked. * @param context The context for the precondition. */ messageRun(message: Message, command: Command, context?: PreconditionContext): PreconditionContainerReturn; /** * Runs a precondition container. * @since 3.0.0 * @param interaction The interaction that ran this precondition. * @param command The command the interaction invoked. * @param context The context for the precondition. */ chatInputRun(interaction: ChatInputCommandInteraction, command: Command, context?: PreconditionContext): PreconditionContainerReturn; /** * Runs a precondition container. * @since 3.0.0 * @param interaction The interaction that ran this precondition. * @param command The command the interaction invoked. * @param context The context for the precondition. */ contextMenuRun(interaction: ContextMenuCommandInteraction, command: Command, context?: PreconditionContext): PreconditionContainerReturn; } /** * Defines the simple options for the {@link PreconditionContainerSingle}, where only the name of the precondition can * be defined. * @since 2.0.0 */ interface SimplePreconditionSingleResolvableDetails { /** * The name of the precondition to retrieve from {@link SapphireClient.preconditions}. * @since 2.0.0 */ name: SimplePreconditionKeys; } /** * Defines the detailed options for the {@link PreconditionContainerSingle}, where both the {@link PreconditionContext} and the * name of the precondition can be defined. * @since 1.0.0 */ interface PreconditionSingleResolvableDetails<K extends PreconditionKeys = PreconditionKeys> { /** * The name of the precondition to retrieve from {@link SapphireClient.preconditions}. * @since 1.0.0 */ name: K; /** * The context to be set at {@link PreconditionContainerSingle.context}. * @since 1.0.0 */ context: Preconditions[K]; } /** * Defines the data accepted by {@link PreconditionContainerSingle}'s constructor. * @since 1.0.0 */ type PreconditionSingleResolvable = SimplePreconditionKeys | SimplePreconditionSingleResolvableDetails | PreconditionSingleResolvableDetails; /** * An {@link IPreconditionContainer} which runs a single precondition from {@link SapphireClient.preconditions}. * @since 1.0.0 */ declare class PreconditionContainerSingle implements IPreconditionContainer { /** * The context to be used when calling {@link Precondition.run}. This will always be an empty object (`{}`) when the * container was constructed with a string, otherwise it is a direct reference to the value from * {@link PreconditionSingleResolvableDetails.context}. * @since 1.0.0 */ readonly context: Record<PropertyKey, unknown>; /** * The name of the precondition to run. * @since 1.0.0 */ readonly name: string; constructor(data: PreconditionSingleResolvable); /** * Runs the container. * @since 1.0.0 * @param message The message that ran this precondition. * @param command The command the message invoked. * @param context The context for the message precondition. */ messageRun(message: Message, command: MessageCommand, context?: PreconditionContext): PreconditionResult | _sapphire_result.Err<UserError, any>; /** * Runs the container. * @since 3.0.0 * @param interaction The interaction that ran this precondition. * @param command The command the interaction invoked. * @param context The context for the chat input command precondition. */ chatInputRun(interaction: ChatInputCommandInteraction, command: ChatInputCommand, context?: PreconditionContext): PreconditionResult | _sapphire_result.Err<UserError, any>; /** * Runs the container. * @since 3.0.0 * @param interaction The interaction that ran this precondition. * @param command The command the interaction invoked. * @param context The context for the context menu command precondition. */ contextMenuRun(interaction: ContextMenuCommandInteraction, command: ContextMenuCommand, context?: PreconditionContext): PreconditionResult | _sapphire_result.Err<UserError, any>; } /** * Defines the condition for {@link PreconditionContainerArray}s to run. * @since 1.0.0 */ interface IPreconditionCondition { /** * Runs the containers one by one. * @seealso {@link PreconditionRunMode.Sequential} * @since 1.0.0 * @param message The message that ran this precondition. * @param command The command the message invoked. * @param entries The containers to run. * @param context The context for the precondition. */ messageSequential(message: Message, command: MessageCommand, entries: readonly IPreconditionContainer[], context: PreconditionContext): PreconditionContainerReturn; /** * Runs all the containers using `Promise.all`, then checks the results once all tasks finished running. * @seealso {@link PreconditionRunMode.Parallel} * @since 1.0.0 * @param message The message that ran this precondition. * @param command The command the message invoked. * @param entries The containers to run. * @param context The context for the precondition. */ messageParallel(message: Message, command: MessageCommand, entries: readonly IPreconditionContainer[], context: PreconditionContext): PreconditionContainerReturn; /** * Runs the containers one by one. * @seealso {@link PreconditionRunMode.Sequential} * @since 3.0.0 * @param interaction The interaction that ran this precondition. * @param command The command the interaction invoked. * @param entries The containers to run. * @param context The context for the precondition. */ chatInputSequential(interaction: ChatInputCommandInteraction, command: ChatInputCommand, entries: readonly IPreconditionContainer[], context: PreconditionContext): PreconditionContainerReturn; /** * Runs all the containers using `Promise.all`, then checks the results once all tasks finished running. * @seealso {@link PreconditionRunMode.Parallel} * @since 3.0.0 * @param interaction The interaction that ran this precondition. * @param command The command the interaction invoked. * @param entries The containers to run. * @param context The context for the precondition. */ chatInputParallel(interaction: ChatInputCommandInteraction, command: ChatInputCommand, entries: readonly IPreconditionContainer[], context: PreconditionContext): PreconditionContainerReturn; /** * Runs the containers one by one. * @seealso {@link PreconditionRunMode.Sequential} * @since 3.0.0 * @param interaction The interaction that ran this precondition. * @param command The command the interaction invoked. * @param entries The containers to run. * @param context The context for the precondition. */ contextMenuSequential(interaction: ContextMenuCommandInteraction, command: ContextMenuCommand, entries: readonly IPreconditionContainer[], context: PreconditionContext): PreconditionContainerReturn; /** * Runs all the containers using `Promise.all`, then checks the results once all tasks finished running. * @seealso {@link PreconditionRunMode.Parallel} * @since 3.0.0 * @param interaction The interaction that ran this precondition. * @param command The command the interaction invoked. * @param entries The containers to run. * @param context The context for the precondition. */ contextMenuParallel(interaction: ContextMenuCommandInteraction, command: ContextMenuCommand, entries: readonly IPreconditionContainer[], context: PreconditionContext): PreconditionContainerReturn; } /** * The run mode for a {@link PreconditionContainerArray}. * @since 1.0.0 */ declare enum PreconditionRunMode { /** * The entries are run sequentially, this is the default behaviour and can be slow when doing long asynchronous * tasks, but is performance savvy. * @since 1.0.0 */ Sequential = 0, /** * All entries are run in parallel using `Promise.all`, then the results are processed after all of them have * completed. * @since 1.0.0 */ Parallel = 1 } /** * The condition for a {@link PreconditionContainerArray}. */ declare enum PreconditionRunCondition { /** * Defines a condition where all the entries must pass. This uses {@link PreconditionConditionAnd}. * @since 1.0.0 */ And = 0, /** * Defines a condition where at least one entry must pass. This uses {@link PreconditionConditionOr}. * @since 1.0.0 */ Or = 1 } /** * Defines the detailed options for the {@link PreconditionContainerArray}, where both the {@link PreconditionRunMode} and the * entries can be defined. * @since 1.0.0 */ interface PreconditionArrayResolvableDetails { /** * The data that will be used to resolve {@link IPreconditionContainer} dependent of this one. * @since 1.0.0 */ entries: readonly PreconditionEntryResolvable[]; /** * The mode the {@link PreconditionContainerArray} will run. * @since 1.0.0 */ mode: PreconditionRunMode; } /** * Defines the data accepted by {@link PreconditionContainerArray}'s constructor. * @since 1.0.0 */ type PreconditionArrayResolvable = readonly PreconditionEntryResolvable[] | PreconditionArrayResolvableDetails; /** * Defines the data accepted for each entry of the array. * @since 1.0.0 * @seealso {@link PreconditionArrayResolvable} * @seealso {@link PreconditionArrayResolvableDetails.entries} */ type PreconditionEntryResolvable = PreconditionSingleResolvable | PreconditionArrayResolvable; /** * An {@link IPreconditionContainer} that defines an array of multiple {@link IPreconditionContainer}s. * * By default, array containers run either of two conditions: AND and OR ({@link PreconditionRunCondition}), the top level * will always default to AND, where the nested one flips the logic (OR, then children arrays are AND, then OR...). * * This allows `['Connect', ['Moderator', ['DJ', 'SongAuthor']]]` to become a thrice-nested precondition container, where: * - Level 1: [Single(Connect), Array] runs AND, both containers must return a successful value. * - Level 2: [Single(Moderator), Array] runs OR, either container must return a successful value. * - Level 3: [Single(DJ), Single(SongAuthor)] runs AND, both containers must return a successful value. * * In other words, it is identical to doing: * ```typescript * Connect && (Moderator || (DJ && SongAuthor)); * ``` * @remark More advanced logic can be accomplished by adding more {@link IPreconditionCondition}s (e.g. other operators), * see {@link PreconditionContainerArray.conditions} for more information. * @since 1.0.0 */ declare class PreconditionContainerArray implements IPreconditionContainer { /** * The mode at which this precondition will run. * @since 1.0.0 */ readonly mode: PreconditionRunMode; /** * The {@link IPreconditionContainer}s the array holds. * @since 1.0.0 */ readonly entries: IPreconditionContainer[]; /** * The {@link PreconditionRunCondition} that defines how entries must be handled. * @since 1.0.0 */ readonly runCondition: PreconditionRunCondition; constructor(data?: PreconditionArrayResolvable, parent?: PreconditionContainerArray | null); /** * Adds a new entry to the array. * @since 1.0.0 * @param entry The value to add to the entries. */ add(entry: IPreconditionContainer): this; append(keyOrEntries: SimplePreconditionSingleResolvableDetails | SimplePreconditionKeys | PreconditionContainerArray): this; append<K extends PreconditionKeys>(entry: PreconditionSingleResolvableDetails<K>): this; /** * Runs the container. * @since 1.0.0 * @param message The message that ran this precondition. * @param command The command the message invoked. * @param context The context for the message command precondition. */ messageRun(message: Message, command: MessageCommand, context?: PreconditionContext): PreconditionContainerReturn; /** * Runs the container. * @since 3.0.0 * @param interaction The interaction that ran this precondition. * @param command The command the interaction invoked. * @param context The context for the chat input precondition. */ chatInputRun(interaction: ChatInputCommandInteraction, command: ChatInputCommand, context?: PreconditionContext): PreconditionContainerReturn; /** * Runs the container. * @since 3.0.0 * @param interaction The interaction that ran this precondition. * @param command The command the interaction invoked. * @param context The context for the context menu precondition. */ contextMenuRun(interaction: ContextMenuCommandInteraction, command: ContextMenuCommand, context?: PreconditionContext): PreconditionContainerReturn; /** * Parses the precondition entry resolvables, and adds them to the entries. * @since 1.0.0 * @param entries The entries to parse. */ protected parse(entries: Iterable<PreconditionEntryResolvable>): this; /** * Retrieves a condition from {@link PreconditionContainerArray.conditions}, assuming existence. * @since 1.0.0 */ protected get condition(): IPreconditionCondition; /** * The preconditions to be run. Extra ones can be added by augmenting {@link PreconditionRunCondition} and then * inserting {@link IPreconditionCondition}s. * @since 1.0.0 * @example * ```typescript * // Adding more kinds of conditions * * // Set the new condition: * PreconditionContainerArray.conditions.set(2, PreconditionConditionRandom); * * // Augment Sapphire to add the new condition, in case of a JavaScript * // project, this can be moved to an `Augments.d.ts` (or any other name) * // file somewhere: * declare module '@sapphire/framework' { * export enum PreconditionRunCondition { * Random = 2 * } * } * ``` */ static readonly conditions: Collection<PreconditionRunCondition, IPreconditionCondition>; } declare class Command<PreParseReturn = Args, Options extends Command.Options = Command.Options> extends AliasPiece<Options, 'commands'> { /** * The raw name of the command as provided through file name or constructor options. * * This is exactly what is set by the developer, completely unmodified internally by the framework. * Unlike the `name` which gets lowercased for storing it uniquely in the {@link CommandStore}. */ rawName: string; /** * A basic summary about the command * @since 1.0.0 */ description: string; /** * The preconditions to be run. * @since 1.0.0 */ preconditions: PreconditionContainerArray; /** * Longer version of command's summary and how to use it * @since 1.0.0 */ detailedDescription: DetailedDescriptionCommand; /** * The full category for the command, can be overridden by setting the {@link Command.Options.fullCategory} option. * * If {@link Command.Options.fullCategory} is not set, then: * - If the command is loaded from the file system, then this is the command's location in file system relative to * the commands folder. For example, if you have a command located at `commands/General/Information/info.ts` then * this property will be `['General', 'Info']`. * - If the command is virtual, then this will be `[]`. * * @since 2.0.0 */ readonly fullCategory: readonly string[]; /** * The strategy to use for the lexer. * @since 1.0.0 */ strategy: IUnorderedStrategy; /** * If {@link SapphireClient.typing} is true, it can be overridden for a specific command using this property, set via its options. * Otherwise, this property will be ignored. * @default true */ typing: boolean; /** * The application command registry associated with this command. * @since 3.0.0 */ readonly applicationCommandRegistry: ApplicationCommandRegistry; /** * The lexer to be used for command parsing * @since 1.0.0 * @private */ protected lexer: Lexer; /** * @since 1.0.0 * @param context The context. * @param options Optional Command settings. */ constructor(context: Command.LoaderContext, options?: 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: Message, parameters: string, context: MessageCommand.RunContext): Awaitable<PreParseReturn>; /** * 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(): string | 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(): string | 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(): string | null; /** * Executes the message command's logic. * @param message The message that triggered the command. * @param args The value returned by {@link Command.messagePreParse}, by default an instance of {@link Args}. * @param context The context in which the command was executed. */ messageRun?(message: Message, args: PreParseReturn, context: MessageCommand.RunContext): Awaitable<unknown>; /** * Executes the application command's logic. * @param interaction The interaction that triggered the command. * @param context The chat input command run context. */ chatInputRun?(interaction: ChatInputCommandInteraction, context: ChatInputCommand.RunContext): Awaitable<unknown>; /** * Executes the context menu's logic. * @param interaction The interaction that triggered the command. * @param context The context menu command run context. */ contextMenuRun?(interaction: ContextMenuCommandInteraction, context: ContextMenuCommand.RunContext): Awaitable<unknown>; /** * Executes the autocomplete logic. * * :::tip * * You may use this, or alternatively create an {@link InteractionHandler interaction handler} to handle autocomplete interactions. * Keep in mind that commands take precedence over interaction handlers. * * ::: * * @param interaction The interaction that triggered the autocomplete. */ autocompleteRun?(interaction: AutocompleteInteraction): Awaitable<unknown>; /** * Defines the JSON.stringify behavior of the command. */ toJSON(): CommandJSON; /** * Registers the application commands that should be handled by this command. * @param registry This command's registry */ registerApplicationCommands?(registry: ApplicationCommandRegistry): Awaitable<void>; /** * Type-guard that ensures the command supports message commands by checking if the handler for it is present */ supportsMessageCommands(): this is MessageCommand; /** * Type-guard that ensures the command supports chat input commands by checking if the handler for it is present */ supportsChatInputCommands(): this is ChatInputCommand; /** * Type-guard that ensures the command supports context menu commands by checking if the handler for it is present */ supportsContextMenuCommands(): this is ContextMenuCommand; /** * Type-guard that ensures the command supports handling autocomplete interactions by checking if the handler for it is present */ supportsAutocompleteInteractions(): this is AutocompleteCommand; reload(): Promise<void>; /** * 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. */ protected parseConstructorPreConditions(options: Command.Options): void; /** * Appends the `NSFW` precondition if {@link Command.Options.nsfw} is set to true. * @param options The command options given from the constructor. */ protected parseConstructorPreConditionsNsfw(options: Command.Options): void; /** * 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. */ protected parseConstructorPreConditionsRunIn(options: Command.Options): void; /** * Appends the `ClientPermissions` precondition when {@link Command.Options.requiredClientPermissions} resolves to a * non-zero bitfield. * @param options The command options given from the constructor. */ protected parseConstructorPreConditionsRequiredClientPermissions(options: Command.Options): void; /** * Appends the `UserPermissions` precondition when {@link Command.Options.requiredUserPermissions} resolves to a * non-zero bitfield. * @param options The command options given from the constructor. */ protected parseConstructorPreConditionsRequiredUserPermissions(options: Command.Options): void; /** * 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. */ protected parseConstructorPreConditionsCooldown(options: Command.Options): void; /** * 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. */ protected resolveConstructorPreConditionsRunType(types: CommandRunInUnion): readonly ChannelType[] | null; static runInTypeIsSpecificsObject(types: Command.Options['runIn']): types is CommandSpecificRunIn; } declare namespace Command { type Options = CommandOptions; type JSON = CommandJSON; /** @deprecated Use {@linkcode LoaderContext} instead. */ type Context = LoaderContext; type LoaderContext = AliasPiece.LoaderContext<'commands'>; type RunInTypes = CommandOptionsRunType; type RunInUnion = CommandRunInUnion; type SpecificRunIn = CommandSpecificRunIn; type ChatInputCommandInteraction<Cached extends discord_js.CacheType = discord_js.CacheType> = discord_js.ChatInputCommandInteraction<Cached>; type ContextMenuCommandInteraction<Cached extends discord_js.CacheType = discord_js.CacheType> = discord_js.ContextMenuCommandInteraction<Cached>; type AutocompleteInteraction<Cached extends discord_js.CacheType = discord_js.CacheType> = discord_js.AutocompleteInteraction<Cached>; type Registry = ApplicationCommandRegistry; } type DetailedDescriptionCommand = string | DetailedDescriptionCommandObject; interface DetailedDescriptionCommandObject { } /** * The allowed values for {@link CommandOptions.runIn}. * @remark It is discouraged to use this type, we recommend using {@link CommandOptionsRunTypeEnum} instead. * @since 2.0.0 */ type CommandOptionsRunType = 'DM' | 'GUILD_TEXT' | 'GUILD_VOICE' | 'GUILD_NEWS' | 'GUILD_NEWS_THREAD' | 'GUILD_PUBLIC_THREAD' | 'GUILD_PRIVATE_THREAD' | 'GUILD_ANY'; /** * The allowed values for {@link CommandOptions.runIn}. * @since 4.7.0 */ type CommandRunInUnion = ChannelType | Command.RunInTypes | CommandOptionsRunTypeEnum | readonly (ChannelType | Command.RunInTypes | CommandOptionsRunTypeEnum)[] | Nullish; /** * A more detailed structure for {@link CommandOptions.runIn} when you want to have a different `runIn` for each * command type. * @since 4.7.0 */ interface