seedcord 0.4.3 → 0.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.cts CHANGED
@@ -1,13 +1,16 @@
1
1
  import { Logger, CoordinatedShutdown, CoordinatedStartup, StartupPhase } from '@seedcord/services';
2
2
  export * from '@seedcord/services';
3
- import { ClientOptions, Guild, User, SlashCommandBuilder, ContextMenuCommandBuilder, Collection, Client, ChatInputCommandInteraction, ButtonInteraction, ModalSubmitInteraction, AutocompleteInteraction, AnySelectMenuInteraction, ContextMenuCommandInteraction, ClientEvents, Events, AutocompleteFocusedOption, EmbedBuilder, ButtonBuilder, StringSelectMenuBuilder, StringSelectMenuOptionBuilder, UserSelectMenuBuilder, ChannelSelectMenuBuilder, MentionableSelectMenuBuilder, RoleSelectMenuBuilder, ModalBuilder, SlashCommandSubcommandBuilder, SlashCommandSubcommandGroupBuilder, ContainerBuilder, TextDisplayBuilder, FileBuilder, MediaGalleryBuilder, SectionBuilder, SeparatorBuilder, ActionRowBuilder, TextInputBuilder, WebhookClient } from 'discord.js';
4
- import { Nullable, Tail, TypedConstructor, ConstructorFunction } from '@seedcord/types';
3
+ import { ClientOptions, Guild, User, SlashCommandBuilder, ContextMenuCommandBuilder, Collection, Client, ChatInputCommandInteraction, ButtonInteraction, ModalSubmitInteraction, AutocompleteInteraction, AnySelectMenuInteraction, ContextMenuCommandInteraction, ClientEvents, Events, AutocompleteFocusedOption, SlashCommandSubcommandBuilder, SlashCommandSubcommandGroupBuilder, EmbedBuilder, ModalBuilder, LabelBuilder, TextInputBuilder, FileUploadBuilder, ButtonBuilder, StringSelectMenuBuilder, StringSelectMenuOptionBuilder, UserSelectMenuBuilder, ChannelSelectMenuBuilder, MentionableSelectMenuBuilder, RoleSelectMenuBuilder, ContainerBuilder, TextDisplayBuilder, FileBuilder, MediaGalleryBuilder, SectionBuilder, SeparatorBuilder, ActionRowBuilder, ColorResolvable, Interaction, Role, TextChannel, TextChannelResolvable, MessageActionRowComponentBuilder, Message, GuildMember, Snowflake, WebhookClient } from 'discord.js';
4
+ import { Nullable, Tail, TypedConstructor, TypedExclude } from '@seedcord/types';
5
5
  export * from '@seedcord/types';
6
6
  import { UUID } from 'crypto';
7
+ import { Constructor, RequireAtLeastOne } from 'type-fest';
8
+ import { UUID as UUID$1 } from 'node:crypto';
7
9
  export * from '@seedcord/utils';
8
10
 
9
11
  /**
10
12
  * Djs Interactions handlers
13
+ *
11
14
  */
12
15
  interface InteractionsConfig {
13
16
  /**
@@ -15,6 +18,10 @@ interface InteractionsConfig {
15
18
  */
16
19
  path: string;
17
20
  ignoreCustomIds?: string[];
21
+ /**
22
+ * Optional path to interaction middleware directory
23
+ */
24
+ middlewares?: string;
18
25
  }
19
26
  /**
20
27
  * Djs Events handlers
@@ -24,6 +31,10 @@ interface EventsConfig {
24
31
  * Path to dir containing event handlers.
25
32
  */
26
33
  path: string;
34
+ /**
35
+ * Optional path to event middleware directory
36
+ */
37
+ middlewares?: string;
27
38
  }
