Skip to content

Commit 832c979

Browse files
authoredOct 23, 2023
refactor: move command types to its own file (#678)
This way the `Command` file is much shorter and easier to navigate
1 parent fc24a48 commit 832c979

18 files changed

+384
-357
lines changed
 

‎src/index.ts

+1
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ export * from './lib/structures/ListenerStore';
7474
export * from './lib/structures/Precondition';
7575
export * from './lib/structures/PreconditionStore';
7676
export * from './lib/types/ArgumentContexts';
77+
export * from './lib/types/CommandTypes';
7778
export * from './lib/types/Enums';
7879
export * from './lib/types/Events';
7980
export {

‎src/lib/parsers/Args.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ import { Identifiers } from '../errors/Identifiers';
2323
import { UserError } from '../errors/UserError';
2424
import type { EmojiObject } from '../resolvers/emoji';
2525
import type { Argument, IArgument } from '../structures/Argument';
26-
import type { MessageCommand } from '../structures/Command';
26+
import type { MessageCommand } from '../types/CommandTypes';
2727

2828
/**
2929
* The argument parser to be used in {@link Command}.

‎src/lib/structures/Argument.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ import type { Awaitable } from '@sapphire/utilities';
44
import type { Message } from 'discord.js';
55
import type { ArgumentError } from '../errors/ArgumentError';
66
import { Args } from '../parsers/Args';
7+
import type { MessageCommand } from '../types/CommandTypes';
78
import type { ArgumentStore } from './ArgumentStore';
8-
import type { MessageCommand } from './Command';
99

1010
/**
1111
* Defines a synchronous result of an {@link Argument}, check {@link Argument.AsyncResult} for the asynchronous version.

‎src/lib/structures/Command.ts

+18-337
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,34 @@
11
import { ArgumentStream, Lexer, Parser, type IUnorderedStrategy } from '@sapphire/lexure';
2-
import { AliasPiece, type AliasPieceJSON } from '@sapphire/pieces';
3-
import { isNullish, isObject, type Awaitable, type NonNullObject, type Nullish } from '@sapphire/utilities';
2+
import { AliasPiece } from '@sapphire/pieces';
3+
import { isNullish, isObject, type Awaitable } from '@sapphire/utilities';
44
import {
55
ChannelType,
66
ChatInputCommandInteraction,
77
ContextMenuCommandInteraction,
88
PermissionsBitField,
99
type AutocompleteInteraction,
10-
type Message,
11-
type PermissionResolvable,
12-
type Snowflake
10+
type Message
1311
} from 'discord.js';
1412
import { Args } from '../parsers/Args';
15-
import { BucketScope, RegisterBehavior } from '../types/Enums';
13+
import type {
14+
AutocompleteCommand,
15+
ChatInputCommand,
16+
CommandJSON,
17+
CommandOptions,
18+
CommandOptionsRunType,
19+
CommandRunInUnion,
20+
CommandSpecificRunIn,
21+
ContextMenuCommand,
22+
DetailedDescriptionCommand,
23+
MessageCommand
24+
} from '../types/CommandTypes';
25+
import { BucketScope, CommandPreConditions, RegisterBehavior } from '../types/Enums';
1626
import { acquire, getDefaultBehaviorWhenNotIdentical, handleBulkOverwrite } from '../utils/application-commands/ApplicationCommandRegistries';
1727
import type { ApplicationCommandRegistry } from '../utils/application-commands/ApplicationCommandRegistry';
1828
import { getNeededRegistryParameters } from '../utils/application-commands/getNeededParameters';
1929
import { emitPerRegistryError } from '../utils/application-commands/registriesErrors';
20-
import { PreconditionContainerArray, type PreconditionEntryResolvable } from '../utils/preconditions/PreconditionContainerArray';
21-
import { FlagUnorderedStrategy, type FlagStrategyOptions } from '../utils/strategies/FlagUnorderedStrategy';
30+
import { PreconditionContainerArray } from '../utils/preconditions/PreconditionContainerArray';
31+
import { FlagUnorderedStrategy } from '../utils/strategies/FlagUnorderedStrategy';
2232
import type { CommandStore } from './CommandStore';
2333

2434
const ChannelTypes = Object.values(ChannelType).filter((type) => typeof type === 'number') as readonly ChannelType[];
@@ -500,331 +510,6 @@ export class Command<PreParseReturn = Args, O extends Command.Options = Command.
500510
}
501511
}
502512

503-
export type MessageCommand = Command & Required<Pick<Command, 'messageRun'>>;
504-
505-
export namespace MessageCommand {
506-
export type Options = CommandOptions;
507-
export type JSON = CommandJSON;
508-
export type Context = AliasPiece.Context;
509-
export type RunInTypes = CommandOptionsRunType;
510-
export type RunContext = MessageCommandContext;
511-
}
512-
513-
export type ChatInputCommand = Command & Required<Pick<Command, 'chatInputRun'>>;
514-
515-
export namespace ChatInputCommand {
516-
export type Options = CommandOptions;
517-
export type JSON = CommandJSON;
518-
export type Context = AliasPiece.Context;
519-
export type RunInTypes = CommandOptionsRunType;
520-
export type RunContext = ChatInputCommandContext;
521-
export type Interaction<Cached extends import('discord.js').CacheType = import('discord.js').CacheType> = ChatInputCommandInteraction<Cached>;
522-
export type Registry = ApplicationCommandRegistry;
523-
}
524-
525-
export type ContextMenuCommand = Command & Required<Pick<Command, 'contextMenuRun'>>;
526-
527-
export namespace ContextMenuCommand {
528-
export type Options = CommandOptions;
529-
export type JSON = CommandJSON;
530-
export type Context = AliasPiece.Context;
531-
export type RunInTypes = CommandOptionsRunType;
532-
export type RunContext = ContextMenuCommandContext;
533-
export type Interaction<Cached extends import('discord.js').CacheType = import('discord.js').CacheType> = ContextMenuCommandInteraction<Cached>;
534-
export type Registry = ApplicationCommandRegistry;
535-
}
536-
537-
export type AutocompleteCommand = Command & Required<Pick<Command, 'autocompleteRun'>>;
538-
539-
export namespace AutocompleteCommand {
540-
export type Options = CommandOptions;
541-
export type JSON = CommandJSON;
542-
export type Context = AliasPiece.Context;
543-
export type RunInTypes = CommandOptionsRunType;
544-
export type RunContext = AutocompleteCommandContext;
545-
export type Interaction<Cached extends import('discord.js').CacheType = import('discord.js').CacheType> = AutocompleteInteraction<Cached>;
546-
export type Registry = ApplicationCommandRegistry;
547-
}
548-
549-
/**
550-
* The allowed values for {@link Command.Options.runIn}.
551-
* @remark It is discouraged to use this type, we recommend using {@link CommandOptionsRunTypeEnum} instead.
552-
* @since 2.0.0
553-
*/
554-
export type CommandOptionsRunType =
555-
| 'DM'
556-
| 'GUILD_TEXT'
557-
| 'GUILD_VOICE'
558-
| 'GUILD_NEWS'
559-
| 'GUILD_NEWS_THREAD'
560-
| 'GUILD_PUBLIC_THREAD'
561-
| 'GUILD_PRIVATE_THREAD'
562-
| 'GUILD_ANY';
563-
564-
/**
565-
* The allowed values for {@link CommandOptions.runIn}.
566-
* @since 4.7.0
567-
*/
568-
export type CommandRunInUnion =
569-
| ChannelType
570-
| Command.RunInTypes
571-
| CommandOptionsRunTypeEnum
572-
| readonly (ChannelType | Command.RunInTypes | CommandOptionsRunTypeEnum)[]
573-
| Nullish;
574-
575-
/**
576-
* A more detailed structure for {@link CommandOptions.runIn} when you want to have a different `runIn` for each
577-
* command type.
578-
* @since 4.7.0
579-
*/
580-
export interface CommandSpecificRunIn {
581-
chatInputRun?: CommandRunInUnion;
582-
messageRun?: CommandRunInUnion;
583-
contextMenuRun?: CommandRunInUnion;
584-
}
585-
586-
/**
587-
* The allowed values for {@link Command.Options.runIn} as an enum.
588-
* @since 2.0.0
589-
*/
590-
export enum CommandOptionsRunTypeEnum {
591-
Dm = 'DM',
592-
GuildText = 'GUILD_TEXT',
593-
GuildVoice = 'GUILD_VOICE',
594-
GuildNews = 'GUILD_NEWS',
595-
GuildNewsThread = 'GUILD_NEWS_THREAD',
596-
GuildPublicThread = 'GUILD_PUBLIC_THREAD',
597-
GuildPrivateThread = 'GUILD_PRIVATE_THREAD',
598-
GuildAny = 'GUILD_ANY'
599-
}
600-
601-
/**
602-
* The available command pre-conditions.
603-
* @since 2.0.0
604-
*/
605-
export enum CommandPreConditions {
606-
Cooldown = 'Cooldown',
607-
/** @deprecated Use {@link RunIn} instead. */
608-
DirectMessageOnly = 'DMOnly',
609-
RunIn = 'RunIn',
610-
/** @deprecated Use {@link RunIn} instead. */
611-
GuildNewsOnly = 'GuildNewsOnly',
612-
/** @deprecated Use {@link RunIn} instead. */
613-
GuildNewsThreadOnly = 'GuildNewsThreadOnly',
614-
/** @deprecated Use {@link RunIn} instead. */
615-
GuildOnly = 'GuildOnly',
616-
/** @deprecated Use {@link RunIn} instead. */
617-
GuildPrivateThreadOnly = 'GuildPrivateThreadOnly',
618-
/** @deprecated Use {@link RunIn} instead. */
619-
GuildPublicThreadOnly = 'GuildPublicThreadOnly',
620-
/** @deprecated Use {@link RunIn} instead. */
621-
GuildTextOnly = 'GuildTextOnly',
622-
/** @deprecated Use {@link RunIn} instead. */
623-
GuildVoiceOnly = 'GuildVoiceOnly',
624-
/** @deprecated Use {@link RunIn} instead. */
625-
GuildThreadOnly = 'GuildThreadOnly',
626-
NotSafeForWork = 'NSFW',
627-
ClientPermissions = 'ClientPermissions',
628-
UserPermissions = 'UserPermissions'
629-
}
630-
631-
/**
632-
* The {@link Command} options.
633-
* @since 1.0.0
634-
*/
635-
export interface CommandOptions extends AliasPiece.Options, FlagStrategyOptions {
636-
/**
637-
* Whether to add aliases for commands with dashes in them
638-
* @since 1.0.0
639-
* @default false
640-
*/
641-
generateDashLessAliases?: boolean;
642-
643-
/**
644-
* Whether to add aliases for commands with underscores in them
645-
* @since 3.0.0
646-
* @default false
647-
*/
648-
generateUnderscoreLessAliases?: boolean;
649-
650-
/**
651-
* The description for the command.
652-
* @since 1.0.0
653-
* @default ''
654-
*/
655-
description?: string;
656-
657-
/**
658-
* The detailed description for the command.
659-
* @since 1.0.0
660-
* @default ''
661-
*/
662-
detailedDescription?: DetailedDescriptionCommand;
663-
664-
/**
665-
* The full category path for the command
666-
* @since 2.0.0
667-
* @default 'An array of folder names that lead back to the folder that is registered for in the commands store'
668-
* @example
669-
* ```typescript
670-
* // Given a file named `ping.js` at the path of `commands/General/ping.js`
671-
* ['General']
672-
*
673-
* // Given a file named `info.js` at the path of `commands/General/About/ping.js`
674-
* ['General', 'About']
675-
* ```
676-
*/
677-
fullCategory?: string[];
678-
679-
/**
680-
* The {@link Precondition}s to be run, accepts an array of their names.
681-
* @seealso {@link PreconditionContainerArray}
682-
* @since 1.0.0
683-
* @default []
684-
*/
685-
preconditions?: readonly PreconditionEntryResolvable[];
686-
687-
/**
688-
* The quotes accepted by this command, pass `[]` to disable them.
689-
* @since 1.0.0
690-
* @default
691-
* [
692-
* ['"', '"'], // Double quotes
693-
* ['“', '”'], // Fancy quotes (on iOS)
694-
* ['「', '」'] // Corner brackets (CJK)
695-
* ['«', '»'] // French quotes (guillemets)
696-
* ]
697-
*/
698-
quotes?: [string, string][];
699-
700-
/**
701-
* Sets whether the command should be treated as NSFW. If set to true, the `NSFW` precondition will be added to the list.
702-
* @since 2.0.0
703-
* @default false
704-
*/
705-
nsfw?: boolean;
706-
707-
/**
708-
* The amount of entries the cooldown can have before filling up, if set to a non-zero value alongside {@link Command.Options.cooldownDelay}, the `Cooldown` precondition will be added to the list.
709-
* @since 2.0.0
710-
* @default 1
711-
*/
712-
cooldownLimit?: number;
713-
714-
/**
715-
* The time in milliseconds for the cooldown entries to reset, if set to a non-zero value alongside {@link Command.Options.cooldownLimit}, the `Cooldown` precondition will be added to the list.
716-
* @since 2.0.0
717-
* @default 0
718-
*/
719-
cooldownDelay?: number;
720-
721-
/**
722-
* The scope of the cooldown entries.
723-
* @since 2.0.0
724-
* @default BucketScope.User
725-
*/
726-
cooldownScope?: BucketScope;
727-
728-
/**
729-
* The users that are exempt from the Cooldown precondition.
730-
* Use this to filter out someone like a bot owner
731-
* @since 2.0.0
732-
* @default undefined
733-
*/
734-
cooldownFilteredUsers?: Snowflake[];
735-
736-
/**
737-
* The required permissions for the client.
738-
* @since 2.0.0
739-
* @default 0
740-
*/
741-
requiredClientPermissions?: PermissionResolvable;
742-
743-
/**
744-
* The required permissions for the user.
745-
* @since 2.0.0
746-
* @default 0
747-
*/
748-
requiredUserPermissions?: PermissionResolvable;
749-
750-
/**
751-
* The channels the command should run in. If set to `null`, no precondition entry will be added.
752-
* Some optimizations are applied when given an array to reduce the amount of preconditions run
753-
* (e.g. `'GUILD_TEXT'` and `'GUILD_NEWS'` becomes `'GUILD_ANY'`, and if both `'DM'` and `'GUILD_ANY'` are defined,
754-
* then no precondition entry is added as it runs in all channels).
755-
*
756-
* This can be both {@link CommandRunInUnion} which will have the same precondition apply to all the types of commands,
757-
* or you can use {@link CommandSpecificRunIn} to apply different preconditions to different types of commands.
758-
* @since 2.0.0
759-
* @default null
760-
*/
761-
runIn?: CommandRunInUnion | CommandSpecificRunIn;
762-
763-
/**
764-
* If {@link SapphireClient.typing} is true, this option will override it.
765-
* Otherwise, this option has no effect - you may call {@link Channel#sendTyping}` in the run method if you want specific commands to display the typing status.
766-
* @default true
767-
*/
768-
typing?: boolean;
769-
}
770-
771-
export interface MessageCommandContext extends Record<PropertyKey, unknown> {
772-
/**
773-
* The prefix used to run this command.
774-
*
775-
* This is a string for the mention and default prefix, and a RegExp for the `regexPrefix`.
776-
*/
777-
prefix: string | RegExp;
778-
/**
779-
* The alias used to run this command.
780-
*/
781-
commandName: string;
782-
/**
783-
* The matched prefix, this will always be the same as {@link MessageCommand.RunContext.prefix} if it was a string, otherwise it is
784-
* the result of doing `prefix.exec(content)[0]`.
785-
*/
786-
commandPrefix: string;
787-
}
788-
789-
export interface ChatInputCommandContext extends Record<PropertyKey, unknown> {
790-
/**
791-
* The name of the command.
792-
*/
793-
commandName: string;
794-
/**
795-
* The id of the command.
796-
*/
797-
commandId: string;
798-
}
799-
800-
export interface ContextMenuCommandContext extends Record<PropertyKey, unknown> {
801-
/**
802-
* The name of the command.
803-
*/
804-
commandName: string;
805-
/**
806-
* The id of the command.
807-
*/
808-
commandId: string;
809-
}
810-
811-
export interface AutocompleteCommandContext extends Record<PropertyKey, unknown> {
812-
/**
813-
* The name of the command.
814-
*/
815-
commandName: string;
816-
/**
817-
* The id of the command.
818-
*/
819-
commandId: string;
820-
}
821-
822-
export interface CommandJSON extends AliasPieceJSON {
823-
description: string;
824-
detailedDescription: DetailedDescriptionCommand;
825-
category: string | null;
826-
}
827-
828513
export namespace Command {
829514
export type Options = CommandOptions;
830515
export type JSON = CommandJSON;
@@ -840,7 +525,3 @@ export namespace Command {
840525
import('discord.js').AutocompleteInteraction<Cached>;
841526
export type Registry = ApplicationCommandRegistry;
842527
}
843-
844-
export type DetailedDescriptionCommand = string | DetailedDescriptionCommandObject;
845-
846-
export interface DetailedDescriptionCommandObject extends NonNullObject {}

‎src/lib/structures/Precondition.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import type {
1313
import type { CooldownPreconditionContext } from '../../preconditions/Cooldown';
1414
import { PreconditionError } from '../errors/PreconditionError';
1515
import type { UserError } from '../errors/UserError';
16-
import type { ChatInputCommand, ContextMenuCommand, MessageCommand } from './Command';
16+
import type { ChatInputCommand, ContextMenuCommand, MessageCommand } from '../types/CommandTypes';
1717
import type { PreconditionStore } from './PreconditionStore';
1818

1919
export type PreconditionResult = Awaitable<Result<unknown, UserError>>;

‎src/lib/structures/PreconditionStore.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { Store } from '@sapphire/pieces';
22
import { Result } from '@sapphire/result';
33
import type { ChatInputCommandInteraction, ContextMenuCommandInteraction, Message } from 'discord.js';
44
import { Identifiers } from '../errors/Identifiers';
5-
import type { ChatInputCommand, ContextMenuCommand, MessageCommand } from './Command';
5+
import type { ChatInputCommand, ContextMenuCommand, MessageCommand } from '../types/CommandTypes';
66
import { Precondition, type AsyncPreconditionResult } from './Precondition';
77

88
export class PreconditionStore extends Store<Precondition> {

‎src/lib/types/CommandTypes.ts

+299
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,299 @@
1+
import { AliasPiece, type AliasPieceJSON } from '@sapphire/pieces';
2+
import { type NonNullObject, type Nullish } from '@sapphire/utilities';
3+
import {
4+
ChannelType,
5+
ChatInputCommandInteraction,
6+
ContextMenuCommandInteraction,
7+
type AutocompleteInteraction,
8+
type PermissionResolvable,
9+
type Snowflake
10+
} from 'discord.js';
11+
import type { Command } from '../structures/Command';
12+
import type { ApplicationCommandRegistry } from '../utils/application-commands/ApplicationCommandRegistry';
13+
import { PreconditionContainerArray, type PreconditionEntryResolvable } from '../utils/preconditions/PreconditionContainerArray';
14+
import { type FlagStrategyOptions } from '../utils/strategies/FlagUnorderedStrategy';
15+
import { BucketScope, CommandOptionsRunTypeEnum } from './Enums';
16+
17+
export type DetailedDescriptionCommand = string | DetailedDescriptionCommandObject;
18+
19+
export interface DetailedDescriptionCommandObject extends NonNullObject {}
20+
21+
/**
22+
* The allowed values for {@link CommandOptions.runIn}.
23+
* @remark It is discouraged to use this type, we recommend using {@link CommandOptionsRunTypeEnum} instead.
24+
* @since 2.0.0
25+
*/
26+
export type CommandOptionsRunType =
27+
| 'DM'
28+
| 'GUILD_TEXT'
29+
| 'GUILD_VOICE'
30+
| 'GUILD_NEWS'
31+
| 'GUILD_NEWS_THREAD'
32+
| 'GUILD_PUBLIC_THREAD'
33+
| 'GUILD_PRIVATE_THREAD'
34+
| 'GUILD_ANY';
35+
36+
/**
37+
* The allowed values for {@link CommandOptions.runIn}.
38+
* @since 4.7.0
39+
*/
40+
export type CommandRunInUnion =
41+
| ChannelType
42+
| Command.RunInTypes
43+
| CommandOptionsRunTypeEnum
44+
| readonly (ChannelType | Command.RunInTypes | CommandOptionsRunTypeEnum)[]
45+
| Nullish;
46+
47+
/**
48+
* A more detailed structure for {@link CommandOptions.runIn} when you want to have a different `runIn` for each
49+
* command type.
50+
* @since 4.7.0
51+
*/
52+
export interface CommandSpecificRunIn {
53+
chatInputRun?: CommandRunInUnion;
54+
messageRun?: CommandRunInUnion;
55+
contextMenuRun?: CommandRunInUnion;
56+
}
57+
58+
/**
59+
* The {@link Command} options.
60+
* @since 1.0.0
61+
*/
62+
export interface CommandOptions extends AliasPiece.Options, FlagStrategyOptions {
63+
/**
64+
* Whether to add aliases for commands with dashes in them
65+
* @since 1.0.0
66+
* @default false
67+
*/
68+
generateDashLessAliases?: boolean;
69+
70+
/**
71+
* Whether to add aliases for commands with underscores in them
72+
* @since 3.0.0
73+
* @default false
74+
*/
75+
generateUnderscoreLessAliases?: boolean;
76+
77+
/**
78+
* The description for the command.
79+
* @since 1.0.0
80+
* @default ''
81+
*/
82+
description?: string;
83+
84+
/**
85+
* The detailed description for the command.
86+
* @since 1.0.0
87+
* @default ''
88+
*/
89+
detailedDescription?: DetailedDescriptionCommand;
90+
91+
/**
92+
* The full category path for the command
93+
* @since 2.0.0
94+
* @default 'An array of folder names that lead back to the folder that is registered for in the commands store'
95+
* @example
96+
* ```typescript
97+
* // Given a file named `ping.js` at the path of `commands/General/ping.js`
98+
* ['General']
99+
*
100+
* // Given a file named `info.js` at the path of `commands/General/About/ping.js`
101+
* ['General', 'About']
102+
* ```
103+
*/
104+
fullCategory?: string[];
105+
106+
/**
107+
* The {@link Precondition}s to be run, accepts an array of their names.
108+
* @seealso {@link PreconditionContainerArray}
109+
* @since 1.0.0
110+
* @default []
111+
*/
112+
preconditions?: readonly PreconditionEntryResolvable[];
113+
114+
/**
115+
* The quotes accepted by this command, pass `[]` to disable them.
116+
* @since 1.0.0
117+
* @default
118+
* [
119+
* ['"', '"'], // Double quotes
120+
* ['“', '”'], // Fancy quotes (on iOS)
121+
* ['「', '」'] // Corner brackets (CJK)
122+
* ['«', '»'] // French quotes (guillemets)
123+
* ]
124+
*/
125+
quotes?: [string, string][];
126+
127+
/**
128+
* Sets whether the command should be treated as NSFW. If set to true, the `NSFW` precondition will be added to the list.
129+
* @since 2.0.0
130+
* @default false
131+
*/
132+
nsfw?: boolean;
133+
134+
/**
135+
* The amount of entries the cooldown can have before filling up, if set to a non-zero value alongside {@link CommandOptions.cooldownDelay}, the `Cooldown` precondition will be added to the list.
136+
* @since 2.0.0
137+
* @default 1
138+
*/
139+
cooldownLimit?: number;
140+
141+
/**
142+
* The time in milliseconds for the cooldown entries to reset, if set to a non-zero value alongside {@link CommandOptions.cooldownLimit}, the `Cooldown` precondition will be added to the list.
143+
* @since 2.0.0
144+
* @default 0
145+
*/
146+
cooldownDelay?: number;
147+
148+
/**
149+
* The scope of the cooldown entries.
150+
* @since 2.0.0
151+
* @default BucketScope.User
152+
*/
153+
cooldownScope?: BucketScope;
154+
155+
/**
156+
* The users that are exempt from the Cooldown precondition.
157+
* Use this to filter out someone like a bot owner
158+
* @since 2.0.0
159+
* @default undefined
160+
*/
161+
cooldownFilteredUsers?: Snowflake[];
162+
163+
/**
164+
* The required permissions for the client.
165+
* @since 2.0.0
166+
* @default 0
167+
*/
168+
requiredClientPermissions?: PermissionResolvable;
169+
170+
/**
171+
* The required permissions for the user.
172+
* @since 2.0.0
173+
* @default 0
174+
*/
175+
requiredUserPermissions?: PermissionResolvable;
176+
177+
/**
178+
* The channels the command should run in. If set to `null`, no precondition entry will be added.
179+
* Some optimizations are applied when given an array to reduce the amount of preconditions run
180+
* (e.g. `'GUILD_TEXT'` and `'GUILD_NEWS'` becomes `'GUILD_ANY'`, and if both `'DM'` and `'GUILD_ANY'` are defined,
181+
* then no precondition entry is added as it runs in all channels).
182+
*
183+
* This can be both {@link CommandRunInUnion} which will have the same precondition apply to all the types of commands,
184+
* or you can use {@link CommandSpecificRunIn} to apply different preconditions to different types of commands.
185+
* @since 2.0.0
186+
* @default null
187+
*/
188+
runIn?: CommandRunInUnion | CommandSpecificRunIn;
189+
190+
/**
191+
* If {@link SapphireClient.typing} is true, this option will override it.
192+
* Otherwise, this option has no effect - you may call {@link Channel#sendTyping}` in the run method if you want specific commands to display the typing status.
193+
* @default true
194+
*/
195+
typing?: boolean;
196+
}
197+
198+
export interface MessageCommandContext extends Record<PropertyKey, unknown> {
199+
/**
200+
* The prefix used to run this command.
201+
*
202+
* This is a string for the mention and default prefix, and a RegExp for the `regexPrefix`.
203+
*/
204+
prefix: string | RegExp;
205+
/**
206+
* The alias used to run this command.
207+
*/
208+
commandName: string;
209+
/**
210+
* The matched prefix, this will always be the same as {@link MessageCommand.RunContext.prefix} if it was a string, otherwise it is
211+
* the result of doing `prefix.exec(content)[0]`.
212+
*/
213+
commandPrefix: string;
214+
}
215+
216+
export interface ChatInputCommandContext extends Record<PropertyKey, unknown> {
217+
/**
218+
* The name of the command.
219+
*/
220+
commandName: string;
221+
/**
222+
* The id of the command.
223+
*/
224+
commandId: string;
225+
}
226+
227+
export interface ContextMenuCommandContext extends Record<PropertyKey, unknown> {
228+
/**
229+
* The name of the command.
230+
*/
231+
commandName: string;
232+
/**
233+
* The id of the command.
234+
*/
235+
commandId: string;
236+
}
237+
238+
export interface AutocompleteCommandContext extends Record<PropertyKey, unknown> {
239+
/**
240+
* The name of the command.
241+
*/
242+
commandName: string;
243+
/**
244+
* The id of the command.
245+
*/
246+
commandId: string;
247+
}
248+
249+
export interface CommandJSON extends AliasPieceJSON {
250+
description: string;
251+
detailedDescription: DetailedDescriptionCommand;
252+
category: string | null;
253+
}
254+
255+
export type AutocompleteCommand = Command & Required<Pick<Command, 'autocompleteRun'>>;
256+
257+
export namespace AutocompleteCommand {
258+
export type Options = CommandOptions;
259+
export type JSON = CommandJSON;
260+
export type Context = AliasPiece.Context;
261+
export type RunInTypes = CommandOptionsRunType;
262+
export type RunContext = AutocompleteCommandContext;
263+
export type Interaction<Cached extends import('discord.js').CacheType = import('discord.js').CacheType> = AutocompleteInteraction<Cached>;
264+
export type Registry = ApplicationCommandRegistry;
265+
}
266+
267+
export type ContextMenuCommand = Command & Required<Pick<Command, 'contextMenuRun'>>;
268+
269+
export namespace ContextMenuCommand {
270+
export type Options = CommandOptions;
271+
export type JSON = CommandJSON;
272+
export type Context = AliasPiece.Context;
273+
export type RunInTypes = CommandOptionsRunType;
274+
export type RunContext = ContextMenuCommandContext;
275+
export type Interaction<Cached extends import('discord.js').CacheType = import('discord.js').CacheType> = ContextMenuCommandInteraction<Cached>;
276+
export type Registry = ApplicationCommandRegistry;
277+
}
278+
279+
export type MessageCommand = Command & Required<Pick<Command, 'messageRun'>>;
280+
281+
export namespace MessageCommand {
282+
export type Options = CommandOptions;
283+
export type JSON = CommandJSON;
284+
export type Context = AliasPiece.Context;
285+
export type RunInTypes = CommandOptionsRunType;
286+
export type RunContext = MessageCommandContext;
287+
}
288+
289+
export type ChatInputCommand = Command & Required<Pick<Command, 'chatInputRun'>>;
290+
291+
export namespace ChatInputCommand {
292+
export type Options = CommandOptions;
293+
export type JSON = CommandJSON;
294+
export type Context = AliasPiece.Context;
295+
export type RunInTypes = CommandOptionsRunType;
296+
export type RunContext = ChatInputCommandContext;
297+
export type Interaction<Cached extends import('discord.js').CacheType = import('discord.js').CacheType> = ChatInputCommandInteraction<Cached>;
298+
export type Registry = ApplicationCommandRegistry;
299+
}

‎src/lib/types/Enums.ts

+45
Original file line numberDiff line numberDiff line change
@@ -62,3 +62,48 @@ export enum InternalRegistryAPIType {
6262
ChatInput,
6363
ContextMenu
6464
}
65+
66+
/**
67+
* The allowed values for {@link CommandOptions.runIn} as an enum.
68+
* @since 2.0.0
69+
*/
70+
export enum CommandOptionsRunTypeEnum {
71+
Dm = 'DM',
72+
GuildText = 'GUILD_TEXT',
73+
GuildVoice = 'GUILD_VOICE',
74+
GuildNews = 'GUILD_NEWS',
75+
GuildNewsThread = 'GUILD_NEWS_THREAD',
76+
GuildPublicThread = 'GUILD_PUBLIC_THREAD',
77+
GuildPrivateThread = 'GUILD_PRIVATE_THREAD',
78+
GuildAny = 'GUILD_ANY'
79+
}
80+
81+
/**
82+
* The available command pre-conditions.
83+
* @since 2.0.0
84+
*/
85+
export enum CommandPreConditions {
86+
Cooldown = 'Cooldown',
87+
/** @deprecated Use {@link RunIn} instead. */
88+
DirectMessageOnly = 'DMOnly',
89+
RunIn = 'RunIn',
90+
/** @deprecated Use {@link RunIn} instead. */
91+
GuildNewsOnly = 'GuildNewsOnly',
92+
/** @deprecated Use {@link RunIn} instead. */
93+
GuildNewsThreadOnly = 'GuildNewsThreadOnly',
94+
/** @deprecated Use {@link RunIn} instead. */
95+
GuildOnly = 'GuildOnly',
96+
/** @deprecated Use {@link RunIn} instead. */
97+
GuildPrivateThreadOnly = 'GuildPrivateThreadOnly',
98+
/** @deprecated Use {@link RunIn} instead. */
99+
GuildPublicThreadOnly = 'GuildPublicThreadOnly',
100+
/** @deprecated Use {@link RunIn} instead. */
101+
GuildTextOnly = 'GuildTextOnly',
102+
/** @deprecated Use {@link RunIn} instead. */
103+
GuildVoiceOnly = 'GuildVoiceOnly',
104+
/** @deprecated Use {@link RunIn} instead. */
105+
GuildThreadOnly = 'GuildThreadOnly',
106+
NotSafeForWork = 'NSFW',
107+
ClientPermissions = 'ClientPermissions',
108+
UserPermissions = 'UserPermissions'
109+
}

‎src/lib/types/Events.ts

+4-4
Original file line numberDiff line numberDiff line change
@@ -9,18 +9,18 @@ import {
99
type Message
1010
} from 'discord.js';
1111
import type { UserError } from '../errors/UserError';
12+
import type { Command } from '../structures/Command';
13+
import type { InteractionHandler } from '../structures/InteractionHandler';
14+
import type { Listener } from '../structures/Listener';
1215
import type {
1316
AutocompleteCommand,
1417
AutocompleteCommandContext,
1518
ChatInputCommand,
1619
ChatInputCommandContext,
17-
Command,
1820
ContextMenuCommand,
1921
ContextMenuCommandContext,
2022
MessageCommand
21-
} from '../structures/Command';
22-
import type { InteractionHandler } from '../structures/InteractionHandler';
23-
import type { Listener } from '../structures/Listener';
23+
} from '../types/CommandTypes';
2424
import type { ApplicationCommandRegistry } from '../utils/application-commands/ApplicationCommandRegistry';
2525
import type { PluginHook } from './Enums';
2626

‎src/lib/utils/preconditions/PreconditionContainerArray.ts

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
11
import { Collection, type ChatInputCommandInteraction, type ContextMenuCommandInteraction, type Message } from 'discord.js';
2-
import type { ChatInputCommand, ContextMenuCommand, MessageCommand } from '../../structures/Command';
32
import type { PreconditionContext, PreconditionKeys, SimplePreconditionKeys } from '../../structures/Precondition';
4-
import type { IPreconditionCondition } from './conditions/IPreconditionCondition';
5-
import { PreconditionConditionAnd } from './conditions/PreconditionConditionAnd';
6-
import { PreconditionConditionOr } from './conditions/PreconditionConditionOr';
3+
import type { ChatInputCommand, ContextMenuCommand, MessageCommand } from '../../types/CommandTypes';
74
import type { IPreconditionContainer, PreconditionContainerReturn } from './IPreconditionContainer';
85
import {
96
PreconditionContainerSingle,
107
type PreconditionSingleResolvable,
118
type PreconditionSingleResolvableDetails,
129
type SimplePreconditionSingleResolvableDetails
1310
} from './PreconditionContainerSingle';
11+
import type { IPreconditionCondition } from './conditions/IPreconditionCondition';
12+
import { PreconditionConditionAnd } from './conditions/PreconditionConditionAnd';
13+
import { PreconditionConditionOr } from './conditions/PreconditionConditionOr';
1414

1515
/**
1616
* The run mode for a {@link PreconditionContainerArray}.

‎src/lib/utils/preconditions/PreconditionContainerSingle.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@ import { err } from '@sapphire/result';
33
import type { ChatInputCommandInteraction, ContextMenuCommandInteraction, Message } from 'discord.js';
44
import { Identifiers } from '../../errors/Identifiers';
55
import { UserError } from '../../errors/UserError';
6-
import type { ChatInputCommand, ContextMenuCommand, MessageCommand } from '../../structures/Command';
76
import type { Precondition, PreconditionContext, PreconditionKeys, Preconditions, SimplePreconditionKeys } from '../../structures/Precondition';
7+
import type { ChatInputCommand, ContextMenuCommand, MessageCommand } from '../../types/CommandTypes';
88
import type { IPreconditionContainer } from './IPreconditionContainer';
99

1010
/**

‎src/lib/utils/preconditions/conditions/IPreconditionCondition.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import type { ChatInputCommandInteraction, ContextMenuCommandInteraction, Message } from 'discord.js';
2-
import type { ChatInputCommand, ContextMenuCommand, MessageCommand } from '../../../structures/Command';
32
import type { PreconditionContext } from '../../../structures/Precondition';
3+
import type { ChatInputCommand, ContextMenuCommand, MessageCommand } from '../../../types/CommandTypes';
44
import type { IPreconditionContainer, PreconditionContainerReturn } from '../IPreconditionContainer';
55

66
/**

‎src/listeners/application-commands/CorePossibleAutocompleteInteraction.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import type { AutocompleteInteraction } from 'discord.js';
2-
import type { AutocompleteCommand } from '../../lib/structures/Command';
32
import { Listener } from '../../lib/structures/Listener';
3+
import type { AutocompleteCommand } from '../../lib/types/CommandTypes';
44
import { Events } from '../../lib/types/Events';
55

66
export class CoreListener extends Listener<typeof Events.PossibleAutocompleteInteraction> {

‎src/listeners/application-commands/chat-input/CorePossibleChatInputCommand.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import type { ChatInputCommandInteraction } from 'discord.js';
2-
import type { ChatInputCommand } from '../../../lib/structures/Command';
32
import { Listener } from '../../../lib/structures/Listener';
3+
import type { ChatInputCommand } from '../../../lib/types/CommandTypes';
44
import { Events } from '../../../lib/types/Events';
55

66
export class CoreListener extends Listener<typeof Events.PossibleChatInputCommand> {

‎src/listeners/application-commands/context-menu/CorePossibleContextMenuCommand.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import type { ContextMenuCommandInteraction } from 'discord.js';
2-
import type { ContextMenuCommand } from '../../../lib/structures/Command';
32
import { Listener } from '../../../lib/structures/Listener';
3+
import type { ContextMenuCommand } from '../../../lib/types/CommandTypes';
44
import { Events } from '../../../lib/types/Events';
55

66
export class CoreListener extends Listener<typeof Events.PossibleContextMenuCommand> {

‎src/optional-listeners/message-command-listeners/CoreMessageCommandTyping.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { isStageChannel } from '@sapphire/discord.js-utilities';
22
import type { Message } from 'discord.js';
3-
import type { MessageCommand } from '../../lib/structures/Command';
43
import { Listener } from '../../lib/structures/Listener';
4+
import type { MessageCommand } from '../../lib/types/CommandTypes';
55
import { Events, type MessageCommandRunPayload } from '../../lib/types/Events';
66

77
export class CoreListener extends Listener<typeof Events.MessageCommandRun> {

‎src/optional-listeners/message-command-listeners/CorePrefixedMessage.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import type { Message } from 'discord.js';
2-
import type { MessageCommand } from '../../lib/structures/Command';
32
import { Listener } from '../../lib/structures/Listener';
3+
import type { MessageCommand } from '../../lib/types/CommandTypes';
44
import { Events } from '../../lib/types/Events';
55

66
export class CoreListener extends Listener<typeof Events.PrefixedMessage> {

‎src/preconditions/RunIn.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import type { ChatInputCommandInteraction, ContextMenuCommandInteraction, Message } from 'discord.js';
22
import { Identifiers } from '../lib/errors/Identifiers';
3-
import { Command, type ChatInputCommand, type ContextMenuCommand, type MessageCommand } from '../lib/structures/Command';
3+
import { Command } from '../lib/structures/Command';
44
import { AllFlowsPrecondition, type Preconditions } from '../lib/structures/Precondition';
5+
import type { ChatInputCommand, ContextMenuCommand, MessageCommand } from '../lib/types/CommandTypes';
56

67
export interface RunInPreconditionContext extends AllFlowsPrecondition.Context {
78
types?: Preconditions['RunIn']['types'];

0 commit comments

Comments
 (0)
Please sign in to comment.