@sapphire/framework
Version:
Discord bot framework built for advanced and amazing bots.
1,215 lines (1,197 loc) • 170 kB
text/typescript
/// <reference types="node" />
import * as discord_js0 from 'discord.js';
import { Snowflake, Message, ChatInputCommandInteraction, ContextMenuCommandInteraction, CommandInteraction, TextBasedChannel, ChannelType, PermissionsBitField, Collection, DMChannel, CategoryChannel, NewsChannel, ThreadChannel, TextChannel, StageChannel, VoiceChannel, GuildMember, Role, User, AutocompleteInteraction, ChatInputApplicationCommandData, UserApplicationCommandData, MessageApplicationCommandData, ApplicationCommandManager, ApplicationCommand as ApplicationCommand$1, PermissionResolvable, PermissionsString, Interaction, ClientEvents, Client, Events as Events$1, ClientOptions, Guild, PartialDMChannel } from 'discord.js';
import { RateLimitManager } from '@sapphire/ratelimits';
import { Piece, AliasPiece, 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 { Awaitable, Nullish } from '@sapphire/utilities';
export { Awaitable } from '@sapphire/utilities';
import * as _sapphire_result0 from '@sapphire/result';
import { Result, Option } from '@sapphire/result';
export * from '@sapphire/result';
import { ChannelTypes, GuildBasedChannelTypes, TextBasedChannelTypes, AnyInteraction } from '@sapphire/discord.js-utilities';
import { ArgumentStream, IUnorderedStrategy, Lexer } from '@sapphire/lexure';
import { URL } from 'node:url';
import { SlashCommandBuilder, SlashCommandSubcommandsOnlyBuilder, SlashCommandOptionsOnlyBuilder, ContextMenuCommandBuilder } from '@discordjs/builders';
import { EventEmitter } from 'node:events';
//#region src/lib/errors/UserError.d.ts
/**
* 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;
}
}
//# sourceMappingURL=UserError.d.mts.map
//#region src/lib/types/Enums.d.ts
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",
}
//# sourceMappingURL=Enums.d.mts.map
//#region src/preconditions/Cooldown.d.ts
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;
}
//# sourceMappingURL=Cooldown.d.mts.map
//#region src/lib/errors/PreconditionError.d.ts
/**
* 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;
}
}
//# sourceMappingURL=PreconditionError.d.mts.map
//#region src/lib/structures/Precondition.d.ts
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;
}
//# sourceMappingURL=Precondition.d.mts.map
//#region src/lib/utils/preconditions/IPreconditionContainer.d.ts
/**
* 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;
}
//# sourceMappingURL=IPreconditionContainer.d.mts.map
//#region src/lib/utils/preconditions/PreconditionContainerSingle.d.ts
/**
* 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_result0.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_result0.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_result0.Err<UserError, any>;
}
//# sourceMappingURL=PreconditionContainerSingle.d.mts.map
//#region src/lib/utils/preconditions/conditions/IPreconditionCondition.d.ts
/**
* 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;
}
//# sourceMappingURL=IPreconditionCondition.d.mts.map
//#region src/lib/utils/preconditions/PreconditionContainerArray.d.ts
/**
* 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>;
}
//# sourceMappingURL=PreconditionContainerArray.d.mts.map
//#region src/lib/errors/Identifiers.d.ts
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",
}
//# sourceMappingURL=Identifiers.d.mts.map
//#region src/lib/resolvers/emoji.d.ts
declare function resolveEmoji(parameter: string): Result<EmojiObject, Identifiers>;
interface EmojiObject {
name: string | null;
id: string | null;
animated?: boolean;
}
//# sourceMappingURL=emoji.d.mts.map
//#region src/lib/parsers/Args.d.ts
/**
* The argument parser to be used in {@link Command}.
*/
declare class Args {
/**
* The original message that triggered the command.
*/
readonly message: Message;
/**
* The command that is being run.
*/
readonly command: MessageCommand;
/**
* The context of the command being run.
*/
readonly commandContext: MessageCommand.RunContext;
/**
* The internal Lexure parser.
*/
protected readonly parser: ArgumentStream;
/**
* The states stored in the args.
* @see Args#save
* @see Args#restore
*/
private readonly states;
constructor(message: Message, command: MessageCommand, parser: ArgumentStream, context: MessageCommand.RunContext);
/**
* Sets the parser to the first token.
*/
start(): Args;
/**
* Retrieves the next parameter and parses it. Advances index on success.
* @param type The type of the argument.
* @param options The pickResult options.
* @example
* ```typescript
* // !square 5
* const resolver = Args.make((parameter, { argument }) => {
* const parsed = Number(parameter);
* if (Number.isNaN(parsed)) {
* return Args.error({ argument, parameter, identifier: 'ArgumentNumberNaN', message: 'You must write a valid number.' });
* }
*
* return Args.ok(parsed);
* });
*
* const a = await args.pickResult(resolver);
* if (!a.success) {
* throw new UserError({ identifier: 'ArgumentNumberNaN', message: 'You must write a valid number.' });
* }
*
* await message.channel.send(`The result is: ${a.value ** 2}!`);
* // Sends "The result is: 25"
* ```
*/
pickResult<T>(type: IArgument<T>, options?: ArgOptions): Promise<ResultType<T>>;
/**
* Retrieves the next parameter and parses it. Advances index on success.
* @param type The type of the argument.
* @param options The pickResult options.
* @example
* ```typescript
* // !add 1 2
* const a = await args.pickResult('integer');
* if (!a.success) {
* throw new UserError({ identifier: 'AddArgumentError', message: 'You must write two numbers, but the first one did not match.' });
* }
*
* const b = await args.pickResult('integer');
* if (!b.success) {
* throw new UserError({ identifier: 'AddArgumentError', message: 'You must write two numbers, but the second one did not match.' });
* }
*
* await message.channel.send(`The result is: ${a.value + b.value}!`);
* // Sends "The result is: 3"
* ```
*/
pickResult<K extends keyof ArgType>(type: K, options?: ArgOptions): Promise<ResultType<ArgType[K]>>;
/**
* Similar to {@link Args.pickResult} but returns the value on success, throwing otherwise.
* @param type The type of the argument.
* @param options The pick options.
* @example
* ```typescript
* // !square 5
* const resolver = Args.make((parameter, { argument }) => {
* const parsed = Number(parameter);
* if (Number.isNaN(parsed)) {
* return Args.error({ argument, parameter, identifier: 'ArgumentNumberNaN', message: 'You must write a valid number.' });
* }
*
* return Args.ok(parsed);
* });
*
* const a = await args.pick(resolver);
*
* await message.channel.send(`The result is: ${a ** 2}!`);
* // Sends "The result is: 25"
* ```
*/
pick<T>(type: IArgument<T>, options?: ArgOptions): Promise<T>;
/**
* Similar to {@link Args.pickResult} but returns the value on success, throwing otherwise.
* @param type The type of the argument.
* @param options The pick options.
* @example
* ```typescript
* // !add 1 2
* const a = await args.pick('integer');
* const b = await args.pick('integer');
* await message.channel.send(`The result is: ${a + b}!`);
* // Sends "The result is: 3"
* ```
*/
pick<K extends keyof ArgType>(type: K, options?: ArgOptions): Promise<ArgType[K]>;
/**
* Retrieves all the following arguments.
* @param type The type of the argument.
* @param options The restResult options.
* @example
* ```typescript
* // !reverse Hello world!
* const resolver = Args.make((parameter) => Args.ok(parameter.split('').reverse()));
*
* const a = await args.restResult(resolver);
* if (!a.success) {
* throw new UserError({ identifier: 'AddArgumentError', message: 'You must write some text.' });
* }
*
* await message.channel.send(`The reversed value is... ${a.value}`);
* // Sends "The reversed value is... !dlrow olleH"
* ```
*/
restResult<T>(type: IArgument<T>, options?: ArgOptions): Promise<ResultType<T>>;
/**
* Retrieves all the following arguments.
* @param type The type of the argument.
* @param options The restResult options.
* @example
* ```typescript
* // !add 2 Hello World!
* const a = await args.pickResult('integer');
* if (!a.success) {
* throw new UserError({ identifier: 'AddArgumentError', message: 'You must write a number and a text, but the former did not match.' });
* }
*
* const b = await args.restResult('string', { minimum: 1 });
* if (!b.success) {
* throw new UserError({ identifier: 'AddArgumentError', message: 'You must write a number and a text, but the latter did not match.' });
* }
*
* await message.channel.send(`The repeated value is... ${b.value.repeat(a.value)}!`);
* // Sends "The repeated value is... Hello World!Hello World!"
* ```
*/
restResult<K extends keyof ArgType>(type: K, options?: ArgOptions): Promise<ResultType<ArgType[K]>>;
/**
* Similar to {@link Args.restResult} but returns the value on success, throwing otherwise.
* @param type The type of the argument.
* @param options The rest options.
* @example
* ```typescript
* // !reverse Hello world!
* const resolver = Args.make((arg) => Args.ok(arg.split('').reverse()));
* const a = await args.rest(resolver);
* await message.channel.send(`The reversed value is... ${a}`);
* // Sends "The reversed value is... !dlrow olleH"
* ```
*/
rest<T>(type: IArgument<T>, options?: ArgOptions): Promise<T>;
/**
* Similar to {@link Args.restResult} but returns the value on success, throwing otherwise.
* @param type The type of the argument.
* @param options The rest options.
* @example
* ```typescript
* // !add 2 Hello World!
* const a = await args.pick('integer');
* const b = await args.rest('string', { minimum: 1 });
* await message.channel.send(`The repeated value is... ${b.repeat(a)}!`);
* // Sends "The repeated value is... Hello World!Hello World!"
* ```
*/
rest<K extends keyof ArgType>(type: K, options?: ArgOptions): Promise<ArgType[K]>;
/**
* Retrieves all the following arguments.
* @param type The type of the argument.
* @param options The repeatResult options.
* @example
* ```typescript
* // !add 2 Hello World!
* const resolver = Args.make((arg) => Args.ok(arg.split('').reverse()));
* const result = await args.repeatResult(resolver, { times: 5 });
* if (!result.success) {
* throw new UserError({ identifier: 'CountArgumentError', message: 'You must write up to 5 words.' });
* }
*
* await message.channel.send(`You have written ${result.value.length} word(s): ${result.value.join(' ')}`);
* // Sends "You have written 2 word(s): olleH !dlroW"
* ```
*/
repeatResult<T>(type: IArgument<T>, options?: RepeatArgOptions): Promise<ArrayResultType<T>>;
/**
* Retrieves all the following arguments.
* @param type The type of the argument.
* @param options The repeatResult options.
* @example
* ```typescript
* // !reverse-each 2 Hello World!
* const result = await args.repeatResult('string', { times: 5 });
* if (!result.success) {
* throw new UserError({ identifier: 'CountArgumentError', message: 'You must write up to 5 words.' });
* }
*
* await message.channel.send(`You have written ${result.value.length} word(s): ${result.value.join(' ')}`);
* // Sends "You have written 2 word(s): Hello World!"
* ```
*/
repeatResult<K extends keyof ArgType>(type: K, options?: RepeatArgOptions): Promise<ArrayResultType<ArgType[K]>>;
/**
* Similar to {@link Args.repeatResult} but returns the value on success, throwing otherwise.
* @param type The type of the argument.
* @param options The repeat options.
* @example
* ```typescript
* // !reverse-each 2 Hello World!
* const resolver = Args.make((arg) => Args.ok(arg.split('').reverse()));
* const result = await args.repeat(resolver, { times: 5 });
* await message.channel.send(`You have written ${result.length} word(s): ${result.join(' ')}`);
* // Sends "You have written 2 word(s): Hello World!"
* ```
*/
repeat<T>(type: IArgument<T>, options?: RepeatArgOptions): Promise<T[]>;
/**
* Similar to {@link Args.repeatResult} but returns the value on success, throwing otherwise.
* @param type The type of the argument.
* @param options The repeat options.
* @example
* ```typescript
* // !add 2 Hello World!
* const words = await args.repeat('string', { times: 5 });
* await message.channel.send(`You have written ${words.length} word(s): ${words.join(' ')}`);
* // Sends "You have written 2 word(s): Hello World!"
* ```
*/
repeat<K extends keyof ArgType>(type: K, options?: RepeatArgOptions): Promise<ArgType[K][]>;
/**
* Peeks the following parameter(s) without advancing the parser's state.
* Passing a function as a parameter allows for returning {@link Args.pickResult}, {@link Args.repeatResult},
* or {@link Args.restResult}; otherwise, passing the custom argument or the argument type with options
* will use {@link Args.pickResult} and only peek a single argument.
* @param type The function, custom argument, or argument name.
* @example
* ```typescript
* // !reversedandscreamfirst hello world
* const resolver = Args.make((arg) => Args.ok(arg.split('').reverse().join('')));
*
* const result = await args.repeatResult(resolver);
* await result.inspectAsync((value) =>
* message.channel.send(`Reversed ${value.length} word(s): ${value.join(' ')}`)
* ); // Reversed 2 word(s): olleh dlrow
*
* const firstWord = await args.pickResult('string');
* await firstWord.inspectAsync((value) =>
* message.channel.send(firstWord.value.toUpperCase())
* ); // HELLO
* ```
*/
peekResult<T>(type: () => Argument.Result<T>): Promise<ResultType<T>>;
/**
* Peeks the following parameter(s) without advancing the parser's state.
* Passing a function as a parameter allows for returning {@link Args.pickResult}, {@link Args.repeatResult},
* or {@link Args.restResult}; otherwise, passing the custom argument or the argument type with options
* will use {@link Args.pickResult} and only peek a single argument.
* @param type The function, custom argument, or argument name.
* @param options The peekResult options.
* @example
* ```typescript
* // !reverseandscreamfirst sapphire community
* const resolver = Args.make((arg) => Args.ok(arg.split('').reverse().join('')));
*
* const peekedWord = await args.peekResult(resolver);
* await peekedWord.inspectAsync((value) => message.channel.send(value)); // erihppas
*
* const firstWord = await args.pickResult('string');
* await firstWord.inspectAsync((value) => message.channel.send(value.toUpperCase())); // SAPPHIRE
* ```
*/
peekResult<T>(type: IArgument<T>, options?: ArgOptions): Promise<ResultType<T>>;
/**
* Peeks the following parameter(s) without advancing the parser's state.
* Passing a function as a parameter allows for returning {@link Args.pickResult}, {@link Args.repeatResult},
* or {@link Args.restResult}; otherwise, passing the custom argument or the argument type with options
* will use {@link Args.pickResult} and only peek a single argument.
* @param type The function, custom argument, or argument name.
* @param options The peekResult options.
* @example
* ```typescript
* // !datethenaddtwo 1608867472611
* const date = await args.peekResult('date');
* await date.inspectAsync((value) =>
* message.channel.send(`Your date (in UTC): ${value.toUTCString()}`)
* ); // Your date (in UTC): Fri, 25 Dec 2020 03:37:52 GMT
*
* const result = await args.pickResult('number', { maximum: Number.MAX_SAFE_INTEGER - 2 });
* await result.inspectAsync((value) =>
* message.channel.send(`Your number plus two: ${value + 2}`)
* ); // Your number plus two: 1608867472613
* ```
*/
peekResult<K extends keyof ArgType>(type: (() => Awaitable<Argument.Result<ArgType[K]>>) | K, options?: ArgOptions): Promise<ResultType<ArgType[K]>>;
/**
* Similar to {@link Args.peekResult} but returns the value on success, throwing otherwise.
* @param type The function, custom argument, or argument name.
* @example
* ```typescript
* // !bigintsumthensquarefirst 25 50 75
* const resolver = Args.make((arg, { argument }) => {
* try {
* return Args.ok(BigInt(arg));
* } catch {
* return Args.error({ parameter: arg, argument, identifier: 'InvalidBigInt', message: 'You must specify a valid number for a bigint.' })
* }
* });
*
* const peeked = await args.repeatResult(resolver);
* await peeked.inspectAsync((value) => message.channel.send(`Sum: **${value.reduce((x, y) => x + y, 0n)}**`)); // Sum: 150n
*
* const first = await args.pick(resolver);
* await message.channel.send(`First bigint squared: ${first**2n}`); // First bigint squared: 625
* ```
*/
peek<T>(type: () => Argument.Result<T>): Promise<T>;
/**
* Similar to {@link Args.peekResult} but returns the value on success, throwing otherwise.
* @param type The function, custom argument, or argument name.
* @param options The peek options.
* @example
* ```typescript
* import { SnowflakeRegex } from '@sapphire/discord.js-utilities';
* import { DiscordSnowflake } from '@sapphire/snowflake';
*
* // !createdat 730159185517477900
* const snowflakeResolver = Args.make<bigint>((arg, { argument }) => {
* return SnowflakeRegex.test(arg)
* ? Args.ok(BigInt(arg))
* : Args.error({ parameter: arg, argument, identifier: 'InvalidSnowflake', message: 'You must specify a valid snowflake.' });
* });
*
* const snowflake = await args.peek(snowflakeResolver);
* const timestamp = Number((snowflake >> 22n) + DiscordSnowflake.epoch);
* const createdAt = new Date(timestamp);
*
* await message.channel.send(
* `The snowflake ${snowflake} was registered on ${createdAt.toUTCString()}.`
* ); // The snowflake 730159185517477900 was registered on Tue, 07 Jul 2020 20:31:55 GMT.
*
* const id = await args.pick('string');
* await message.channel.send(`Your ID, reversed: ${id.split('').reverse().join('')}`); // Your ID, reversed: 009774715581951037
* ```
*/
peek<T>(type: IArgument<T>, options?: ArgOptions): Promise<T>;
/**
* Similar to {@link Args.peekResult} but returns the value on success, throwing otherwise.
* @param type The function, custom argument, or argument name.
* @param options The peek options.
* @example
* ```typescript
* // !messagelink https://discord.com/channels/737141877803057244/737142209639350343/791843123898089483
* const remoteMessage = await args.peek('message');
* await message.channel.send(
* `${remoteMessage.author.tag}: ${remoteMessage.content}`
* ); // RealShadowNova#7462: Yeah, Sapphire has been a great experience so far, especially being able to help and contribute.
*
* const url = await args.pick('hyperlink');
* await message.channel.send(`Hostname: ${url.hostname}`); // Hostname: discord.com
* ```
*/
peek<K extends keyof ArgType>(type: (() => Argument.Result<ArgType[K]>) | K, options?: ArgOptions): Promise<ArgType[K]>;
/**
* Retrieves the next raw argument from the parser.
* @example
* ```typescript
* // !numbers 1 2 3
*
* console.log(args.nextMaybe());
* // -> { exists: true, value: '1' }
* ```
*/
nextMaybe(): Option<string>;
/**
* Retrieves the value of the next unused ordered token, but only if it could be transformed.
* That token will now be used if the transformation succeeds.
* @typeparam T Output type of the {@link ArgsNextCallback callback}.
* @param cb Gives an option of either the resulting value, or nothing if failed.
* @example
* ```typescript
* // !numbers 1 2 3
* const parse = (x: strin