28
39
  /**
29
40
  * Djs SlashCommands and ContextMenuCommands
@@ -63,6 +74,7 @@ interface BotConfig {
63
74
  *
64
75
  * @example
65
76
  * ```ts
77
+ * // This map's values...
66
78
  * const Emojis = {
67
79
  * ThumbsUp: 'thumbsup',
68
80
  * ThumbsDown: 'thumbsdown',
@@ -71,10 +83,9 @@ interface BotConfig {
71
83
  * };
72
84
  * ```
73
85
  *
74
- * will turn into
75
- *
76
86
  * @example
77
87
  * ```ts
88
+ * // ...turn into these Discord emojis
78
89
  * const Emojis = {
79
90
  * ThumbsUp: '<:thumbsup:1872389747982323423>',
80
91
  * ThumbsDown: '<:thumbsdown:1872389747982323424>',
@@ -107,6 +118,7 @@ interface DefaultEffects {
107
118
  error: Error;
108
119
  guild: Nullable<Guild>;
109
120
  user: Nullable<User>;
121
+ metadata?: unknown;
110
122
  };
111
123
  }
112
124
  /**
@@ -167,7 +179,10 @@ declare class EffectsRegistry extends Plugin {
167
179
  emit<KeyOfEffects extends EffectKeys>(event: KeyOfEffects, data: AllEffects[KeyOfEffects]): boolean;
168
180
  }
169
181
 
170
- /** Base interface defining core Seedcord functionality */
182
+ /** Base interface defining core Seedcord functionality
183
+ *
184
+ * @internal
185
+ */
171
186
  interface BaseCore {
172
187
  readonly bot: Bot;
173
188
  readonly effects: EffectsRegistry;
@@ -219,12 +234,12 @@ declare abstract class Plugin implements Initializeable {
219
234
  }
220
235
  /**
221
236
  * Constructor type for plugins that can accept additional arguments after Core
222
- * @param TPlugin - The plugin type being constructed
237
+ * @typeParam TPlugin - The plugin type being constructed
223
238
  */
224
239
  type PluginCtor<TPlugin extends Plugin = Plugin> = new (core: Core, ...args: any[]) => TPlugin;
225
240
  /**
226
241
  * Extracts the argument types for a plugin constructor (excluding the Core parameter)
227
- * @param Ctor - The plugin constructor to extract arguments from
242
+ * @typeParam Ctor - The plugin constructor to extract arguments from
228
243
  */
229
244
  type PluginArgs<Ctor extends PluginCtor> = Tail<ConstructorParameters<Ctor>>;
230
245
  /**
@@ -300,10 +315,6 @@ declare class Bot extends Plugin {
300
315
  private readonly events;
301
316
  readonly commands: CommandRegistry;
302
317
  private readonly emojiInjector;
303
- /**
304
- * @param core - Seedcord core instance
305
- * @internal
306
- */
307
318
  constructor(core: Core);
308
319
  /**
309
320
  * Initializes Discord client and all controllers
@@ -385,6 +396,7 @@ interface Handler {
385
396
  * Should always accompany the `@Catchable` decorator. Will require the class to implement the `runChecks` method.
386
397
  *
387
398
  * @see {@link Checkable}
399
+ * @see {@link Catchable}
388
400
  */
389
401
  interface WithChecks {
390
402
  /**
@@ -396,8 +408,18 @@ interface WithChecks {
396
408
  */
397
409
  runChecks(): Promise<void>;
398
410
  }
411
+ /**
412
+ * Interface for handlers that implement pre-execution checks
413
+ *
414
+ * @internal
415
+ */
399
416
  interface HandlerWithChecks extends WithChecks, Handler {
400
417
  }
418
+ /**
419
+ * Base class for all handlers. Not meant to be used directly.
420
+ *
421
+ * @internal
422
+ */
401
423
  declare abstract class BaseHandler<ValidEvent extends ValidEventTypes> implements Handler {
402
424
  core: Core;
403
425
  protected checkable: boolean;
@@ -419,8 +441,8 @@ declare abstract class BaseHandler<ValidEvent extends ValidEventTypes> implement
419
441
  /**
420
442
  * Gets arguments parsed from interaction customId
421
443
  *
422
- * Arguments are extracted from customId using ":" and "-" separators.
423
- * For customId "accept:user123-guild456", returns ["user123", "guild456"]
444
+ * Arguments are extracted from customId using `:` and `-` separators.
445
+ * For customId `accept:user123-guild456`, returns `["user123", "guild456"]`
424
446
  */
425
447
  protected getArgs(): string[];
426
448
  /**
@@ -434,7 +456,7 @@ declare abstract class BaseHandler<ValidEvent extends ValidEventTypes> implement
434
456
  * Base class for Discord interaction handlers
435
457
  *
436
458
  * Extend this class to handle slash commands, buttons, modals, and select menus.
437
- * Use decorators like \@SlashRoute, \@ButtonRoute, etc. to define routing.
459
+ * Use decorators like `@SlashRoute`, `@ButtonRoute`, etc. to define routing.
438
460
  *
439
461
  * @typeParam Repliable - The interaction type this handler processes
440
462
  */
@@ -452,6 +474,14 @@ declare abstract class InteractionHandler<Repliable extends Repliables> extends
452
474
  declare abstract class InteractionMiddleware<Repliable extends Repliables> extends BaseHandler<Repliable> implements Handler {
453
475
  constructor(event: Repliable, core: Core, args?: string[]);
454
476
  }
477
+ /**
478
+ * Base class for Discord event middleware
479
+ *
480
+ * Middleware runs before event handlers and can modify behavior or block execution.
481
+ */
482
+ declare abstract class EventMiddleware<EventName extends keyof ClientEvents> extends BaseHandler<ClientEvents[EventName]> implements Handler {
483
+ constructor(event: ClientEvents[EventName], core: Core, args?: string[]);
484
+ }
455
485
  /**
456
486
  * Handler for Discord autocomplete interactions
457
487
  *
@@ -459,7 +489,7 @@ declare abstract class InteractionMiddleware<Repliable extends Repliables> exten
459
489
  * The focused option is automatically available via the `focused` property.
460
490
  */
461
491
  declare abstract class AutocompleteHandler extends BaseHandler<AutocompleteInteraction> implements Handler {
462
- /** The currently focused autocomplete option (Based on what you set in \@AutocompleteRoute) */
492
+ /** The currently focused autocomplete option (Based on what you set in `@AutocompleteRoute`) */
463
493
  protected readonly focused: AutocompleteFocusedOption;
464
494
  constructor(event: AutocompleteInteraction, core: Core, args?: string[]);
465
495
  }
@@ -467,7 +497,7 @@ declare abstract class AutocompleteHandler extends BaseHandler<AutocompleteInter
467
497
  * Base class for Discord client event handlers
468
498
  *
469
499
  * Extend this class to handle Discord events like messageCreate, guildMemberAdd, etc.
470
- * Use the \@EventRegisterable decorator to specify which event to listen for.
500
+ * Use the `EventRegisterable` decorator to specify which event to listen for.
471
501
  *
472
502
  * @typeParam Repliable - The Discord event type this handler processes
473
503
  */
@@ -477,12 +507,21 @@ declare abstract class EventHandler<Repliable extends keyof ClientEvents> extend
477
507
  /** Constructor type for interaction and autocomplete handlers */
478
508
  type HandlerConstructor = TypedConstructor<typeof InteractionHandler | typeof AutocompleteHandler>;
479
509
  /** Constructor type for interaction middleware */
480
- type MiddlewareConstructor = TypedConstructor<typeof InteractionMiddleware> & (new (event: Repliables, core: Core, args?: string[]) => InteractionMiddleware<Repliables>);
510
+ type InteractionMiddlewareConstructor = TypedConstructor<typeof InteractionMiddleware> & (new (event: Repliables, core: Core, args?: string[]) => InteractionMiddleware<Repliables>);
511
+ /** Constructor type for legacy interaction middleware */
512
+ type MiddlewareConstructor = InteractionMiddlewareConstructor;
513
+ /** Constructor type for event middleware */
514
+ type EventMiddlewareConstructor = TypedConstructor<typeof EventMiddleware> & (new <EventName extends keyof ClientEvents>(event: ClientEvents[EventName], core: Core, args?: string[]) => EventMiddleware<EventName>);
481
515
  /** Constructor type for autocomplete handlers */
482
516
  type AutocompleteHandlerConstructor = TypedConstructor<typeof AutocompleteHandler> & (new (event: AutocompleteInteraction, core: Core, args?: string[]) => AutocompleteHandler);
483
517
  /** Constructor type for Discord client event handlers */
484
518
  type EventHandlerConstructor = TypedConstructor<typeof EventHandler>;
485
519
 
520
+ /**
521
+ * Constructor type for handler classes.
522
+ *
523
+ * @internal
524
+ */
486
525
  type HandlerCtor = new (...args: any[]) => Handler;
487
526
  /**
488
527
  * Marks a handler class as requiring check execution.
@@ -490,12 +529,13 @@ type HandlerCtor = new (...args: any[]) => Handler;
490
529
  * Enables the runChecks() method to be called before execute()
491
530
  * for handlers that need pre-execution validation.
492
531
  *
493
- * @param ctor - The handler to mark as checkable (Do not pass this directly. Just call the decorator without a **()**)
532
+ * @typeParam TypeHandler - The type of the handler class being decorated
533
+ * @param ctor - The handler to mark as checkable (Do not pass this directly. Just call the decorator without a `()`)
494
534
  * @decorator
495
535
  * @example
496
536
  * ```typescript
497
537
  * \@Checkable
498
- * class AdminCommand extends InteractionHandler {
538
+ * class AdminCommand extends InteractionHandler implements WithChecks {
499
539
  * async runChecks() {
500
540
  * // Perform admin permission checks
501
541
  * }
@@ -508,9 +548,9 @@ declare function Checkable<TypeHandler extends HandlerCtor>(ctor: TypeHandler):
508
548
  * Configuration options for the Catchable decorator.
509
549
  */
510
550
  interface CatchableOptions {
511
- /** Whether to log errors to console (default: false) */
551
+ /** Whether to log errors to console (default: `false`) */
512
552
  log?: boolean;
513
- /** Always use followUp instead of reply/editReply (default: false) */
553
+ /** Always use followUp instead of reply/editReply (default: `false`) */
514
554
  forceFollowup?: boolean;
515
555
  }
516
556
  /**
@@ -533,9 +573,21 @@ interface CatchableOptions {
533
573
  */
534
574
  declare function Catchable(options?: CatchableOptions): (_target: RepliableInteractionHandler, _propertyKey: string, descriptor: TypedPropertyDescriptor<(...args: any[]) => Promise<void>>) => void;
535
575
 
576
+ /**
577
+ * Available Discord.js builder classes for use with BuilderComponent
578
+ *
579
+ * @internal
580
+ */
536
581
  declare const BuilderTypes: {
537
582
  command: typeof SlashCommandBuilder;
583
+ context_menu: typeof ContextMenuCommandBuilder;
584
+ subcommand: typeof SlashCommandSubcommandBuilder;
585
+ group: typeof SlashCommandSubcommandGroupBuilder;
538
586
  embed: typeof EmbedBuilder;
587
+ modal: typeof ModalBuilder;
588
+ label: typeof LabelBuilder;
589
+ text_input: typeof TextInputBuilder;
590
+ file_upload: typeof FileUploadBuilder;
539
591
  button: typeof ButtonBuilder;
540
592
  menu_string: typeof StringSelectMenuBuilder;
541
593
  menu_option_string: typeof StringSelectMenuOptionBuilder;
@@ -543,10 +595,6 @@ declare const BuilderTypes: {
543
595
  menu_channel: typeof ChannelSelectMenuBuilder;
544
596
  menu_mentionable: typeof MentionableSelectMenuBuilder;
545
597
  menu_role: typeof RoleSelectMenuBuilder;
546
- modal: typeof ModalBuilder;
547
- context_menu: typeof ContextMenuCommandBuilder;
548
- subcommand: typeof SlashCommandSubcommandBuilder;
549
- group: typeof SlashCommandSubcommandGroupBuilder;
550
598
  container: typeof ContainerBuilder;
551
599
  text_display: typeof TextDisplayBuilder;
552
600
  file: typeof FileBuilder;
@@ -554,6 +602,11 @@ declare const BuilderTypes: {
554
602
  section: typeof SectionBuilder;
555
603
  separator: typeof SeparatorBuilder;
556
604
  };
605
+ /**
606
+ * Available Discord.js action row classes for use with RowComponent
607
+ *
608
+ * @internal
609
+ */
557
610
  declare const RowTypes: {
558
611
  button: typeof ActionRowBuilder<ButtonBuilder>;
559
612
  menu_string: typeof ActionRowBuilder<StringSelectMenuBuilder>;
@@ -561,23 +614,31 @@ declare const RowTypes: {
561
614
  menu_channel: typeof ActionRowBuilder<ChannelSelectMenuBuilder>;
562
615
  menu_mentionable: typeof ActionRowBuilder<MentionableSelectMenuBuilder>;
563
616
  menu_role: typeof ActionRowBuilder<RoleSelectMenuBuilder>;
564
- modal: typeof ActionRowBuilder<ModalActionRowComponentBuilder>;
565
- };
566
- declare const ModalTypes: {
567
- text: typeof TextInputBuilder;
568
617
  };
618
+ /**
619
+ * Available Discord.js builder types for use with BuilderComponent
620
+ */
569
621
  type BuilderType = keyof typeof BuilderTypes;
622
+ /**
623
+ * @internal
624
+ */
570
625
  type InstantiatedBuilder<BuilderKey extends BuilderType> = InstanceType<(typeof BuilderTypes)[BuilderKey]>;
626
+ /**
627
+ * Available Discord.js action row types for use with RowComponent
628
+ */
571
629
  type ActionRowComponentType = keyof typeof RowTypes;
630
+ /**
631
+ * @internal
632
+ */
572
633
  type InstantiatedActionRow<RowKey extends ActionRowComponentType> = InstanceType<(typeof RowTypes)[RowKey]>;
573
- type ModalFieldTypes = keyof typeof ModalTypes;
574
- type InstantiatedModalField<ModalKey extends ModalFieldTypes> = InstanceType<(typeof ModalTypes)[ModalKey]>;
575
634
  /**
576
635
  * Base class for Discord component wrappers
577
636
  *
578
637
  * Provides common functionality for building Discord components with proper typing.
579
638
  *
580
639
  * @typeParam TComponent - The Discord.js component type being wrapped
640
+ *
641
+ * @internal
581
642
  */
582
643
  declare abstract class BaseComponent<TComponent> {
583
644
  private readonly _component;
@@ -603,7 +664,7 @@ declare abstract class BaseComponent<TComponent> {
603
664
  /**
604
665
  * Builds a customId string for interactive components
605
666
  *
606
- * Creates customIds in the format "prefix:arg1-arg2-arg3" for buttons, modals, etc.
667
+ * Creates customIds in the format `prefix:arg1-arg2-arg3` for buttons, modals, etc.
607
668
  * Arguments are joined with hyphens and separated from prefix with a colon.
608
669
  *
609
670
  * @param prefix - The route prefix that handlers will match against
@@ -621,7 +682,13 @@ declare abstract class BaseComponent<TComponent> {
621
682
  * @typeParam BuilderKey - The type of Discord.js builder being wrapped
622
683
  */
623
684
  declare abstract class BuilderComponent<BuilderKey extends BuilderType> extends BaseComponent<InstantiatedBuilder<BuilderKey>> {
624
- private readonly botColor;
685
+ /**
686
+ * Bot color for the component
687
+ * Uses the DEFAULT_BOT_COLOR environment variable or falls back to 'Default' set by Discord.js.
688
+ *
689
+ * Set DEFAULT_BOT_COLOR to a hex code in your `.env` file to customize.
690
+ */
691
+ readonly botColor: ColorResolvable;
625
692
  protected constructor(type: BuilderKey);
626
693
  get component(): InstantiatedBuilder<BuilderKey>;
627
694
  }
@@ -636,18 +703,6 @@ declare abstract class RowComponent<RowKey extends ActionRowComponentType> exten
636
703
  protected constructor(type: RowKey);
637
704
  get component(): InstantiatedActionRow<RowKey>;
638
705
  }
639
- /**
640
- * Base class for modal field components
641
- *
642
- * Wraps Discord.js modal field builders (TextInputBuilder, etc.) and
643
- * packages them in action rows for use in modals.
644
- *
645
- * @typeParam ModalKey - The type of modal field builder being wrapped
646
- */
647
- declare abstract class ModalComponent<ModalKey extends ModalFieldTypes> extends BaseComponent<InstantiatedModalField<ModalKey>> {
648
- protected constructor(type: ModalKey);
649
- get component(): InstantiatedActionRow<'modal'>;
650
- }
651
706
  /**
652
707
  * Pre-configured error embed with default styling
653
708
  *
@@ -680,24 +735,36 @@ declare abstract class CustomError extends Error {
680
735
  get emit(): boolean;
681
736
  /**
682
737
  * Sets whether this error should be emitted to logs
683
- *
684
- * @see {@link emit}
685
738
  */
686
739
  set emit(value: boolean);
687
740
  }
688
741
  /** Constructor type for custom error classes */
689
742
  type CustomErrorConstructor = new (message: string, ...args: any[]) => CustomError;
690
743
 
744
+ /**
745
+ * Metadata key for command registration information.
746
+ *
747
+ * @internal
748
+ */
691
749
  declare const CommandMetadataKey: unique symbol;
750
+ /**
751
+ * Constructor type for command classes.
752
+ *
753
+ * @internal
754
+ */
692
755
  type CommandCtor = new (...args: any[]) => BuilderComponent<'command' | 'context_menu'>;
693
756
  /**
694
757
  * Metadata for global command registration.
758
+ *
759
+ * @internal
695
760
  */
696
761
  interface GlobalMeta {
697
762
  scope: 'global';
698
763
  }
699
764
  /**
700
765
  * Metadata for guild-specific command registration.
766
+ *
767
+ * @internal
701
768
  */
702
769
  interface GuildMeta {
703
770
  scope: 'guild';
@@ -705,8 +772,16 @@ interface GuildMeta {
705
772
  }
706
773
  /**
707
774
  * Union type for command registration metadata.
775
+ *
776
+ * @internal
708
777
  */
709
778
  type CommandMeta = GlobalMeta | GuildMeta;
779
+ /**
780
+ * Type representing command registration scope.
781
+ *
782
+ * @internal
783
+ */
784
+ type CommandScope = CommandMeta['scope'];
710
785
  /**
711
786
  * Registers a command for global deployment.
712
787
  *
@@ -743,7 +818,7 @@ declare function RegisterCommand(scope: 'guild', guilds: string[]): (ctor: Comma
743
818
  * Automatically handles errors in event handlers and sends error responses
744
819
  * if the event contains a Discord message object.
745
820
  *
746
- * @param log - Whether to log errors to console (default: false)
821
+ * @param log - Whether to log errors to console (default: `false`)
747
822
  * @decorator
748
823
  * @example
749
824
  * ```typescript
@@ -759,12 +834,13 @@ declare function EventCatchable(log?: boolean): (_target: EventHandler<keyof Cli
759
834
 
760
835
  declare const EventMetadataKey: unique symbol;
761
836
  /**
762
- * Registers an event handler class with a specific Discord.js event.
837
+ * Registers an event handler class with a one or multiple Discord.js event(s).
763
838
  *
764
- * Associates the decorated class with a Discord client event for automatic
839
+ * Associates the decorated class with the mentioned Discord client event(s) for automatic
765
840
  * registration and execution when the event is emitted.
766
841
  *
767
- * @param eventName - The Discord.js event name to listen for
842
+ * @typeParam KeyofEvents - The key of the Discord.js ClientEvents to register for
843
+ * @param events - The Discord.js event name(s) to listen for
768
844
  * @decorator
769
845
  * @example
770
846
  * ```typescript
@@ -775,9 +851,24 @@ declare const EventMetadataKey: unique symbol;
775
851
  * }
776
852
  * }
777
853
  * ```
854
+ *
855
+ * @example
856
+ * ```typescript
857
+ * \@RegisterEvent([Events.MessageCreate, Events.MessageUpdate])
858
+ * class MessageHandler extends EventHandler<Events.MessageCreate | Events.MessageUpdate> {
859
+ * async execute() {
860
+ * // Handle message creation or update
861
+ * }
862
+ * }
863
+ * ```
778
864
  */
779
- declare function RegisterEvent<KeyofEvents extends keyof ClientEvents>(eventName: KeyofEvents): (constructor: ConstructorFunction) => void;
865
+ declare function RegisterEvent<KeyofEvents extends keyof ClientEvents>(events: KeyofEvents | KeyofEvents[]): (constructor: Constructor<unknown>) => void;
780
866
 
867
+ /**
868
+ * Enum defining interaction route types for decorators
869
+ *
870
+ * @internal
871
+ */
781
872
  declare enum InteractionRoutes {
782
873
  Slash = "interaction:slash",
783
874
  Button = "interaction:button",
@@ -791,6 +882,9 @@ declare enum InteractionRoutes {
791
882
  UserContextMenu = "interaction:userContextMenu",
792
883
  Autocomplete = "interaction:autocomplete"
793
884
  }
885
+ /**
886
+ * Types of select menus supported for routing
887
+ */
794
888
  declare enum SelectMenuType {
795
889
  String = "string",
796
890
  User = "user",
@@ -798,6 +892,11 @@ declare enum SelectMenuType {
798
892
  Channel = "channel",
799
893
  Mentionable = "mentionable"
800
894
  }
895
+ /**
896
+ * Metadata key used to mark classes as interaction handlers
897
+ *
898
+ * @internal
899
+ */
801
900
  declare const InteractionMetadataKey: unique symbol;
802
901
  /**
803
902
  * Routes slash commands to handler classes
@@ -813,29 +912,36 @@ declare const InteractionMetadataKey: unique symbol;
813
912
  * class PingCommand extends InteractionHandler {
814
913
  * // handles /ping command
815
914
  * }
915
+ * ```
816
916
  *
917
+ * @example
918
+ * ```
817
919
  * \@SlashRoute(['ban', 'kick'])
818
920
  * class ModerationHandler extends InteractionHandler {
819
921
  * // handles /ban and /kick commands
820
922
  * }
923
+ * ```
821
924
  *
925
+ * @example
926
+ * ```
822
927
  * \@SlashRoute('admin/user/promote')
823
928
  * class PromoteHandler extends InteractionHandler {
824
929
  * // handles /admin user promote subcommand
825
930
  * }
826
931
  * ```
827
932
  */
828
- declare function SlashRoute(routeOrRoutes: string | string[]): (constructor: ConstructorFunction) => void;
933
+ declare function SlashRoute(routeOrRoutes: string | string[]): (constructor: Constructor<unknown>) => void;
829
934
  /**
830
935
  * Routes button interactions to handler classes
831
936
  *
832
937
  * Matches the customId prefix before the first colon.
833
- * For customId "accept:user123", use \@ButtonRoute("accept").
938
+ *
939
+ * For customId `accept:user123`, use `@ButtonRoute("accept")`.
834
940
  *
835
941
  * @param routeOrRoutes - CustomId prefix(es) to handle
836
942
  * @decorator
837
943
  */
838
- declare function ButtonRoute(routeOrRoutes: string | string[]): (constructor: ConstructorFunction) => void;
944
+ declare function ButtonRoute(routeOrRoutes: string | string[]): (constructor: Constructor<unknown>) => void;
839
945
  /**
840
946
  * Routes modal submissions to handler classes
841
947
  *
@@ -844,7 +950,7 @@ declare function ButtonRoute(routeOrRoutes: string | string[]): (constructor: Co
844
950
  * @param routeOrRoutes - CustomId prefix(es) to handle
845
951
  * @decorator
846
952
  */
847
- declare function ModalRoute(routeOrRoutes: string | string[]): (constructor: ConstructorFunction) => void;
953
+ declare function ModalRoute(routeOrRoutes: string | string[]): (constructor: Constructor<unknown>) => void;
848
954
  /**
849
955
  * Routes context menu commands to handler classes
850
956
  *
@@ -852,7 +958,7 @@ declare function ModalRoute(routeOrRoutes: string | string[]): (constructor: Con
852
958
  * @param routeOrRoutes - Command name(s) to handle
853
959
  * @decorator
854
960
  */
855
- declare function ContextMenuRoute(type: 'message' | 'user', routeOrRoutes: string | string[]): (constructor: ConstructorFunction) => void;
961
+ declare function ContextMenuRoute(type: 'message' | 'user', routeOrRoutes: string | string[]): (constructor: Constructor<unknown>) => void;
856
962
  /**
857
963
  * Routes autocomplete interactions to handler classes
858
964
  *
@@ -865,7 +971,7 @@ declare function ContextMenuRoute(type: 'message' | 'user', routeOrRoutes: strin
865
971
  * @example \@AutocompleteRoute(['user', 'profile'], ['name', 'bio']) // Multiple commands, multiple fields
866
972
  * @decorator
867
973
  */
868
- declare function AutocompleteRoute(commandRoutes: string | string[], focusedFields: string | string[]): (constructor: ConstructorFunction) => void;
974
+ declare function AutocompleteRoute(commandRoutes: string | string[], focusedFields: string | string[]): (constructor: Constructor<unknown>) => void;
869
975
  /**
870
976
  * Routes select menu interactions to handler classes
871
977
  *
@@ -873,9 +979,393 @@ declare function AutocompleteRoute(commandRoutes: string | string[], focusedFiel
873
979
  *
874
980
  * @param type - Select menu type from {@link SelectMenuType}
875
981
  * @param routeOrRoutes - CustomId prefix(es) to handle
982
+ *
983
+ * @decorator
984
+ *
985
+ * @example
986
+ * ```typescript
987
+ * \@SelectMenuRoute(SelectMenuType.String, 'fruits')
988
+ * class RoleSelectHandler extends InteractionHandler {
989
+ * // handles string select menus with customId starting with 'fruits'
990
+ * }
991
+ * ```
992
+ */
993
+ declare function SelectMenuRoute(type: SelectMenuType, routeOrRoutes: string | string[]): (constructor: Constructor<unknown>) => void;
994
+
995
+ /**
996
+ * Middleware types supported by Seedcord
997
+ */
998
+ declare enum MiddlewareType {
999
+ Interaction = "middleware:interaction",
1000
+ Event = "middleware:event"
1001
+ }
1002
+ /**
1003
+ * Metadata key for middleware configuration
1004
+ *
1005
+ * @internal
1006
+ */
1007
+ declare const MiddlewareMetadataKey: unique symbol;
1008
+ /**
1009
+ * Additional middleware registration options
1010
+ */
1011
+ interface MiddlewareOptions {
1012
+ /**
1013
+ * Restrict event middleware execution to specific Discord client events
1014
+ */
1015
+ readonly events?: readonly (keyof ClientEvents)[];
1016
+ }
1017
+ /**
1018
+ * Metadata stored for middleware registration
1019
+ */
1020
+ interface MiddlewareMetadata {
1021
+ /**
1022
+ * Priority number used to order middleware
1023
+ */
1024
+ priority: number;
1025
+ /**
1026
+ * Middleware kind from {@link MiddlewareType}
1027
+ */
1028
+ type: MiddlewareType;
1029
+ /**
1030
+ * Optional list of Discord client events to target
1031
+ */
1032
+ events?: readonly (keyof ClientEvents)[];
1033
+ }
1034
+ /**
1035
+ * Decorator used to register middleware with priority ordering. The lower the priority number, the earlier it runs.
1036
+ *
1037
+ * Interaction middleware cannot specify event filters.
1038
+ *
1039
+ * @param type - Middleware kind from {@link MiddlewareType}
1040
+ * @param priority - Ordering value where lower runs earlier. Default is 0
1041
+ * @param options - Additional registration options
1042
+ *
876
1043
  * @decorator
1044
+ *
1045
+ * @example
1046
+ * ```ts
1047
+ * \@Middleware(MiddlewareType.Event, 10, { events: [Events.MessageCreate, Events.MessageUpdate] })
1048
+ * class MyEventMiddleware extends EventMiddleware {}
1049
+ * ```
1050
+ * @throws A {@link TypeError} If priority is not a finite number
1051
+ * @throws An {@link Error} If interaction middleware specifies event filters
1052
+ */
1053
+ declare function Middleware(type: MiddlewareType, priority?: number, options?: MiddlewareOptions): ClassDecorator;
1054
+
1055
+ /**
1056
+ * Manages Discord event handler registration and execution.
1057
+ *
1058
+ * Scans event handler directories, registers handlers with Discord client events,
1059
+ * and coordinates event execution through the handler system. Does not handle interactions.
1060
+ *
1061
+ * Multiple handlers can point to one event.
1062
+ *
1063
+ * @internal
877
1064
  */
878
- declare function SelectMenuRoute(type: SelectMenuType, routeOrRoutes: string | string[]): (constructor: ConstructorFunction) => void;
1065
+ declare class EventController implements Initializeable {
1066
+ protected core: Core;
1067
+ private readonly logger;
1068
+ private isInitialized;
1069
+ private readonly eventMap;
1070
+ private readonly middlewares;
1071
+ constructor(core: Core);
1072
+ init(): Promise<void>;
1073
+ private loadHandlers;
1074
+ private loadMiddlewares;
1075
+ private registerMiddleware;
1076
+ private runMiddlewares;
1077
+ private isEventHandlerClass;
1078
+ private isMiddlewareClass;
1079
+ private registerHandler;
1080
+ private attachToClient;
1081
+ private processEvent;
1082
+ }
1083
+
1084
+ /**
1085
+ * Manages Discord interaction handling and routing.
1086
+ *
1087
+ * Scans handler directories, registers handlers with Discord client events,
1088
+ * and coordinates event execution through the handler system. Only handles interactions.
1089
+ *
1090
+ * Enforces that there is only one handler per interaction.
1091
+ *
1092
+ * @internal
1093
+ */
1094
+ declare class InteractionController implements Initializeable {
1095
+ protected core: Core;
1096
+ private readonly logger;
1097
+ private isInitialized;
1098
+ private readonly slashMap;
1099
+ private readonly buttonMap;
1100
+ private readonly modalMap;
1101
+ private readonly stringSelectMap;
1102
+ private readonly userSelectMap;
1103
+ private readonly roleSelectMap;
1104
+ private readonly channelSelectMap;
1105
+ private readonly mentionableSelectMap;
1106
+ private readonly messageContextMenuMap;
1107
+ private readonly userContextMenuMap;
1108
+ private readonly autocompleteMap;
1109
+ private readonly keysToIgnore;
1110
+ private readonly middlewares;
1111
+ constructor(core: Core);
1112
+ init(): Promise<void>;
1113
+ private loadHandlers;
1114
+ private loadMiddlewares;
1115
+ private registerMiddleware;
1116
+ private isHandlerClass;
1117
+ private isMiddlewareClass;
1118
+ private registerHandler;
1119
+ private attachToClient;
1120
+ private parseCustomId;
1121
+ private handleCustomIdInteraction;
1122
+ processInteraction<TInteraction extends Interaction>(interaction: TInteraction, extractKey: (i: TInteraction) => string, getHandler: (key: string) => HandlerConstructor | undefined, args?: string[]): Promise<void>;
1123
+ private handleInteraction;
1124
+ private handleSlashCommand;
1125
+ private handleButton;
1126
+ private handleModal;
1127
+ private handleStringSelectMenu;
1128
+ private handleUserSelectMenu;
1129
+ private handleRoleSelectMenu;
1130
+ private handleChannelSelectMenu;
1131
+ private handleMentionableSelectMenu;
1132
+ private handleMessageContextMenu;
1133
+ private handleUserContextMenu;
1134
+ private handleAutocomplete;
1135
+ }
1136
+
1137
+ /**
1138
+ * Error thrown when a requested channel cannot be found.
1139
+ */
1140
+ declare class ChannelNotFoundError extends CustomError {
1141
+ readonly channelId: string;
1142
+ /**
1143
+ * Creates a new ChannelNotFoundError.
1144
+ *
1145
+ * @param message - The error message
1146
+ * @param channelId - The ID of the channel that could not be found
1147
+ */
1148
+ constructor(message: string, channelId: string);
1149
+ }
1150
+ /**
1151
+ * Error thrown when the bot cannot send embeds in a channel.
1152
+ */
1153
+ declare class CannotSendEmbedsError extends CustomError {
1154
+ readonly channelId: string;
1155
+ /**
1156
+ * Creates a new CannotSendEmbedsError.
1157
+ *
1158
+ * @param message - The error message
1159
+ * @param channelId - The ID of the channel where embeds cannot be sent
1160
+ */
1161
+ constructor(message: string, channelId: string);
1162
+ }
1163
+ /**
1164
+ * Error thrown when a channel could not be found or accessed.
1165
+ */
1166
+ declare class CouldNotFindChannel extends CustomError {
1167
+ readonly channelId: string;
1168
+ /**
1169
+ * Creates a new CouldNotFindChannel error.
1170
+ *
1171
+ * @param message - The error message
1172
+ * @param channelId - The ID of the channel that could not be found
1173
+ */
1174
+ constructor(message: string, channelId: string);
1175
+ }
1176
+ /**
1177
+ * Error thrown when a channel is not a text channel.
1178
+ */
1179
+ declare class ChannelNotTextChannel extends CustomError {
1180
+ readonly channelId: string;
1181
+ /**
1182
+ * Creates a new ChannelNotTextChannel error.
1183
+ *
1184
+ * @param message - The error message
1185
+ * @param channelId - The ID of the channel that is not a text channel
1186
+ */
1187
+ constructor(message: string, channelId: string);
1188
+ }
1189
+
1190
+ /**
1191
+ * Generic database operation error with UUID tracking.
1192
+ *
1193
+ * Thrown for various database operation failures and includes
1194
+ * a UUID for error tracking and debugging purposes.
1195
+ */
1196
+ declare class DatabaseError extends CustomError {
1197
+ uuid: UUID;
1198
+ /**
1199
+ * Creates a new DatabaseError.
1200
+ *
1201
+ * @param message - The error message describing what went wrong
1202
+ * @param uuid - A unique identifier for this specific error instance
1203
+ */
1204
+ constructor(message: string, uuid: UUID);
1205
+ }
1206
+
1207
+ /**
1208
+ * Error thrown when the bot lacks necessary permissions to perform an action.
1209
+ */
1210
+ declare class MissingPermissions extends CustomError {
1211
+ missingPerms: string[];
1212
+ roleOrChannel: Role | TextChannel;
1213
+ /**
1214
+ * Creates a new BotMissingPermissionsError.
1215
+ *
1216
+ * @param message - The error message
1217
+ * @param missingPerms - Array of missing permission names
1218
+ * @param roleOrChannel - The role or channel where permissions are missing
1219
+ */
1220
+ constructor(message: string, missingPerms: string[], roleOrChannel: Role | TextChannel);
1221
+ }
1222
+ /**
1223
+ * Error thrown when attempting to modify a role higher than the bot's highest role.
1224
+ */
1225
+ declare class RoleHigherThanMe extends CustomError {
1226
+ role: Role;
1227
+ botRole: Role;
1228
+ /**
1229
+ * Creates a new RoleHigherThanMe error.
1230
+ *
1231
+ * @param message - The error message
1232
+ */
1233
+ constructor(message: string, role: Role, botRole: Role);
1234
+ }
1235
+ /**
1236
+ * Error thrown when attempting to assign a managed/bot role.
1237
+ */
1238
+ declare class CannotAssignBotRole extends CustomError {
1239
+ /**
1240
+ * Creates a new CannotAssignBotRole error.
1241
+ *
1242
+ * @param message - The error message
1243
+ */
1244
+ constructor(message?: string);
1245
+ }
1246
+ /**
1247
+ * Error thrown when a requested role does not exist.
1248
+ */
1249
+ declare class RoleDoesNotExist extends CustomError {
1250
+ roleId: string;
1251
+ /**
1252
+ * Creates a new RoleDoesNotExist error.
1253
+ *
1254
+ * @param message - The error message
1255
+ * @param roleId - The ID of the role that doesn't exist
1256
+ */
1257
+ constructor(message: string, roleId: string);
1258
+ }
1259
+ /**
1260
+ * Error thrown when a role has dangerous permissions that shouldn't be assigned.
1261
+ */
1262
+ declare class HasDangerousPermissions extends CustomError {
1263
+ role: Role;
1264
+ dangerousPerms: string[];
1265
+ /**
1266
+ * Creates a new HasDangerousPermissions error.
1267
+ *
1268
+ * @param message - The error message
1269
+ * @param role - The role with dangerous permissions
1270
+ * @param dangerousPerms - Array of dangerous permission names
1271
+ */
1272
+ constructor(message: string, role: Role, dangerousPerms: string[]);
1273
+ }
1274
+
1275
+ /**
1276
+ * Error thrown when attempting to perform actions on a user not in the guild.
1277
+ */
1278
+ declare class UserNotInGuild extends CustomError {
1279
+ /**
1280
+ * Creates a new UserNotInGuild error.
1281
+ *
1282
+ * @param message - The error message
1283
+ */
1284
+ constructor(message?: string);
1285
+ }
1286
+ /**
1287
+ * Error thrown when a requested user cannot be found.
1288
+ */
1289
+ declare class UserNotFound extends CustomError {
1290
+ readonly userArg: string;
1291
+ /**
1292
+ * Creates a new UserNotFound error.
1293
+ *
1294
+ * @param userArg - The user argument that could not be resolved
1295
+ */
1296
+ constructor(userArg: string);
1297
+ }
1298
+
1299
+ declare class EmojiInjector {
1300
+ private readonly core;
1301
+ private readonly logger;
1302
+ constructor(core: Core);
1303
+ init(): Promise<void>;
1304
+ }
1305
+
1306
+ /**
1307
+ * Fetches and validates a text channel.
1308
+ *
1309
+ * @param client - The Discord client instance
1310
+ * @param channelId - Channel ID or TextChannel instance
1311
+ * @returns Promise resolving to the text channel
1312
+ * @throws A {@link CouldNotFindChannel} When the channel doesn't exist or isn't text-based
1313
+ */
1314
+ declare function fetchText(client: Client, channelId: TextChannelResolvable): Promise<TextChannel>;
1315
+
1316
+ /** Discord message content with embeds and components */
1317
+ interface MessageContent {
1318
+ embeds: EmbedBuilder[];
1319
+ components: [ActionRowBuilder<MessageActionRowComponentBuilder>];
1320
+ }
1321
+ /** Discord message that requires at least one of content, embeds, or components */
1322
+ type AtleastOneMessageComponent = RequireAtLeastOne<{
1323
+ content: string;
1324
+ } & MessageContent>;
1325
+
1326
+ /**
1327
+ * Sends a message to a text channel by ID.
1328
+ *
1329
+ * @param client - The Discord client instance
1330
+ * @param channelId - Channel ID or TextChannel instance
1331
+ * @param message - Message content to send
1332
+ * @returns Promise resolving to the sent message
1333
+ * @throws A {@link CouldNotFindChannel} When the channel doesn't exist or isn't text-based
1334
+ */
1335
+ declare function sendInText(client: Client, channelId: TextChannelResolvable, message: AtleastOneMessageComponent): Promise<Message>;
1336
+
1337
+ /**
1338
+ * Structure representing the extracted error response.
1339
+ */
1340
+ interface ExtractedErrorResponse {
1341
+ /** The unique identifier for the error instance */
1342
+ uuid: UUID$1;
1343
+ /** The formatted error response to be sent to the user */
1344
+ response: EmbedBuilder;
1345
+ }
1346
+ /**
1347
+ * Processes an error and extracts the standardized response, if available (else returns a {@link GenericError}).
1348
+ *
1349
+ * Handles different error types (CustomError, DatabaseError) with appropriate
1350
+ * logging, side effects, and user-facing error messages.
1351
+ *
1352
+ * @param error - The error to process
1353
+ * @param core - The core framework instance
1354
+ * @param guild - The guild where the error occurred (if any)
1355
+ * @param user - The user who triggered the error (if any)
1356
+ * @returns Object containing UUID and formatted error response embed
1357
+ */
1358
+ declare function extractErrorResponse(error: Error, core: Core, guild: Nullable<Guild>, user: Nullable<User>, metadata?: unknown): ExtractedErrorResponse;
1359
+ /**
1360
+ * Generic error shown to users when an unknown error occurs
1361
+ *
1362
+ * Set an environment variable called `DEVELOPER_DISCORD_USERNAME` in your `.env` file to customize the contact name.
1363
+ */
1364
+ declare class GenericError extends CustomError {
1365
+ private readonly uuid;
1366
+ private readonly developerUsername;
1367
+ constructor(uuid: UUID$1);
1368
+ }
879
1369
 
880
1370
  /**
881
1371
  * Throws a custom error with a formatted message and optional UUID.
@@ -883,7 +1373,7 @@ declare function SelectMenuRoute(type: SelectMenuType, routeOrRoutes: string | s
883
1373
  * Wraps an unknown error in a {@link CustomError} subclass. If the error class
884
1374
  * is {@link DatabaseError}, a UUID is generated and passed to the constructor.
885
1375
  *
886
- * @typeParam T - A constructor for a {@link CustomError} subclass
1376
+ * @typeParam Ctor - A constructor for a {@link CustomError} subclass
887
1377
  * @param error - The original error or value
888
1378
  * @param message - Custom message to include
889
1379
  * @param CustomError - Error class to instantiate and throw
@@ -900,6 +1390,171 @@ declare function SelectMenuRoute(type: SelectMenuType, routeOrRoutes: string | s
900
1390
  */
901
1391
  declare function throwCustomError<Ctor extends CustomErrorConstructor>(error: unknown, message: string, CustomError: Ctor): never;
902
1392
 
1393
+ /**
1394
+ * Sends a direct message to a user.
1395
+ *
1396
+ * @param user - The user to send the DM to
1397
+ * @param content - Message content with embeds, components, etc.
1398
+ * @returns Promise resolving to the sent message, or null if DM failed
1399
+ */
1400
+ declare function attemptSendDM(user: User, content: AtleastOneMessageComponent): Promise<Nullable<Message>>;
1401
+
1402
+ /**
1403
+ * Route string computed from provided parts.
1404
+ *
1405
+ * @typeParam Cmmd - Main command name
1406
+ * @typeParam Subc - Subcommand name
1407
+ * @typeParam Grp - Group name (will be ignored if subcommand is not provided with it)
1408
+ */
1409
+ type CommandRouteString<Cmmd extends string, Subc extends string | undefined, Grp extends string | undefined> = Subc extends string ? (Grp extends string ? `${Cmmd}/${Grp}/${Subc}` : `${Cmmd}/${Subc}`) : Cmmd;
1410
+ /**
1411
+ * From provided positional arguments. Either provide the route to either {@link SlashRoute} or {@link AutocompleteRoute} manually, or use this utility to build it.
1412
+ *
1413
+ * @param command - Main command name
1414
+ * @param subcommand - Optional subcommand name
1415
+ * @param group - Optional group name (will be ignored if subcommand is not provided with it)
1416
+ */
1417
+ declare function buildSlashRoute<Cmmd extends string, Subc extends string | undefined = undefined, Grp extends string | undefined = undefined>(command: Cmmd, subcommand?: Subc, group?: Grp): CommandRouteString<Cmmd, Subc, Grp>;
1418
+ /**
1419
+ * From a Discord interaction. The {@link InteractionController} uses this internally to build the route string to then route the correct handler.
1420
+ *
1421
+ * @internal
1422
+ */
1423
+ declare function buildSlashRoute(interaction: ChatInputCommandInteraction | AutocompleteInteraction): string;
1424
+
1425
+ /**
1426
+ * Map of permission bits to their prettified human-readable names.
1427
+ */
1428
+ declare const PermissionNames: Map<bigint, string>;
1429
+ /**
1430
+ * Defines the scope types for bot permission validation.
1431
+ */
1432
+ type BotPermissionScope = 'manage' | 'others' | 'all' | bigint[] | 'embed';
1433
+ /**
1434
+ * Defines the valid group types for permission checking, excluding 'all' and bigint[].
1435
+ */
1436
+ type BotPermissionScopeGroups = TypedExclude<BotPermissionScope, 'all' | bigint[]>;
1437
+ /**
1438
+ * Predefined permission groups for different scopes.
1439
+ */
1440
+ declare const PERM_GROUPS: Record<BotPermissionScopeGroups, Map<bigint, string>>;
1441
+ /**
1442
+ * Checks permissions for a {@link Role}.
1443
+ *
1444
+ * @param client - The Discord client instance
1445
+ * @param roleOrChannel - Role to check permissions for
1446
+ * @param scope - Permission scope to validate
1447
+ * @param inverse - Whether to check for absence of permissions (role only). Defaults to false.
1448
+ * @throws A {@link MissingPermissions} When required permissions are missing
1449
+ * @throws A {@link HasDangerousPermissions} When role has dangerous permissions (if inverse is true)
1450
+ */
1451
+ declare function checkPermissions(client: Client, roleOrChannel: Role, scope: BotPermissionScope, inverse?: boolean): void;
1452
+ /**
1453
+ * Checks permissions for a {@link TextChannel}.
1454
+ *
1455
+ * @param client - The Discord client instance
1456
+ * @param roleOrChannel - TextChannel to check permissions for
1457
+ * @param scope - Permission scope to validate
1458
+ * @throws A {@link MissingPermissions} When required permissions are missing
1459
+ */
1460
+ declare function checkPermissions(client: Client, roleOrChannel: TextChannel, scope?: BotPermissionScope): void;
1461
+
1462
+ /**
1463
+ * Checks if the bot has required permissions in a guild or channel.
1464
+ *
1465
+ * @param client - The Discord client instance
1466
+ * @param guildOrChannel - Guild or text channel to check permissions in
1467
+ * @param scope - Permission scope to validate
1468
+ * @param inverse - Whether to check for absence of permissions
1469
+ * @throws A {@link MissingPermissions} When bot lacks required permissions
1470
+ */
1471
+ declare function checkBotPermissions(client: Client, guildOrChannel: Guild | TextChannel, scope?: BotPermissionScope, inverse?: boolean): void;
1472
+
1473
+ /**
1474
+ * Fetches a role by ID from a client or guild.
1475
+ *
1476
+ * @param clientOrGuild - Discord client or guild instance
1477
+ * @param roleId - The role ID to fetch
1478
+ * @returns Promise resolving to the role
1479
+ * @throws A {@link RoleDoesNotExist} When the role doesn't exist
1480
+ */
1481
+ declare function fetchRole(clientOrGuild: Client | Guild, roleId: string): Promise<Role>;
1482
+
1483
+ /**
1484
+ * Gets the bot's highest role in a guild.
1485
+ *
1486
+ * @param client - The Discord client instance
1487
+ * @param guild - The guild to get the bot's role from
1488
+ * @returns The bot's highest role in the guild
1489
+ * @throws An {@link Error} When the bot is not in the guild
1490
+ */
1491
+ declare function getBotRole(client: Client, guild: Guild): Role;
1492
+
1493
+ /**
1494
+ * Validates if the bot has permission to assign a target role.
1495
+ *
1496
+ * @param targetRole - The role to check assignment permissions for
1497
+ * @throws A {@link RoleHigherThanMe} When the target role is higher than bot's role
1498
+ * @throws A {@link CannotAssignBotRole} When trying to assign a managed/bot role
1499
+ * @throws A {@link MissingPermissions} When bot lacks Manage Roles permission
1500
+ */
1501
+ declare function hasPermsToAssign(targetRole: Role): void;
1502
+
1503
+ /**
1504
+ * Fetches a guild member by user ID with error handling.
1505
+ *
1506
+ * @param guild - The guild to fetch the member from
1507
+ * @param userId - The Discord user ID
1508
+ * @returns Promise resolving to the guild member
1509
+ * @throws A {@link UserNotInGuild} When the user is not found in the guild
1510
+ */
1511
+ declare function fetchGuildMember(guild: Guild, userId: string): Promise<GuildMember>;
1512
+
1513
+ /**
1514
+ * Fetches multiple guild members by user IDs.
1515
+ *
1516
+ * @param guild - The guild to fetch members from
1517
+ * @param userIds - Array of Discord user IDs
1518
+ * @returns Promise resolving to array of successfully fetched members
1519
+ */
1520
+ declare function fetchManyGuildMembers(guild: Guild, userIds: string[]): Promise<GuildMember[]>;
1521
+
1522
+ /**
1523
+ * Fetches multiple Discord users by IDs.
1524
+ *
1525
+ * @param client - The Discord client instance
1526
+ * @param userIds - Array of Discord user IDs
1527
+ * @returns Promise resolving to array of successfully fetched users
1528
+ */
1529
+ declare function fetchManyUsers(client: Client, userIds: string[]): Promise<User[]>;
1530
+
1531
+ /**
1532
+ * Fetches a Discord user by ID with error handling.
1533
+ *
1534
+ * @param client - The Discord client instance
1535
+ * @param userId - The Discord user ID
1536
+ * @returns Promise resolving to the user
1537
+ * @throws A {@link UserNotFound} When the user doesn't exist
1538
+ */
1539
+ declare function fetchUser(client: Client, userId: string): Promise<User>;
1540
+
1541
+ /**
1542
+ * Updates a guild member's roles by adding and removing specified roles.
1543
+ *
1544
+ * @param rolesToAdd - Array of role IDs to add to the member
1545
+ * @param rolesToRemove - Array of role IDs to remove from the member
1546
+ * @param member - The guild member to update
1547
+ * @returns Promise that resolves when roles are updated
1548
+ */
1549
+ declare function updateMemberRoles(rolesToAdd: Snowflake[], rolesToRemove: Snowflake[], member: GuildMember): Promise<void>;
1550
+
1551
+ /**
1552
+ * Default handler for unhandled interaction.
1553
+ */
1554
+ declare class UnhandledEvent extends InteractionHandler<Repliables> {
1555
+ execute(): Promise<void>;
1556
+ }
1557
+
903
1558
  /**
904
1559
  * Type-safe event emitter for application effects.
905
1560
  *
@@ -907,6 +1562,8 @@ declare function throwCustomError<Ctor extends CustomErrorConstructor>(error: un
907
1562
  * for Seedcord's effect system.
908
1563
  *
909
1564
  * @typeParam AllEffects - Side effect definitions mapping event names to data types
1565
+ *
1566
+ * @internal
910
1567
  */
911
1568
  declare class EffectsEmitter {
912
1569
  private readonly emitter;
@@ -939,6 +1596,11 @@ declare class EffectsEmitter {
939
1596
  emit<KeyOfEffects extends EffectKeys>(event: KeyOfEffects, data: AllEffects[KeyOfEffects]): boolean;
940
1597
  }
941
1598
 
1599
+ /**
1600
+ * Metadata key used to store effect handler information
1601
+ *
1602
+ * @internal
1603
+ */
942
1604
  declare const EffectMetadataKey: unique symbol;
943
1605
  /**
944
1606
  * Registers a side effect handler class with a specific side effect event.
@@ -946,6 +1608,7 @@ declare const EffectMetadataKey: unique symbol;
946
1608
  * Associates the decorated class with a side effect event type for automatic
947
1609
  * registration and execution when the side effect is emitted.
948
1610
  *
1611
+ * @typeParam TEffect - The side effect event name to register for
949
1612
  * @param effect - The side effect event name to register for
950
1613
  * @decorator
951
1614
  * @example
@@ -958,7 +1621,7 @@ declare const EffectMetadataKey: unique symbol;
958
1621
  * }
959
1622
  * ```
960
1623
  */
961
- declare function RegisterEffect<TEffect extends EffectKeys>(effect: TEffect): (constructor: ConstructorFunction) => void;
1624
+ declare function RegisterEffect<TEffect extends EffectKeys>(effect: TEffect): (constructor: Constructor<unknown>) => void;
962
1625
 
963
1626
  /**
964
1627
  * Abstract base class for handling application side effects.
@@ -1000,20 +1663,24 @@ declare abstract class WebhookLog<KeyOfEffects extends EffectKeys> extends Effec
1000
1663
  }
1001
1664
 
1002
1665
  /**
1003
- * Generic database operation error with UUID tracking.
1666
+ * Default effect to log unhandled exceptions via webhook. It provides basic information about the error:
1667
+ * - Error stack trace
1668
+ * - Guild ID and name (if applicable)
1669
+ * - User ID and username (if applicable)
1670
+ * - A unique UUID for tracking
1671
+ * - Timestamps comparing interaction time and error log time (if applicable)
1672
+ * - Metadata associated with the error (if provided)
1004
1673
  *
1005
- * Thrown for various database operation failures and includes
1006
- * a UUID for error tracking and debugging purposes.
1674
+ * Developers need to set the UNKNOWN_EXCEPTION_WEBHOOK_URL environment variable in their .env file otherwise this effect will throw an error during initialization.
1675
+ *
1676
+ * @throws Error if UNKNOWN_EXCEPTION_WEBHOOK_URL is not set or is invalid
1007
1677
  */
1008
- declare class DatabaseError extends CustomError {
1009
- uuid: UUID;
1010
- /**
1011
- * Creates a new DatabaseError.
1012
- *
1013
- * @param message - The error message describing what went wrong
1014
- * @param uuid - A unique identifier for this specific error instance
1015
- */
1016
- constructor(message: string, uuid: UUID);
1678
+ declare class UnknownException extends WebhookLog<'unknownException'> {
1679
+ private static readonly logger;
1680
+ static readonly unknownExceptionWebhookUrl: string;
1681
+ webhook: WebhookClient;
1682
+ execute(): Promise<void>;
1683
+ private prepareMetadataFile;
1017
1684
  }
1018
1685
 
1019
- export { type AllEffects, AutocompleteHandler, type AutocompleteHandlerConstructor, AutocompleteRoute, BaseErrorEmbed, Bot, BuilderComponent, ButtonRoute, Catchable, Checkable, type CommandMeta, CommandMetadataKey, type Config, ContextMenuRoute, type Core, CustomError, type CustomErrorConstructor, DatabaseError, type DefaultEffects, type EffectKeys, EffectMetadataKey, type EffectParams, type Effects, EffectsEmitter, EffectsHandler, EffectsRegistry, EventCatchable, EventHandler, type EventHandlerConstructor, EventMetadataKey, type Handler, type HandlerConstructor, type Initializeable, InteractionHandler, InteractionMetadataKey, InteractionMiddleware, InteractionRoutes, type MiddlewareConstructor, ModalComponent, ModalRoute, Pluggable, Plugin, type PluginArgs, type PluginCtor, RegisterCommand, RegisterEffect, RegisterEvent, type RepliableInteractionHandler, type Repliables, RowComponent, Seedcord, SelectMenuRoute, SelectMenuType, SlashRoute, type ValidEventTypes, type ValidInteractionTypes, type ValidNonInteractionTypes, WebhookLog, type WithChecks, throwCustomError };
1686
+ export { type ActionRowComponentType, type AllEffects, type AtleastOneMessageComponent, AutocompleteHandler, type AutocompleteHandlerConstructor, AutocompleteRoute, BaseComponent, type BaseCore, BaseErrorEmbed, BaseHandler, Bot, type BotConfig, type BotPermissionScope, type BotPermissionScopeGroups, BuilderComponent, type BuilderType, BuilderTypes, ButtonRoute, CannotAssignBotRole, CannotSendEmbedsError, Catchable, type CatchableOptions, ChannelNotFoundError, ChannelNotTextChannel, Checkable, type CommandCtor, type CommandMeta, CommandMetadataKey, CommandRegistry, type CommandRouteString, type CommandScope, type CommandsConfig, type Config, ContextMenuRoute, type Core, CouldNotFindChannel, CustomError, type CustomErrorConstructor, DatabaseError, type DefaultEffects, type EffectKeys, EffectMetadataKey, type EffectParams, type Effects, type EffectsConfig, EffectsEmitter, EffectsHandler, EffectsRegistry, EmojiInjector, EventCatchable, EventController, EventHandler, type EventHandlerConstructor, EventMetadataKey, EventMiddleware, type EventMiddlewareConstructor, type EventsConfig, type ExtractedErrorResponse, GenericError, type GlobalMeta, type GuildMeta, type Handler, type HandlerConstructor, type HandlerCtor, type HandlerWithChecks, HasDangerousPermissions, type Initializeable, type InstantiatedActionRow, type InstantiatedBuilder, InteractionController, InteractionHandler, InteractionMetadataKey, InteractionMiddleware, type InteractionMiddlewareConstructor, InteractionRoutes, type InteractionsConfig, type MessageContent, Middleware, type MiddlewareConstructor, type MiddlewareMetadata, MiddlewareMetadataKey, type MiddlewareOptions, MiddlewareType, MissingPermissions, ModalRoute, PERM_GROUPS, PermissionNames, Pluggable, Plugin, type PluginArgs, type PluginCtor, RegisterCommand, RegisterEffect, RegisterEvent, type RepliableInteractionHandler, type Repliables, RoleDoesNotExist, RoleHigherThanMe, RowComponent, RowTypes, Seedcord, SelectMenuRoute, SelectMenuType, SlashRoute, UnhandledEvent, UnknownException, UserNotFound, UserNotInGuild, type ValidEventTypes, type ValidInteractionTypes, type ValidNonInteractionTypes, WebhookLog, type WithChecks, attemptSendDM, buildSlashRoute, checkBotPermissions, checkPermissions, extractErrorResponse, fetchGuildMember, fetchManyGuildMembers, fetchManyUsers, fetchRole, fetchText, fetchUser, getBotRole, hasPermsToAssign, sendInText, throwCustomError, updateMemberRoles };