1
1
import { ArgumentStream , Lexer , Parser , type IUnorderedStrategy } from '@sapphire/lexure' ;
2
2
import { AliasPiece , type AliasPieceJSON } from '@sapphire/pieces' ;
3
- import { isNullish , type Awaitable , type NonNullObject } from '@sapphire/utilities' ;
3
+ import { isNullish , isObject , type Awaitable , type NonNullObject , type Nullish } from '@sapphire/utilities' ;
4
4
import {
5
5
ChannelType ,
6
6
ChatInputCommandInteraction ,
@@ -23,6 +23,14 @@ import type { CommandStore } from './CommandStore';
23
23
24
24
const ChannelTypes = Object . values ( ChannelType ) . filter ( ( type ) => typeof type === 'number' ) as readonly ChannelType [ ] ;
25
25
const GuildChannelTypes = ChannelTypes . filter ( ( type ) => type !== ChannelType . DM && type !== ChannelType . GroupDM ) as readonly ChannelType [ ] ;
26
+ function runInTypeIsSpecificsObject ( types : Command . Options [ 'runIn' ] ) : types is CommandSpecificRunIn {
27
+ if ( ! isObject ( types ) ) {
28
+ return false ;
29
+ }
30
+
31
+ const specificTypes = types as CommandSpecificRunIn ;
32
+ return Boolean ( specificTypes . chatInputRun || specificTypes . messageRun || specificTypes . contextMenuRun ) ;
33
+ }
26
34
27
35
export class Command < PreParseReturn = Args , O extends Command . Options = Command . Options > extends AliasPiece < O > {
28
36
/**
@@ -361,9 +369,31 @@ export class Command<PreParseReturn = Args, O extends Command.Options = Command.
361
369
* @param options The command options given from the constructor.
362
370
*/
363
371
protected parseConstructorPreConditionsRunIn ( options : Command . Options ) {
364
- const types = this . resolveConstructorPreConditionsRunType ( options . runIn ) ;
365
- if ( types !== null ) {
366
- this . preconditions . append ( { name : CommandPreConditions . RunIn , context : { types } } ) ;
372
+ // Early return if there's no runIn option:
373
+ if ( isNullish ( options . runIn ) ) return ;
374
+
375
+ if ( runInTypeIsSpecificsObject ( options . runIn ) ) {
376
+ const messageRunTypes = this . resolveConstructorPreConditionsRunType ( options . runIn . messageRun ) ;
377
+ const chatInputRunTypes = this . resolveConstructorPreConditionsRunType ( options . runIn . chatInputRun ) ;
378
+ const contextMenuRunTypes = this . resolveConstructorPreConditionsRunType ( options . runIn . contextMenuRun ) ;
379
+
380
+ if ( messageRunTypes !== null || chatInputRunTypes !== null || contextMenuRunTypes !== null ) {
381
+ this . preconditions . append ( {
382
+ name : CommandPreConditions . RunIn ,
383
+ context : {
384
+ types : {
385
+ messageRun : messageRunTypes ?? [ ] ,
386
+ chatInputRun : chatInputRunTypes ?? [ ] ,
387
+ contextMenuRun : contextMenuRunTypes ?? [ ]
388
+ }
389
+ }
390
+ } ) ;
391
+ }
392
+ } else {
393
+ const types = this . resolveConstructorPreConditionsRunType ( options . runIn ) ;
394
+ if ( types !== null ) {
395
+ this . preconditions . append ( { name : CommandPreConditions . RunIn , context : { types } } ) ;
396
+ }
367
397
}
368
398
}
369
399
@@ -421,7 +451,7 @@ export class Command<PreParseReturn = Args, O extends Command.Options = Command.
421
451
* @param types The types to resolve.
422
452
* @returns The resolved types, or `null` if no types were resolved.
423
453
*/
424
- protected resolveConstructorPreConditionsRunType ( types : Command . Options [ 'runIn' ] ) : readonly ChannelType [ ] | null {
454
+ protected resolveConstructorPreConditionsRunType ( types : CommandRunInUnion ) : readonly ChannelType [ ] | null {
425
455
if ( isNullish ( types ) ) return null ;
426
456
if ( typeof types === 'number' ) return [ types ] ;
427
457
if ( typeof types === 'string' ) {
@@ -530,6 +560,28 @@ export type CommandOptionsRunType =
530
560
| 'GUILD_PRIVATE_THREAD'
531
561
| 'GUILD_ANY' ;
532
562
563
+ /**
564
+ * The allowed values for {@link CommandOptions.runIn}.
565
+ * @since 4.7.0
566
+ */
567
+ export type CommandRunInUnion =
568
+ | ChannelType
569
+ | Command . RunInTypes
570
+ | CommandOptionsRunTypeEnum
571
+ | readonly ( ChannelType | Command . RunInTypes | CommandOptionsRunTypeEnum ) [ ]
572
+ | Nullish ;
573
+
574
+ /**
575
+ * A more detailed structure for {@link CommandOptions.runIn} when you want to have a different `runIn` for each
576
+ * command type.
577
+ * @since 4.7.0
578
+ */
579
+ export interface CommandSpecificRunIn {
580
+ chatInputRun ?: CommandRunInUnion ;
581
+ messageRun ?: CommandRunInUnion ;
582
+ contextMenuRun ?: CommandRunInUnion ;
583
+ }
584
+
533
585
/**
534
586
* The allowed values for {@link Command.Options.runIn} as an enum.
535
587
* @since 2.0.0
@@ -695,16 +747,17 @@ export interface CommandOptions extends AliasPiece.Options, FlagStrategyOptions
695
747
requiredUserPermissions ?: PermissionResolvable ;
696
748
697
749
/**
698
- * The channels the command should run in. If set to `null`, no precondition entry will be added. Some optimizations are applied when given an array to reduce the amount of preconditions run (e.g. `'GUILD_TEXT'` and `'GUILD_NEWS'` becomes `'GUILD_ANY'`, and if both `'DM'` and `'GUILD_ANY'` are defined, then no precondition entry is added as it runs in all channels).
750
+ * The channels the command should run in. If set to `null`, no precondition entry will be added.
751
+ * Some optimizations are applied when given an array to reduce the amount of preconditions run
752
+ * (e.g. `'GUILD_TEXT'` and `'GUILD_NEWS'` becomes `'GUILD_ANY'`, and if both `'DM'` and `'GUILD_ANY'` are defined,
753
+ * then no precondition entry is added as it runs in all channels).
754
+ *
755
+ * This can be both {@link CommandRunInUnion} which will have the same precondition apply to all the types of commands,
756
+ * or you can use {@link CommandSpecificRunIn} to apply different preconditions to different types of commands.
699
757
* @since 2.0.0
700
758
* @default null
701
759
*/
702
- runIn ?:
703
- | ChannelType
704
- | Command . RunInTypes
705
- | CommandOptionsRunTypeEnum
706
- | readonly ( ChannelType | Command . RunInTypes | CommandOptionsRunTypeEnum ) [ ]
707
- | null ;
760
+ runIn ?: CommandRunInUnion | CommandSpecificRunIn ;
708
761
709
762
/**
710
763
* If {@link SapphireClient.typing} is true, this option will override it.
@@ -776,6 +829,8 @@ export namespace Command {
776
829
export type JSON = CommandJSON ;
777
830
export type Context = AliasPiece . Context ;
778
831
export type RunInTypes = CommandOptionsRunType ;
832
+ export type RunInUnion = CommandRunInUnion ;
833
+ export type SpecificRunIn = CommandSpecificRunIn ;
779
834
export type ChatInputCommandInteraction < Cached extends import ( 'discord.js' ) . CacheType = import ( 'discord.js' ) . CacheType > =
780
835
import ( 'discord.js' ) . ChatInputCommandInteraction < Cached > ;
781
836
export type ContextMenuCommandInteraction < Cached extends import ( 'discord.js' ) . CacheType = import ( 'discord.js' ) . CacheType > =
0 commit comments