@mostfeatured/dbi 0.1.29 → 0.1.31

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.
Files changed (102) hide show
  1. package/.gitattributes +2 -2
  2. package/.hintrc +7 -7
  3. package/.vscode/settings.json +2 -2
  4. package/LICENSE +674 -674
  5. package/dist/DBI.js.map +1 -1
  6. package/dist/Events.js.map +1 -1
  7. package/dist/index.js.map +1 -1
  8. package/dist/methods/handleMessageCommands.js +1 -1
  9. package/dist/methods/handleMessageCommands.js.map +1 -1
  10. package/dist/methods/hookEventListeners.js.map +1 -1
  11. package/dist/methods/hookInteractionListeners.js.map +1 -1
  12. package/dist/methods/publishInteractions.js.map +1 -1
  13. package/dist/types/ApplicationRoleConnectionMetadata.js.map +1 -1
  14. package/dist/types/Builders/ButtonBuilder.js.map +1 -1
  15. package/dist/types/Builders/ChannelSelectMenuBuilder.js.map +1 -1
  16. package/dist/types/Builders/MentionableSelectMenuBuilder.js.map +1 -1
  17. package/dist/types/Builders/ModalBuilder.js.map +1 -1
  18. package/dist/types/Builders/RoleSelectMenuBuilder.js.map +1 -1
  19. package/dist/types/Builders/StringSelectMenuBuilder.js.map +1 -1
  20. package/dist/types/Builders/UserSelectMenuBuilder.js.map +1 -1
  21. package/dist/types/ChatInput/ChatInput.js.map +1 -1
  22. package/dist/types/ChatInput/ChatInputOptions.d.ts +16 -16
  23. package/dist/types/ChatInput/ChatInputOptions.d.ts.map +1 -1
  24. package/dist/types/ChatInput/ChatInputOptions.js.map +1 -1
  25. package/dist/types/Components/Button.js.map +1 -1
  26. package/dist/types/Components/ChannelSelectMenu.js.map +1 -1
  27. package/dist/types/Components/MentionableSelectMenu.js.map +1 -1
  28. package/dist/types/Components/Modal.js.map +1 -1
  29. package/dist/types/Components/RoleSelectMenu.js.map +1 -1
  30. package/dist/types/Components/StringSelectMenu.js.map +1 -1
  31. package/dist/types/Components/UserSelectMenu.js.map +1 -1
  32. package/dist/types/Event.js.map +1 -1
  33. package/dist/types/Interaction.d.ts +1 -0
  34. package/dist/types/Interaction.d.ts.map +1 -1
  35. package/dist/types/Interaction.js.map +1 -1
  36. package/dist/types/other/CustomEvent.js.map +1 -1
  37. package/dist/types/other/FakeMessageInteraction.js.map +1 -1
  38. package/dist/types/other/InteractionLocale.js.map +1 -1
  39. package/dist/types/other/Locale.js.map +1 -1
  40. package/dist/types/other/MessageContextMenu.js.map +1 -1
  41. package/dist/types/other/UserContextMenu.js.map +1 -1
  42. package/dist/utils/MemoryStore.js.map +1 -1
  43. package/dist/utils/UtilTypes.js.map +1 -1
  44. package/dist/utils/customId.js.map +1 -1
  45. package/dist/utils/permissions.js.map +1 -1
  46. package/dist/utils/recursiveImport.js.map +1 -1
  47. package/dist/utils/recursiveUnload.js.map +1 -1
  48. package/dist/utils/unloadModule.js.map +1 -1
  49. package/examples/modal/dbi.js +29 -29
  50. package/examples/modal/login.js +14 -14
  51. package/examples/modal/package.json +15 -15
  52. package/examples/modal/publish.js +12 -12
  53. package/examples/modal/src/chatInput.js +37 -37
  54. package/examples/modal/src/components.js +32 -32
  55. package/examples/modal/src/event.js +19 -19
  56. package/examples/modal/src/interactionlocales.js +23 -23
  57. package/examples/modal/src/locales.js +37 -37
  58. package/examples/modal/src/modal.js +27 -27
  59. package/generated/namespaceData.d.ts +14 -14
  60. package/package.json +45 -45
  61. package/readme.md +591 -591
  62. package/src/DBI.ts +1090 -1090
  63. package/src/Events.ts +189 -189
  64. package/src/data/eventMap.json +247 -247
  65. package/src/index.ts +23 -23
  66. package/src/methods/handleMessageCommands.ts +482 -482
  67. package/src/methods/hookEventListeners.ts +118 -118
  68. package/src/methods/hookInteractionListeners.ts +260 -260
  69. package/src/methods/publishInteractions.ts +255 -255
  70. package/src/types/ApplicationRoleConnectionMetadata.ts +19 -19
  71. package/src/types/Builders/ButtonBuilder.ts +52 -52
  72. package/src/types/Builders/ChannelSelectMenuBuilder.ts +52 -52
  73. package/src/types/Builders/MentionableSelectMenuBuilder.ts +52 -52
  74. package/src/types/Builders/ModalBuilder.ts +52 -52
  75. package/src/types/Builders/RoleSelectMenuBuilder.ts +52 -52
  76. package/src/types/Builders/StringSelectMenuBuilder.ts +52 -52
  77. package/src/types/Builders/UserSelectMenuBuilder.ts +52 -52
  78. package/src/types/ChatInput/ChatInput.ts +27 -27
  79. package/src/types/ChatInput/ChatInputOptions.ts +388 -388
  80. package/src/types/Components/Button.ts +38 -38
  81. package/src/types/Components/ChannelSelectMenu.ts +42 -42
  82. package/src/types/Components/MentionableSelectMenu.ts +42 -42
  83. package/src/types/Components/Modal.ts +45 -45
  84. package/src/types/Components/RoleSelectMenu.ts +42 -42
  85. package/src/types/Components/StringSelectMenu.ts +42 -42
  86. package/src/types/Components/UserSelectMenu.ts +42 -42
  87. package/src/types/Event.ts +144 -144
  88. package/src/types/Interaction.ts +96 -96
  89. package/src/types/other/CustomEvent.ts +18 -18
  90. package/src/types/other/FakeMessageInteraction.ts +407 -407
  91. package/src/types/other/InteractionLocale.ts +33 -33
  92. package/src/types/other/Locale.ts +69 -69
  93. package/src/types/other/MessageContextMenu.ts +26 -26
  94. package/src/types/other/UserContextMenu.ts +24 -24
  95. package/src/utils/MemoryStore.ts +27 -27
  96. package/src/utils/UtilTypes.ts +10 -10
  97. package/src/utils/customId.ts +44 -44
  98. package/src/utils/permissions.ts +4 -4
  99. package/src/utils/recursiveImport.ts +22 -22
  100. package/src/utils/recursiveUnload.ts +24 -24
  101. package/src/utils/unloadModule.ts +6 -6
  102. package/tsconfig.json +40 -40
package/src/DBI.ts CHANGED
@@ -1,1090 +1,1090 @@
1
- import Discord, { MessagePayload } from "discord.js";
2
- import {
3
- DBIChatInput,
4
- TDBIChatInputOmitted,
5
- } from "./types/ChatInput/ChatInput";
6
- import { DBIChatInputOptions } from "./types/ChatInput/ChatInputOptions";
7
- import { publishInteractions } from "./methods/publishInteractions";
8
- import { ClientEvents, DBIEvent, TDBIEventOmitted } from "./types/Event";
9
- import { MemoryStore } from "./utils/MemoryStore";
10
- import { hookInteractionListeners } from "./methods/hookInteractionListeners";
11
- import { Events } from "./Events";
12
- import {
13
- DBILocale,
14
- TDBILocaleConstructor,
15
- TDBILocaleString,
16
- } from "./types/other/Locale";
17
- import { DBIButton, TDBIButtonOmitted } from "./types/Components/Button";
18
- import {
19
- DBIStringSelectMenu,
20
- TDBIStringSelectMenuOmitted,
21
- } from "./types/Components/StringSelectMenu";
22
- import {
23
- DBIMessageContextMenu,
24
- TDBIMessageContextMenuOmitted,
25
- } from "./types/other/MessageContextMenu";
26
- import {
27
- DBIUserContextMenu,
28
- TDBIUserContextMenuOmitted,
29
- } from "./types/other/UserContextMenu";
30
- import { hookEventListeners } from "./methods/hookEventListeners";
31
- import eventMap from "./data/eventMap.json";
32
- import { DBIModal, TDBIModalOmitted } from "./types/Components/Modal";
33
- import * as Sharding from "discord-hybrid-sharding";
34
- import _ from "lodash";
35
- import {
36
- DBIInteractionLocale,
37
- TDBIInteractionLocaleOmitted,
38
- } from "./types/other/InteractionLocale";
39
- import { TDBIInteractions } from "./types/Interaction";
40
- import { NamespaceData, NamespaceEnums } from "../generated/namespaceData";
41
- import {
42
- DBICustomEvent,
43
- TDBICustomEventOmitted,
44
- } from "./types/other/CustomEvent";
45
- import aaq from "async-and-quick";
46
- import {
47
- DBIUserSelectMenu,
48
- TDBIUserSelectMenuOmitted,
49
- } from "./types/Components/UserSelectMenu";
50
- import {
51
- DBIMentionableSelectMenu,
52
- TDBIMentionableSelectMenuOmitted,
53
- } from "./types/Components/MentionableSelectMenu";
54
- import {
55
- DBIChannelSelectMenu,
56
- TDBIChannelSelectMenuOmitted,
57
- } from "./types/Components/ChannelSelectMenu";
58
- import {
59
- DBIRoleSelectMenu,
60
- TDBIRoleSelectMenuOmitted,
61
- } from "./types/Components/RoleSelectMenu";
62
- import { handleMessageCommands } from "./methods/handleMessageCommands";
63
- import { FakeMessageInteraction } from "./types/other/FakeMessageInteraction";
64
-
65
- export interface DBIStore {
66
- get(key: string, defaultValue?: any): Promise<any>;
67
- set(key: string, value: any): Promise<void>;
68
- delete(key: string): Promise<void>;
69
- has(key: string): Promise<boolean>;
70
- }
71
-
72
- export type TDBIClientData<TNamespace extends NamespaceEnums> = {
73
- namespace: NamespaceData[TNamespace]["clientNamespaces"];
74
- token: string;
75
- options: Discord.ClientOptions;
76
- client: Discord.Client<true>;
77
- };
78
-
79
- export type TDBIMessageCommandsActionCtx<TNamespace extends NamespaceEnums> = {
80
- interaction: FakeMessageInteraction;
81
- dbiInteraction: DBIChatInput<TNamespace>;
82
- locale: { guild?: DBILocale<TNamespace>; user: DBILocale<TNamespace> };
83
- }
84
-
85
- export type TDBIMessageCommandsPrefixesCtx = {
86
- message: Discord.Message;
87
- };
88
-
89
- export type TDBILocaleInvalidPathCtx<TNamespace extends NamespaceEnums> = {
90
- path: string;
91
- locale: DBILocale<TNamespace>;
92
- }
93
-
94
- export interface DBIConfig<TNamespace extends NamespaceEnums> {
95
- discord: {
96
- namespace: string;
97
- token: string;
98
- options: Discord.ClientOptions;
99
- }[];
100
- defaults: {
101
- locale: {
102
- name: TDBILocaleString;
103
- invalidPath(ctx: TDBILocaleInvalidPathCtx<TNamespace>): string;
104
- };
105
- directMessages: boolean;
106
- defaultMemberPermissions: Discord.PermissionsString[];
107
- messageCommands: {
108
- deferReplyContent(ctx: TDBIMessageCommandsActionCtx<TNamespace>): MessagePayload | string | Promise<MessagePayload | string>;
109
- };
110
- };
111
-
112
- sharding: "hybrid" | "default" | "off";
113
- /**
114
- * Persist store. (Default to MemoryStore thats not persis tho.)
115
- */
116
- store: DBIStore;
117
-
118
- references: {
119
- autoClear?: {
120
- check: number;
121
- ttl: number;
122
- };
123
- };
124
-
125
- inlineListeners: {
126
- autoClear?: {
127
- check: number;
128
- ttl: number;
129
- };
130
- }
131
-
132
- strict: boolean;
133
- messageCommands?: {
134
- prefixes(ctx: TDBIMessageCommandsPrefixesCtx): string[] | Promise<string[]>;
135
- typeAliases: {
136
- booleans: Record<string, boolean>;
137
- };
138
- };
139
- }
140
-
141
- export interface DBIConfigConstructor<TNamespace extends NamespaceEnums, OtherData extends Record<string, any>> {
142
- discord:
143
- | {
144
- token: string;
145
- options: Discord.ClientOptions;
146
- }
147
- | {
148
- namespace: string;
149
- token: string;
150
- options: Discord.ClientOptions;
151
- }[];
152
-
153
- defaults?: {
154
- locale?: {
155
- name?: TDBILocaleString;
156
- invalidPath?: string | ((ctx: TDBILocaleInvalidPathCtx<TNamespace>) => string);
157
- };
158
- directMessages?: boolean;
159
- defaultMemberPermissions?: Discord.PermissionsString[];
160
- messageCommands?: {
161
- deferReplyContent?: MessagePayload | string | ((ctx: TDBIMessageCommandsActionCtx<TNamespace>) => MessagePayload | string | Promise<MessagePayload | string>);
162
- };
163
- };
164
-
165
- sharding?: "hybrid" | "default" | "off";
166
- /**
167
- * Persist store. (Default to MemoryStore thats not persis tho.)
168
- */
169
- store?: DBIStore;
170
-
171
- references?: {
172
- autoClear?: {
173
- check: number;
174
- ttl: number;
175
- };
176
- };
177
-
178
- inlineListeners?: {
179
- autoClear?: {
180
- check: number;
181
- ttl: number;
182
- };
183
- };
184
-
185
- data?: {
186
- other?: OtherData;
187
- refs?: Map<string, { at: number; value: any; ttl?: number }>;
188
- };
189
-
190
- strict?: boolean;
191
-
192
- messageCommands?: {
193
- prefixes: string[] | ((ctx: TDBIMessageCommandsPrefixesCtx) => string[] | Promise<string[]>);
194
- typeAliases?: {
195
- /**
196
- * Example: {"yes": true, "no": false}
197
- */
198
- booleans?: Record<string, boolean>;
199
- };
200
- };
201
- }
202
-
203
- export interface DBIRegisterAPI<TNamespace extends NamespaceEnums> {
204
- ChatInput(cfg: TDBIChatInputOmitted<TNamespace>): DBIChatInput<TNamespace>;
205
- ChatInputOptions: DBIChatInputOptions<TNamespace>;
206
- Event(cfg: TDBIEventOmitted<TNamespace>): DBIEvent<TNamespace>;
207
- Locale(cfg: TDBILocaleConstructor<TNamespace>): DBILocale<TNamespace>;
208
- Button(cfg: TDBIButtonOmitted<TNamespace>): DBIButton<TNamespace>;
209
- StringSelectMenu(
210
- cfg: TDBIStringSelectMenuOmitted<TNamespace>
211
- ): DBIStringSelectMenu<TNamespace>;
212
- UserSelectMenu(
213
- cfg: TDBIUserSelectMenuOmitted<TNamespace>
214
- ): DBIUserSelectMenu<TNamespace>;
215
- RoleSelectMenu(
216
- cfg: TDBIRoleSelectMenuOmitted<TNamespace>
217
- ): DBIRoleSelectMenu<TNamespace>;
218
- ChannelSelectMenu(
219
- cfg: TDBIChannelSelectMenuOmitted<TNamespace>
220
- ): DBIChannelSelectMenu<TNamespace>;
221
- MentionableSelectMenu(
222
- cfg: TDBIMentionableSelectMenuOmitted<TNamespace>
223
- ): DBIMentionableSelectMenu<TNamespace>;
224
- MessageContextMenu(
225
- cfg: TDBIMessageContextMenuOmitted<TNamespace>
226
- ): DBIMessageContextMenu<TNamespace>;
227
- UserContextMenu(
228
- cfg: TDBIUserContextMenuOmitted<TNamespace>
229
- ): DBIUserContextMenu<TNamespace>;
230
- InteractionLocale(cfg: TDBIInteractionLocaleOmitted): DBIInteractionLocale;
231
- Modal(cfg: TDBIModalOmitted<TNamespace>): DBIModal<TNamespace>;
232
- CustomEvent<T extends keyof NamespaceData[TNamespace]["customEvents"]>(
233
- cfg: TDBICustomEventOmitted<TNamespace, T>
234
- ): DBICustomEvent<TNamespace, T>;
235
-
236
- createInlineEvent(cfg: Omit<TDBIEventOmitted<TNamespace>, "id">): DBIEvent<TNamespace>;
237
- createInlineButton(cfg: Omit<TDBIButtonOmitted<TNamespace>, "id" | "name">): DBIButton<TNamespace>;
238
- createInlineStringSelectMenu(
239
- cfg: Omit<TDBIStringSelectMenuOmitted<TNamespace>, "id" | "name">
240
- ): DBIStringSelectMenu<TNamespace>;
241
- createInlineUserSelectMenu(
242
- cfg: Omit<TDBIUserSelectMenuOmitted<TNamespace>, "id" | "name">
243
- ): DBIUserSelectMenu<TNamespace>;
244
- createInlineRoleSelectMenu(
245
- cfg: Omit<TDBIRoleSelectMenuOmitted<TNamespace>, "id" | "name">
246
- ): DBIRoleSelectMenu<TNamespace>;
247
- createInlineChannelSelectMenu(
248
- cfg: Omit<TDBIChannelSelectMenuOmitted<TNamespace>, "id" | "name">
249
- ): DBIChannelSelectMenu<TNamespace>;
250
- createInlineMentionableSelectMenu(
251
- cfg: Omit<TDBIMentionableSelectMenuOmitted<TNamespace>, "id" | "name">
252
- ): DBIMentionableSelectMenu<TNamespace>;
253
- createInlineModal(cfg: Omit<TDBIModalOmitted<TNamespace>, "id" | "name">): DBIModal<TNamespace>;
254
-
255
- onUnload(cb: () => Promise<any> | any): any;
256
- }
257
-
258
- export class DBI<
259
- TNamespace extends NamespaceEnums,
260
- TOtherData extends Record<string, any> = Record<string, any>
261
- > {
262
- namespace: TNamespace;
263
- config: DBIConfig<TNamespace>;
264
- data: {
265
- interactions: Discord.Collection<string, TDBIInteractions<TNamespace>>;
266
- events: Discord.Collection<string, DBIEvent<TNamespace>>;
267
- locales: Discord.Collection<string, DBILocale<TNamespace>>;
268
- interactionLocales: Discord.Collection<string, DBIInteractionLocale>;
269
- other: TOtherData;
270
- eventMap: Record<string, string[] | { [k: string]: string }>;
271
- customEventNames: Set<string>;
272
- unloaders: Set<() => void>;
273
- registers: Set<(...args: any[]) => any>;
274
- registerUnloaders: Set<(...args: any[]) => any>;
275
- refs: Map<string, { at: number; value: any; ttl?: number }>;
276
- clients: TDBIClientData<TNamespace>[] & {
277
- next(key?: string): TDBIClientData<TNamespace>;
278
- random(): TDBIClientData<TNamespace>;
279
- random(size: number): TDBIClientData<TNamespace>[];
280
- first(): TDBIClientData<TNamespace>;
281
- get(
282
- namespace: NamespaceData[TNamespace]["clientNamespaces"]
283
- ): TDBIClientData<TNamespace>;
284
- indexes: Record<string, number>;
285
- };
286
- };
287
- events: Events<TNamespace>;
288
- cluster?: Sharding.ClusterClient<Discord.Client>;
289
- private _loaded: boolean;
290
- private _hooked: boolean;
291
- constructor(namespace: TNamespace, config: DBIConfigConstructor<TNamespace, TOtherData>) {
292
- this.namespace = namespace as any;
293
- const self = this;
294
-
295
- config.store = (config.store as any) || new MemoryStore();
296
- config.defaults = {
297
- locale: (() => {
298
- const invalidPath = config.defaults?.locale?.invalidPath;
299
- return {
300
- ...(config.defaults?.locale || {}),
301
- invalidPath: (typeof invalidPath === "function" ? invalidPath : (ctx: TDBILocaleInvalidPathCtx<TNamespace>) => (invalidPath || `Invalid locale path "${ctx.path}".`)) as any
302
- }
303
- })(),
304
- defaultMemberPermissions: [],
305
- directMessages: false,
306
- ...(config.defaults || {}),
307
- messageCommands: (() => {
308
- const deferReplyContent = config.defaults?.messageCommands?.deferReplyContent
309
- return {
310
- ...(config.defaults?.messageCommands || {}),
311
- deferReplyContent: (typeof deferReplyContent === "function" ? deferReplyContent : () => (deferReplyContent || "Loading...")) as any
312
- }
313
- })(),
314
- };
315
-
316
- config.sharding = config.sharding ?? "off";
317
- config.strict = config.strict ?? true;
318
- config.references = {
319
- autoClear: undefined,
320
- ...(config.references || {}),
321
- };
322
- config.inlineListeners = {
323
- autoClear: {
324
- check: 60000,
325
- ttl: 900000,
326
- },
327
- ...(config.inlineListeners || {}),
328
- };
329
-
330
- if (config.messageCommands) {
331
- const { prefixes, typeAliases } = config.messageCommands;
332
-
333
- if (Array.isArray(prefixes) && config.strict && !prefixes.length)
334
- throw new Error("No prefixes provided.");
335
-
336
- const prefixesFn = typeof prefixes === "function" ? prefixes : () => prefixes;
337
-
338
- config.messageCommands.prefixes = prefixesFn;
339
- config.messageCommands.typeAliases = {
340
- booleans: typeAliases.booleans ?? {
341
- true: true,
342
- false: false,
343
- yes: true,
344
- no: false,
345
- y: true,
346
- n: false,
347
- "1": true,
348
- "0": false,
349
- },
350
- };
351
- }
352
-
353
- // @ts-ignore
354
- this.config = config;
355
-
356
- this.data = {
357
- interactions: new Discord.Collection(),
358
- events: new Discord.Collection(),
359
- locales: new Discord.Collection(),
360
- interactionLocales: new Discord.Collection(),
361
- other: (config.data?.other as any) ?? ({} as TOtherData),
362
- eventMap: { ...eventMap },
363
- customEventNames: new Set(),
364
- unloaders: new Set(),
365
- registers: new Set(),
366
- registerUnloaders: new Set(),
367
- refs: config.data?.refs ?? new Map(),
368
- clients: Object.assign([], {
369
- next(key = "global") {
370
- this.indexes[key] = ((this.indexes[key] ?? -1) + 1) % this.length;
371
- return this[this.indexes[key]];
372
- },
373
- random(size?: number) {
374
- if (typeof size === "number") {
375
- return this.sort(() => Math.random() - 0.5).slice(0, size);
376
- } else {
377
- return this[Math.floor(Math.random() * this.length)];
378
- }
379
- },
380
- first() {
381
- return this[0];
382
- },
383
- get(namespace: string) {
384
- return this.find((i: any) => i.namespace === namespace);
385
- },
386
- indexes: {},
387
- }) as any,
388
- };
389
-
390
- this.events = new Events(this as any);
391
-
392
- config.discord = Array.isArray(config.discord)
393
- ? config.discord
394
- : [
395
- {
396
- token: config.discord.token,
397
- options: config.discord.options,
398
- namespace: "default",
399
- },
400
- ];
401
-
402
- this.data.clients.push(...(config.discord as any));
403
- for (let clientContext of this.data.clients) {
404
- let client = new Discord.Client({
405
- ...((clientContext.options || {}) as any),
406
- ...(config.sharding == "hybrid"
407
- ? {
408
- shards: Sharding.getInfo().SHARD_LIST,
409
- shardCount: Sharding.getInfo().TOTAL_SHARDS,
410
- }
411
- : {}),
412
- });
413
- clientContext.client = client as Discord.Client<true>;
414
- }
415
-
416
- if (this.data.clients.length === 0) throw new Error("No clients provided.");
417
- if (
418
- this.data.clients.length !== 1 &&
419
- !(config.sharding && config.sharding === "off")
420
- )
421
- throw new Error("Sharding only supports 1 client.");
422
-
423
- this.cluster =
424
- config.sharding == "hybrid"
425
- ? new Sharding.ClusterClient(this.data.clients[0].client)
426
- : undefined;
427
- this._loaded = false;
428
- this._hooked = false;
429
- }
430
-
431
- private async _hookListeners() {
432
- if (this._hooked) return;
433
- const self = this;
434
- this._hooked = true;
435
- this.data.unloaders.add(hookInteractionListeners(this as any));
436
- this.data.unloaders.add(hookEventListeners(this as any));
437
- if (typeof this.config.references.autoClear !== "undefined") {
438
- this.data.unloaders.add(
439
- (() => {
440
- let interval = setInterval(() => {
441
- this.data.refs.forEach(({ at, ttl }, key) => {
442
- if (
443
- Date.now() >
444
- at + (ttl || this.config.references.autoClear.ttl)
445
- ) {
446
- this.data.refs.delete(key);
447
- }
448
- });
449
- }, this.config.references.autoClear.check);
450
- return () => {
451
- clearInterval(interval);
452
- };
453
- })()
454
- );
455
- }
456
- if (typeof this.config.inlineListeners.autoClear !== "undefined") {
457
- this.data.unloaders.add(
458
- (() => {
459
- let interval = setInterval(() => {
460
- this.data.interactions.forEach((i, key) => {
461
- if (
462
- i.ttl &&
463
- (Date.now() >
464
- i.at + (i.ttl || this.config.inlineListeners.autoClear.ttl))
465
- ) {
466
- this.data.interactions.delete(key);
467
- }
468
- });
469
- this.data.events.forEach((i, key) => {
470
- if (
471
- i.ttl &&
472
- (Date.now() >
473
- i.at + (i.ttl || this.config.inlineListeners.autoClear.ttl))
474
- ) {
475
- this.data.events.delete(key);
476
- }
477
- });
478
- }, this.config.inlineListeners.autoClear.check);
479
- return () => {
480
- clearInterval(interval);
481
- };
482
- })()
483
- );
484
- }
485
- if (typeof this.config.messageCommands !== "undefined") {
486
- this.data.unloaders.add(
487
- (() => {
488
- const { client } = this.client();
489
-
490
- function onMessage(message: Discord.Message) {
491
- handleMessageCommands(self as any, message);
492
- }
493
-
494
- client.on("messageCreate", onMessage);
495
- return () => {
496
- client.off("messageCreate", onMessage);
497
- };
498
- })()
499
- );
500
- }
501
- }
502
-
503
- private async _unhookListeners() {
504
- if (!this._hooked) return;
505
- this._hooked = false;
506
- this.data.unloaders.forEach((f) => {
507
- f();
508
- });
509
- this.data.unloaders.clear();
510
- }
511
-
512
- private async _unregisterAll() {
513
- for await (const cb of this.data.registerUnloaders) {
514
- await cb();
515
- }
516
- this.data.events.clear();
517
- this.data.interactions.clear();
518
- this.data.interactionLocales.clear();
519
- this.data.locales.clear();
520
- this.data.registerUnloaders.clear();
521
- this.data.refs.clear();
522
-
523
- this.data.customEventNames.forEach((value) => {
524
- delete this.data.eventMap[value];
525
- });
526
- this.data.customEventNames.clear();
527
- }
528
-
529
- private async _registerAll(flags: string[] = []) {
530
- const self = this;
531
- const ChatInputOptions = new DBIChatInputOptions(self);
532
-
533
- const randomInlineId = () => `inline:${Math.random().toString(36).slice(2)}`;
534
-
535
- for await (const cb of this.data.registers) {
536
- let ChatInput = function (cfg: DBIChatInput<TNamespace>) {
537
- let dbiChatInput = new DBIChatInput(self, cfg);
538
- if (self.data.interactions.has(dbiChatInput.name))
539
- throw new Error(
540
- `DBIChatInput "${dbiChatInput.name}" already loaded as "${self.data.interactions.get(dbiChatInput.name)?.type
541
- }"!`
542
- );
543
- if (!cfg.flag || flags.includes("all") || flags.includes(cfg.flag)) self.data.interactions.set(dbiChatInput.name, dbiChatInput);
544
- return dbiChatInput;
545
- };
546
- ChatInput = Object.assign(
547
- ChatInput,
548
- class {
549
- constructor(...args: any[]) {
550
- return ChatInput.apply(this, args as any);
551
- }
552
- }
553
- );
554
-
555
- let Event = function (cfg: TDBIEventOmitted<TNamespace>) {
556
- let dbiEvent = new DBIEvent(self as any, cfg);
557
- if (
558
- self.config.strict &&
559
- self.data.events.has(dbiEvent.id || dbiEvent.name)
560
- )
561
- throw new Error(
562
- `DBIEvent "${dbiEvent.id || dbiEvent.name}" already loaded!`
563
- );
564
- if (!cfg.flag || flags.includes("all") || flags.includes(cfg.flag)) self.data.events.set(dbiEvent.id || dbiEvent.name, dbiEvent);
565
- return dbiEvent;
566
- };
567
- Event = Object.assign(
568
- Event,
569
- class {
570
- constructor(...args: any[]) {
571
- return Event.apply(this, args as any);
572
- }
573
- }
574
- );
575
-
576
- let createInlineEvent = function (cfg: Omit<TDBIEventOmitted<TNamespace>, "id">) {
577
- return Event({ ...cfg, ttl: cfg?.ttl || self.config.inlineListeners.autoClear?.ttl, id: randomInlineId() } as any);
578
- }
579
-
580
- let Button = function (cfg: TDBIButtonOmitted<TNamespace>) {
581
- let dbiButton = new DBIButton(self as any, cfg);
582
- if (self.config.strict && self.data.interactions.has(dbiButton.name))
583
- throw new Error(
584
- `DBIButton "${dbiButton.name}" already loaded as "${self.data.interactions.get(dbiButton.name)?.type
585
- }"!`
586
- );
587
- if (!cfg.flag || flags.includes("all") || flags.includes(cfg.flag)) self.data.interactions.set(dbiButton.name, dbiButton as any);
588
- return dbiButton;
589
- };
590
- Button = Object.assign(
591
- Button,
592
- class {
593
- constructor(...args: any[]) {
594
- return Button.apply(this, args as any);
595
- }
596
- }
597
- );
598
-
599
- let createInlineButton = function (cfg: Omit<TDBIButtonOmitted<TNamespace>, "name" | "id">) {
600
- let id = randomInlineId();
601
- return Button({ ...cfg, ttl: cfg?.ttl || self.config.inlineListeners.autoClear?.ttl, id, name: id } as any);
602
- }
603
-
604
- let StringSelectMenu = function (
605
- cfg: TDBIStringSelectMenuOmitted<TNamespace>
606
- ) {
607
- let dbiStringSelectMenu = new DBIStringSelectMenu(self as any, cfg);
608
- if (
609
- self.config.strict &&
610
- self.data.interactions.has(dbiStringSelectMenu.name)
611
- )
612
- throw new Error(
613
- `DBIStringSelectMenu "${dbiStringSelectMenu.name
614
- }" already loaded as "${self.data.interactions.get(dbiStringSelectMenu.name)?.type
615
- }"!`
616
- );
617
- if (!cfg.flag || flags.includes("all") || flags.includes(cfg.flag)) self.data.interactions.set(
618
- dbiStringSelectMenu.name,
619
- dbiStringSelectMenu as any
620
- );
621
- return dbiStringSelectMenu;
622
- };
623
- StringSelectMenu = Object.assign(
624
- StringSelectMenu,
625
- class {
626
- constructor(...args: any[]) {
627
- return StringSelectMenu.apply(this, args as any);
628
- }
629
- }
630
- );
631
-
632
- let createInlineStringSelectMenu = function (cfg: Omit<TDBIStringSelectMenuOmitted<TNamespace>, "id" | "name">) {
633
- let id = randomInlineId();
634
- return StringSelectMenu({ ...cfg, ttl: cfg?.ttl || self.config.inlineListeners.autoClear?.ttl, id, name: id } as any);
635
- }
636
-
637
- let UserSelectMenu = function (
638
- cfg: TDBIUserSelectMenuOmitted<TNamespace>
639
- ) {
640
- let dbiUserSelectMenu = new DBIUserSelectMenu(self as any, cfg);
641
- if (
642
- self.config.strict &&
643
- self.data.interactions.has(dbiUserSelectMenu.name)
644
- )
645
- throw new Error(
646
- `DBIUserSelectMenu "${dbiUserSelectMenu.name}" already loaded as "${self.data.interactions.get(dbiUserSelectMenu.name)?.type
647
- }"!`
648
- );
649
- if (!cfg.flag || flags.includes("all") || flags.includes(cfg.flag)) self.data.interactions.set(
650
- dbiUserSelectMenu.name,
651
- dbiUserSelectMenu as any
652
- );
653
- return dbiUserSelectMenu;
654
- };
655
- UserSelectMenu = Object.assign(
656
- UserSelectMenu,
657
- class {
658
- constructor(...args: any[]) {
659
- return UserSelectMenu.apply(this, args as any);
660
- }
661
- }
662
- );
663
-
664
- let createInlineUserSelectMenu = function (cfg: Omit<TDBIUserSelectMenuOmitted<TNamespace>, "id" | "name">) {
665
- let id = randomInlineId();
666
- return UserSelectMenu({ ...cfg, ttl: cfg?.ttl || self.config.inlineListeners.autoClear?.ttl, id, name: id } as any);
667
- }
668
-
669
- let RoleSelectMenu = function (
670
- cfg: TDBIRoleSelectMenuOmitted<TNamespace>
671
- ) {
672
- let dbiRoleSelectMenu = new DBIRoleSelectMenu(self as any, cfg);
673
- if (
674
- self.config.strict &&
675
- self.data.interactions.has(dbiRoleSelectMenu.name)
676
- )
677
- throw new Error(
678
- `DBIRoleSelectMenu "${dbiRoleSelectMenu.name}" already loaded as "${self.data.interactions.get(dbiRoleSelectMenu.name)?.type
679
- }"!`
680
- );
681
- if (!cfg.flag || flags.includes("all") || flags.includes(cfg.flag)) self.data.interactions.set(
682
- dbiRoleSelectMenu.name,
683
- dbiRoleSelectMenu as any
684
- );
685
- return dbiRoleSelectMenu;
686
- };
687
- RoleSelectMenu = Object.assign(
688
- RoleSelectMenu,
689
- class {
690
- constructor(...args: any[]) {
691
- return RoleSelectMenu.apply(this, args as any);
692
- }
693
- }
694
- );
695
-
696
- let createInlineRoleSelectMenu = function (cfg: Omit<TDBIRoleSelectMenuOmitted<TNamespace>, "id" | "name">) {
697
- let id = randomInlineId();
698
- return RoleSelectMenu({ ...cfg, ttl: cfg?.ttl || self.config.inlineListeners.autoClear?.ttl, id, name: id } as any);
699
- }
700
-
701
- let ChannelSelectMenu = function (
702
- cfg: TDBIChannelSelectMenuOmitted<TNamespace>
703
- ) {
704
- let dbiChannelSelectMenu = new DBIChannelSelectMenu(self as any, cfg);
705
- if (
706
- self.config.strict &&
707
- self.data.interactions.has(dbiChannelSelectMenu.name)
708
- )
709
- throw new Error(
710
- `DBIChannelSelectMenu "${dbiChannelSelectMenu.name
711
- }" already loaded as "${self.data.interactions.get(dbiChannelSelectMenu.name)?.type
712
- }"!`
713
- );
714
- if (!cfg.flag || flags.includes("all") || flags.includes(cfg.flag)) self.data.interactions.set(
715
- dbiChannelSelectMenu.name,
716
- dbiChannelSelectMenu as any
717
- );
718
- return dbiChannelSelectMenu;
719
- };
720
- ChannelSelectMenu = Object.assign(
721
- ChannelSelectMenu,
722
- class {
723
- constructor(...args: any[]) {
724
- return ChannelSelectMenu.apply(this, args as any);
725
- }
726
- }
727
- );
728
-
729
- let createInlineChannelSelectMenu = function (cfg: Omit<TDBIChannelSelectMenuOmitted<TNamespace>, "id" | "name">) {
730
- let id = randomInlineId();
731
- return ChannelSelectMenu({ ...cfg, ttl: cfg?.ttl || self.config.inlineListeners.autoClear?.ttl, id, name: id } as any);
732
- }
733
-
734
- let MentionableSelectMenu = function (
735
- cfg: TDBIMentionableSelectMenuOmitted<TNamespace>
736
- ) {
737
- let dbiMentionableSelectMenu = new DBIMentionableSelectMenu(
738
- self as any,
739
- cfg
740
- );
741
- if (
742
- self.config.strict &&
743
- self.data.interactions.has(dbiMentionableSelectMenu.name)
744
- )
745
- throw new Error(
746
- `DBIMentionableSelectMenu "${dbiMentionableSelectMenu.name
747
- }" already loaded as "${self.data.interactions.get(dbiMentionableSelectMenu.name)?.type
748
- }"!`
749
- );
750
- if (!cfg.flag || flags.includes("all") || flags.includes(cfg.flag)) self.data.interactions.set(
751
- dbiMentionableSelectMenu.name,
752
- dbiMentionableSelectMenu as any
753
- );
754
- return dbiMentionableSelectMenu;
755
- };
756
- MentionableSelectMenu = Object.assign(
757
- MentionableSelectMenu,
758
- class {
759
- constructor(...args: any[]) {
760
- return MentionableSelectMenu.apply(this, args as any);
761
- }
762
- }
763
- );
764
-
765
- let createInlineMentionableSelectMenu = function (cfg: Omit<TDBIMentionableSelectMenuOmitted<TNamespace>, "id" | "name">) {
766
- let id = randomInlineId();
767
- return MentionableSelectMenu({ ...cfg, ttl: cfg?.ttl || self.config.inlineListeners.autoClear?.ttl, id, name: id } as any);
768
- }
769
-
770
- let MessageContextMenu = function (
771
- cfg: TDBIMessageContextMenuOmitted<TNamespace>
772
- ) {
773
- let dbiMessageContextMenu = new DBIMessageContextMenu(self as any, cfg);
774
- if (
775
- self.config.strict &&
776
- self.data.interactions.has(dbiMessageContextMenu.name)
777
- )
778
- throw new Error(
779
- `DBIMessageContextMenu "${dbiMessageContextMenu.name
780
- }" already loaded as "${self.data.interactions.get(dbiMessageContextMenu.name)?.type
781
- }"!`
782
- );
783
- if (!cfg.flag || flags.includes("all") || flags.includes(cfg.flag)) self.data.interactions.set(
784
- dbiMessageContextMenu.name,
785
- dbiMessageContextMenu as any
786
- );
787
- return dbiMessageContextMenu;
788
- };
789
- MessageContextMenu = Object.assign(
790
- MessageContextMenu,
791
- class {
792
- constructor(...args: any[]) {
793
- return MessageContextMenu.apply(this, args as any);
794
- }
795
- }
796
- );
797
-
798
- let UserContextMenu = function (
799
- cfg: TDBIUserContextMenuOmitted<TNamespace>
800
- ) {
801
- let dbiUserContextMenu = new DBIUserContextMenu(self as any, cfg);
802
- if (
803
- self.config.strict &&
804
- self.data.interactions.has(dbiUserContextMenu.name)
805
- )
806
- throw new Error(
807
- `DBIUserContextMenu "${dbiUserContextMenu.name
808
- }" already loaded as "${self.data.interactions.get(dbiUserContextMenu.name)?.type
809
- }"!`
810
- );
811
- if (!cfg.flag || flags.includes("all") || flags.includes(cfg.flag)) self.data.interactions.set(
812
- dbiUserContextMenu.name,
813
- dbiUserContextMenu as any
814
- );
815
- return dbiUserContextMenu;
816
- };
817
- UserContextMenu = Object.assign(
818
- UserContextMenu,
819
- class {
820
- constructor(...args: any[]) {
821
- return UserContextMenu.apply(this, args as any);
822
- }
823
- }
824
- );
825
-
826
- let Modal = function (cfg: TDBIModalOmitted<TNamespace>) {
827
- let dbiModal = new DBIModal(self as any, cfg);
828
- if (self.config.strict && self.data.interactions.has(dbiModal.name))
829
- throw new Error(
830
- `DBIModal "${dbiModal.name}" already loaded as "${self.data.interactions.get(dbiModal.name)?.type
831
- }"!`
832
- );
833
- if (!cfg.flag || flags.includes("all") || flags.includes(cfg.flag)) self.data.interactions.set(dbiModal.name, dbiModal as any);
834
- return dbiModal;
835
- };
836
- Modal = Object.assign(
837
- Modal,
838
- class {
839
- constructor(...args: any[]) {
840
- return Modal.apply(this, args as any);
841
- }
842
- }
843
- );
844
-
845
- let createInlineModal = function (cfg: Omit<TDBIModalOmitted<TNamespace>, "name" | "id">) {
846
- let id = randomInlineId();
847
- return Modal({ ...cfg, ttl: cfg?.ttl || self.config.inlineListeners.autoClear?.ttl, id, name: id } as any);
848
- }
849
-
850
- let Locale = function (cfg: TDBILocaleConstructor<TNamespace>) {
851
- let dbiLocale = new DBILocale(self as any, cfg);
852
- if (
853
- self.config.strict &&
854
- self.data.interactionLocales.has(dbiLocale.name)
855
- )
856
- throw new Error(`DBILocale "${dbiLocale.name}" already loaded!`);
857
- if (self.data.locales.has(dbiLocale.name))
858
- dbiLocale.mergeLocale(self.data.locales.get(dbiLocale.name));
859
- if (!cfg.flag || flags.includes("all") || flags.includes(cfg.flag)) self.data.locales.set(dbiLocale.name, dbiLocale);
860
- return dbiLocale;
861
- };
862
- Locale = Object.assign(
863
- Locale,
864
- class {
865
- constructor(...args: any[]) {
866
- return Locale.apply(this, args as any);
867
- }
868
- }
869
- );
870
-
871
- let CustomEvent = function (cfg: TDBICustomEventOmitted<TNamespace>) {
872
- let dbiCustomEvent = new DBICustomEvent(self, cfg) as any;
873
- if (self.config.strict && self.data.eventMap[dbiCustomEvent.name])
874
- throw new Error(
875
- `DBICustomEvent "${dbiCustomEvent.name}" already loaded!`
876
- );
877
- self.data.eventMap[dbiCustomEvent.name] = dbiCustomEvent.map;
878
- self.data.customEventNames.add(dbiCustomEvent.name);
879
- return dbiCustomEvent;
880
- };
881
- CustomEvent = Object.assign(
882
- CustomEvent,
883
- class {
884
- constructor(...args: any[]) {
885
- return CustomEvent.apply(this, args as any);
886
- }
887
- }
888
- );
889
-
890
- let InteractionLocale = function (cfg: TDBIInteractionLocaleOmitted) {
891
- let dbiInteractionLocale = new DBIInteractionLocale(self, cfg);
892
- if (
893
- self.config.strict &&
894
- self.data.interactionLocales.has(dbiInteractionLocale.name)
895
- )
896
- throw new Error(
897
- `DBIInteractionLocale "${dbiInteractionLocale.name}" already loaded!`
898
- );
899
- if (!cfg.flag || flags.includes("all") || flags.includes(cfg.flag)) self.data.interactionLocales.set(
900
- dbiInteractionLocale.name,
901
- dbiInteractionLocale
902
- );
903
- return dbiInteractionLocale;
904
- };
905
- InteractionLocale = Object.assign(
906
- InteractionLocale,
907
- class {
908
- constructor(...args: any[]) {
909
- return InteractionLocale.apply(this, args as any);
910
- }
911
- }
912
- );
913
-
914
- await cb({
915
- ChatInput,
916
- Event,
917
- ChatInputOptions,
918
- Locale,
919
- Button,
920
- StringSelectMenu,
921
- UserSelectMenu,
922
- RoleSelectMenu,
923
- ChannelSelectMenu,
924
- MentionableSelectMenu,
925
- MessageContextMenu,
926
- UserContextMenu,
927
- CustomEvent,
928
- Modal,
929
- InteractionLocale,
930
- createInlineButton,
931
- createInlineEvent,
932
- createInlineStringSelectMenu,
933
- createInlineUserSelectMenu,
934
- createInlineRoleSelectMenu,
935
- createInlineChannelSelectMenu,
936
- createInlineMentionableSelectMenu,
937
- createInlineModal,
938
- onUnload(cb: () => Promise<any> | any) {
939
- self.data.registerUnloaders.add(cb);
940
- },
941
- });
942
- }
943
- self.data.interactions.sort((a, b) => b.name.length - a.name.length);
944
- }
945
-
946
- emit<
947
- TEventName extends keyof (NamespaceData[TNamespace]["customEvents"] &
948
- ClientEvents)
949
- >(
950
- name: TEventName,
951
- args: (NamespaceData[TNamespace]["customEvents"] & ClientEvents)[TEventName]
952
- ): void {
953
- this.data.clients.forEach((d) =>
954
- d.client.emit(name as any, { ...args, _DIRECT_: true } as any)
955
- );
956
- }
957
-
958
- /**
959
- * this.data.interactions.get(name)
960
- */
961
- interaction<
962
- TInteractionName extends keyof NamespaceData[TNamespace]["interactionMapping"]
963
- >(
964
- name: TInteractionName
965
- ): NamespaceData[TNamespace]["interactionMapping"][TInteractionName] {
966
- return this.data.interactions.get(name as any) as any;
967
- }
968
-
969
- client<TClientName extends NamespaceData[TNamespace]["clientNamespaces"]>(
970
- name?: TClientName
971
- ): TDBIClientData<TNamespace> {
972
- return name ? this.data.clients.get(name) : this.data.clients.first();
973
- }
974
- /**
975
- * this.data.events.get(name)
976
- */
977
- event<TEventName extends NamespaceData[TNamespace]["eventNames"]>(
978
- name: TEventName
979
- ): DBIEvent<TNamespace> {
980
- return this.data.events.get(name);
981
- }
982
-
983
- /**
984
- * this.data.locales.get(name)
985
- */
986
- locale<TLocaleName extends NamespaceData[TNamespace]["localeNames"]>(
987
- name: TLocaleName
988
- ): DBILocale<TNamespace> {
989
- return this.data.locales.get(name) as any;
990
- }
991
-
992
- /**
993
- * Shorthands for modifying `dbi.data.other`
994
- */
995
- get<K extends keyof TOtherData>(
996
- k: K,
997
- defaultValue?: TOtherData[K]
998
- ): TOtherData[K] {
999
- if (defaultValue && !this.has(k as any)) {
1000
- this.set(k, defaultValue);
1001
- return defaultValue;
1002
- }
1003
- return _.get(this.data.other, k);
1004
- }
1005
-
1006
- /**
1007
- * Shorthands for modifying `dbi.data.other`
1008
- */
1009
- set<K extends keyof TOtherData>(k: K, v: TOtherData[K]): any {
1010
- this.data.other = _.set(this.data.other as any, k, v);
1011
- }
1012
-
1013
- /**
1014
- * Shorthands for modifying `dbi.data.other`
1015
- */
1016
- has(k: string): boolean {
1017
- return _.has(this.data.other, k as any);
1018
- }
1019
-
1020
- /**
1021
- * Shorthands for modifying `dbi.data.other`
1022
- */
1023
- delete(k: string): boolean {
1024
- return _.unset(this.data.other, k);
1025
- }
1026
-
1027
- async login(): Promise<any> {
1028
- await aaq.quickForEach(this.data.clients, async (clientContext) => {
1029
- await clientContext.client.login(
1030
- this.config.sharding == "default" ? null : clientContext.token
1031
- );
1032
- });
1033
- this.events.trigger("clientsReady", undefined, true);
1034
- }
1035
-
1036
- async register(cb: (api: DBIRegisterAPI<TNamespace>) => void): Promise<any> {
1037
- this.data.registers.add(cb);
1038
- }
1039
-
1040
- async load(...flags: string[]): Promise<boolean> {
1041
- if (this._loaded) return false;
1042
- await this._registerAll(flags);
1043
- await this._hookListeners();
1044
- this._loaded = true;
1045
- return true;
1046
- }
1047
-
1048
- async unload(): Promise<boolean> {
1049
- if (!this._loaded) return false;
1050
- await this._unregisterAll();
1051
- await this._unhookListeners();
1052
- this._loaded = false;
1053
- return true;
1054
- }
1055
-
1056
- get loaded(): boolean {
1057
- return this._loaded;
1058
- }
1059
-
1060
- async publish(type: "Global", clear?: boolean): Promise<any>;
1061
- async publish(type: "Guild", guildId: string, clear?: boolean): Promise<any>;
1062
-
1063
- async publish(...args: any[]) {
1064
- let interactions = this.data.interactions.filter(
1065
- (i) =>
1066
- i.type == "ChatInput" ||
1067
- i.type == "MessageContextMenu" ||
1068
- i.type == "UserContextMenu"
1069
- ) as any;
1070
- switch (args[0]) {
1071
- case "Global": {
1072
- return await publishInteractions(
1073
- this.data.clients,
1074
- args[1] ? new Discord.Collection() : interactions,
1075
- this.data.interactionLocales,
1076
- args[0]
1077
- );
1078
- }
1079
- case "Guild": {
1080
- return await publishInteractions(
1081
- this.data.clients,
1082
- args[2] ? new Discord.Collection() : interactions,
1083
- this.data.interactionLocales,
1084
- args[0],
1085
- args[1]
1086
- );
1087
- }
1088
- }
1089
- }
1090
- }
1
+ import Discord, { MessagePayload } from "discord.js";
2
+ import {
3
+ DBIChatInput,
4
+ TDBIChatInputOmitted,
5
+ } from "./types/ChatInput/ChatInput";
6
+ import { DBIChatInputOptions } from "./types/ChatInput/ChatInputOptions";
7
+ import { publishInteractions } from "./methods/publishInteractions";
8
+ import { ClientEvents, DBIEvent, TDBIEventOmitted } from "./types/Event";
9
+ import { MemoryStore } from "./utils/MemoryStore";
10
+ import { hookInteractionListeners } from "./methods/hookInteractionListeners";
11
+ import { Events } from "./Events";
12
+ import {
13
+ DBILocale,
14
+ TDBILocaleConstructor,
15
+ TDBILocaleString,
16
+ } from "./types/other/Locale";
17
+ import { DBIButton, TDBIButtonOmitted } from "./types/Components/Button";
18
+ import {
19
+ DBIStringSelectMenu,
20
+ TDBIStringSelectMenuOmitted,
21
+ } from "./types/Components/StringSelectMenu";
22
+ import {
23
+ DBIMessageContextMenu,
24
+ TDBIMessageContextMenuOmitted,
25
+ } from "./types/other/MessageContextMenu";
26
+ import {
27
+ DBIUserContextMenu,
28
+ TDBIUserContextMenuOmitted,
29
+ } from "./types/other/UserContextMenu";
30
+ import { hookEventListeners } from "./methods/hookEventListeners";
31
+ import eventMap from "./data/eventMap.json";
32
+ import { DBIModal, TDBIModalOmitted } from "./types/Components/Modal";
33
+ import * as Sharding from "discord-hybrid-sharding";
34
+ import _ from "lodash";
35
+ import {
36
+ DBIInteractionLocale,
37
+ TDBIInteractionLocaleOmitted,
38
+ } from "./types/other/InteractionLocale";
39
+ import { TDBIInteractions } from "./types/Interaction";
40
+ import { NamespaceData, NamespaceEnums } from "../generated/namespaceData";
41
+ import {
42
+ DBICustomEvent,
43
+ TDBICustomEventOmitted,
44
+ } from "./types/other/CustomEvent";
45
+ import aaq from "async-and-quick";
46
+ import {
47
+ DBIUserSelectMenu,
48
+ TDBIUserSelectMenuOmitted,
49
+ } from "./types/Components/UserSelectMenu";
50
+ import {
51
+ DBIMentionableSelectMenu,
52
+ TDBIMentionableSelectMenuOmitted,
53
+ } from "./types/Components/MentionableSelectMenu";
54
+ import {
55
+ DBIChannelSelectMenu,
56
+ TDBIChannelSelectMenuOmitted,
57
+ } from "./types/Components/ChannelSelectMenu";
58
+ import {
59
+ DBIRoleSelectMenu,
60
+ TDBIRoleSelectMenuOmitted,
61
+ } from "./types/Components/RoleSelectMenu";
62
+ import { handleMessageCommands } from "./methods/handleMessageCommands";
63
+ import { FakeMessageInteraction } from "./types/other/FakeMessageInteraction";
64
+
65
+ export interface DBIStore {
66
+ get(key: string, defaultValue?: any): Promise<any>;
67
+ set(key: string, value: any): Promise<void>;
68
+ delete(key: string): Promise<void>;
69
+ has(key: string): Promise<boolean>;
70
+ }
71
+
72
+ export type TDBIClientData<TNamespace extends NamespaceEnums> = {
73
+ namespace: NamespaceData[TNamespace]["clientNamespaces"];
74
+ token: string;
75
+ options: Discord.ClientOptions;
76
+ client: Discord.Client<true>;
77
+ };
78
+
79
+ export type TDBIMessageCommandsActionCtx<TNamespace extends NamespaceEnums> = {
80
+ interaction: FakeMessageInteraction;
81
+ dbiInteraction: DBIChatInput<TNamespace>;
82
+ locale: { guild?: DBILocale<TNamespace>; user: DBILocale<TNamespace> };
83
+ }
84
+
85
+ export type TDBIMessageCommandsPrefixesCtx = {
86
+ message: Discord.Message;
87
+ };
88
+
89
+ export type TDBILocaleInvalidPathCtx<TNamespace extends NamespaceEnums> = {
90
+ path: string;
91
+ locale: DBILocale<TNamespace>;
92
+ }
93
+
94
+ export interface DBIConfig<TNamespace extends NamespaceEnums> {
95
+ discord: {
96
+ namespace: string;
97
+ token: string;
98
+ options: Discord.ClientOptions;
99
+ }[];
100
+ defaults: {
101
+ locale: {
102
+ name: TDBILocaleString;
103
+ invalidPath(ctx: TDBILocaleInvalidPathCtx<TNamespace>): string;
104
+ };
105
+ directMessages: boolean;
106
+ defaultMemberPermissions: Discord.PermissionsString[];
107
+ messageCommands: {
108
+ deferReplyContent(ctx: TDBIMessageCommandsActionCtx<TNamespace>): MessagePayload | string | Promise<MessagePayload | string>;
109
+ };
110
+ };
111
+
112
+ sharding: "hybrid" | "default" | "off";
113
+ /**
114
+ * Persist store. (Default to MemoryStore thats not persis tho.)
115
+ */
116
+ store: DBIStore;
117
+
118
+ references: {
119
+ autoClear?: {
120
+ check: number;
121
+ ttl: number;
122
+ };
123
+ };
124
+
125
+ inlineListeners: {
126
+ autoClear?: {
127
+ check: number;
128
+ ttl: number;
129
+ };
130
+ }
131
+
132
+ strict: boolean;
133
+ messageCommands?: {
134
+ prefixes(ctx: TDBIMessageCommandsPrefixesCtx): string[] | Promise<string[]>;
135
+ typeAliases: {
136
+ booleans: Record<string, boolean>;
137
+ };
138
+ };
139
+ }
140
+
141
+ export interface DBIConfigConstructor<TNamespace extends NamespaceEnums, OtherData extends Record<string, any>> {
142
+ discord:
143
+ | {
144
+ token: string;
145
+ options: Discord.ClientOptions;
146
+ }
147
+ | {
148
+ namespace: string;
149
+ token: string;
150
+ options: Discord.ClientOptions;
151
+ }[];
152
+
153
+ defaults?: {
154
+ locale?: {
155
+ name?: TDBILocaleString;
156
+ invalidPath?: string | ((ctx: TDBILocaleInvalidPathCtx<TNamespace>) => string);
157
+ };
158
+ directMessages?: boolean;
159
+ defaultMemberPermissions?: Discord.PermissionsString[];
160
+ messageCommands?: {
161
+ deferReplyContent?: MessagePayload | string | ((ctx: TDBIMessageCommandsActionCtx<TNamespace>) => MessagePayload | string | Promise<MessagePayload | string>);
162
+ };
163
+ };
164
+
165
+ sharding?: "hybrid" | "default" | "off";
166
+ /**
167
+ * Persist store. (Default to MemoryStore thats not persis tho.)
168
+ */
169
+ store?: DBIStore;
170
+
171
+ references?: {
172
+ autoClear?: {
173
+ check: number;
174
+ ttl: number;
175
+ };
176
+ };
177
+
178
+ inlineListeners?: {
179
+ autoClear?: {
180
+ check: number;
181
+ ttl: number;
182
+ };
183
+ };
184
+
185
+ data?: {
186
+ other?: OtherData;
187
+ refs?: Map<string, { at: number; value: any; ttl?: number }>;
188
+ };
189
+
190
+ strict?: boolean;
191
+
192
+ messageCommands?: {
193
+ prefixes: string[] | ((ctx: TDBIMessageCommandsPrefixesCtx) => string[] | Promise<string[]>);
194
+ typeAliases?: {
195
+ /**
196
+ * Example: {"yes": true, "no": false}
197
+ */
198
+ booleans?: Record<string, boolean>;
199
+ };
200
+ };
201
+ }
202
+
203
+ export interface DBIRegisterAPI<TNamespace extends NamespaceEnums> {
204
+ ChatInput(cfg: TDBIChatInputOmitted<TNamespace>): DBIChatInput<TNamespace>;
205
+ ChatInputOptions: DBIChatInputOptions<TNamespace>;
206
+ Event(cfg: TDBIEventOmitted<TNamespace>): DBIEvent<TNamespace>;
207
+ Locale(cfg: TDBILocaleConstructor<TNamespace>): DBILocale<TNamespace>;
208
+ Button(cfg: TDBIButtonOmitted<TNamespace>): DBIButton<TNamespace>;
209
+ StringSelectMenu(
210
+ cfg: TDBIStringSelectMenuOmitted<TNamespace>
211
+ ): DBIStringSelectMenu<TNamespace>;
212
+ UserSelectMenu(
213
+ cfg: TDBIUserSelectMenuOmitted<TNamespace>
214
+ ): DBIUserSelectMenu<TNamespace>;
215
+ RoleSelectMenu(
216
+ cfg: TDBIRoleSelectMenuOmitted<TNamespace>
217
+ ): DBIRoleSelectMenu<TNamespace>;
218
+ ChannelSelectMenu(
219
+ cfg: TDBIChannelSelectMenuOmitted<TNamespace>
220
+ ): DBIChannelSelectMenu<TNamespace>;
221
+ MentionableSelectMenu(
222
+ cfg: TDBIMentionableSelectMenuOmitted<TNamespace>
223
+ ): DBIMentionableSelectMenu<TNamespace>;
224
+ MessageContextMenu(
225
+ cfg: TDBIMessageContextMenuOmitted<TNamespace>
226
+ ): DBIMessageContextMenu<TNamespace>;
227
+ UserContextMenu(
228
+ cfg: TDBIUserContextMenuOmitted<TNamespace>
229
+ ): DBIUserContextMenu<TNamespace>;
230
+ InteractionLocale(cfg: TDBIInteractionLocaleOmitted): DBIInteractionLocale;
231
+ Modal(cfg: TDBIModalOmitted<TNamespace>): DBIModal<TNamespace>;
232
+ CustomEvent<T extends keyof NamespaceData[TNamespace]["customEvents"]>(
233
+ cfg: TDBICustomEventOmitted<TNamespace, T>
234
+ ): DBICustomEvent<TNamespace, T>;
235
+
236
+ createInlineEvent(cfg: Omit<TDBIEventOmitted<TNamespace>, "id">): DBIEvent<TNamespace>;
237
+ createInlineButton(cfg: Omit<TDBIButtonOmitted<TNamespace>, "id" | "name">): DBIButton<TNamespace>;
238
+ createInlineStringSelectMenu(
239
+ cfg: Omit<TDBIStringSelectMenuOmitted<TNamespace>, "id" | "name">
240
+ ): DBIStringSelectMenu<TNamespace>;
241
+ createInlineUserSelectMenu(
242
+ cfg: Omit<TDBIUserSelectMenuOmitted<TNamespace>, "id" | "name">
243
+ ): DBIUserSelectMenu<TNamespace>;
244
+ createInlineRoleSelectMenu(
245
+ cfg: Omit<TDBIRoleSelectMenuOmitted<TNamespace>, "id" | "name">
246
+ ): DBIRoleSelectMenu<TNamespace>;
247
+ createInlineChannelSelectMenu(
248
+ cfg: Omit<TDBIChannelSelectMenuOmitted<TNamespace>, "id" | "name">
249
+ ): DBIChannelSelectMenu<TNamespace>;
250
+ createInlineMentionableSelectMenu(
251
+ cfg: Omit<TDBIMentionableSelectMenuOmitted<TNamespace>, "id" | "name">
252
+ ): DBIMentionableSelectMenu<TNamespace>;
253
+ createInlineModal(cfg: Omit<TDBIModalOmitted<TNamespace>, "id" | "name">): DBIModal<TNamespace>;
254
+
255
+ onUnload(cb: () => Promise<any> | any): any;
256
+ }
257
+
258
+ export class DBI<
259
+ TNamespace extends NamespaceEnums,
260
+ TOtherData extends Record<string, any> = Record<string, any>
261
+ > {
262
+ namespace: TNamespace;
263
+ config: DBIConfig<TNamespace>;
264
+ data: {
265
+ interactions: Discord.Collection<string, TDBIInteractions<TNamespace>>;
266
+ events: Discord.Collection<string, DBIEvent<TNamespace>>;
267
+ locales: Discord.Collection<string, DBILocale<TNamespace>>;
268
+ interactionLocales: Discord.Collection<string, DBIInteractionLocale>;
269
+ other: TOtherData;
270
+ eventMap: Record<string, string[] | { [k: string]: string }>;
271
+ customEventNames: Set<string>;
272
+ unloaders: Set<() => void>;
273
+ registers: Set<(...args: any[]) => any>;
274
+ registerUnloaders: Set<(...args: any[]) => any>;
275
+ refs: Map<string, { at: number; value: any; ttl?: number }>;
276
+ clients: TDBIClientData<TNamespace>[] & {
277
+ next(key?: string): TDBIClientData<TNamespace>;
278
+ random(): TDBIClientData<TNamespace>;
279
+ random(size: number): TDBIClientData<TNamespace>[];
280
+ first(): TDBIClientData<TNamespace>;
281
+ get(
282
+ namespace: NamespaceData[TNamespace]["clientNamespaces"]
283
+ ): TDBIClientData<TNamespace>;
284
+ indexes: Record<string, number>;
285
+ };
286
+ };
287
+ events: Events<TNamespace>;
288
+ cluster?: Sharding.ClusterClient<Discord.Client>;
289
+ private _loaded: boolean;
290
+ private _hooked: boolean;
291
+ constructor(namespace: TNamespace, config: DBIConfigConstructor<TNamespace, TOtherData>) {
292
+ this.namespace = namespace as any;
293
+ const self = this;
294
+
295
+ config.store = (config.store as any) || new MemoryStore();
296
+ config.defaults = {
297
+ locale: (() => {
298
+ const invalidPath = config.defaults?.locale?.invalidPath;
299
+ return {
300
+ ...(config.defaults?.locale || {}),
301
+ invalidPath: (typeof invalidPath === "function" ? invalidPath : (ctx: TDBILocaleInvalidPathCtx<TNamespace>) => (invalidPath || `Invalid locale path "${ctx.path}".`)) as any
302
+ }
303
+ })(),
304
+ defaultMemberPermissions: [],
305
+ directMessages: false,
306
+ ...(config.defaults || {}),
307
+ messageCommands: (() => {
308
+ const deferReplyContent = config.defaults?.messageCommands?.deferReplyContent
309
+ return {
310
+ ...(config.defaults?.messageCommands || {}),
311
+ deferReplyContent: (typeof deferReplyContent === "function" ? deferReplyContent : () => (deferReplyContent || "Loading...")) as any
312
+ }
313
+ })(),
314
+ };
315
+
316
+ config.sharding = config.sharding ?? "off";
317
+ config.strict = config.strict ?? true;
318
+ config.references = {
319
+ autoClear: undefined,
320
+ ...(config.references || {}),
321
+ };
322
+ config.inlineListeners = {
323
+ autoClear: {
324
+ check: 60000,
325
+ ttl: 900000,
326
+ },
327
+ ...(config.inlineListeners || {}),
328
+ };
329
+
330
+ if (config.messageCommands) {
331
+ const { prefixes, typeAliases } = config.messageCommands;
332
+
333
+ if (Array.isArray(prefixes) && config.strict && !prefixes.length)
334
+ throw new Error("No prefixes provided.");
335
+
336
+ const prefixesFn = typeof prefixes === "function" ? prefixes : () => prefixes;
337
+
338
+ config.messageCommands.prefixes = prefixesFn;
339
+ config.messageCommands.typeAliases = {
340
+ booleans: typeAliases.booleans ?? {
341
+ true: true,
342
+ false: false,
343
+ yes: true,
344
+ no: false,
345
+ y: true,
346
+ n: false,
347
+ "1": true,
348
+ "0": false,
349
+ },
350
+ };
351
+ }
352
+
353
+ // @ts-ignore
354
+ this.config = config;
355
+
356
+ this.data = {
357
+ interactions: new Discord.Collection(),
358
+ events: new Discord.Collection(),
359
+ locales: new Discord.Collection(),
360
+ interactionLocales: new Discord.Collection(),
361
+ other: (config.data?.other as any) ?? ({} as TOtherData),
362
+ eventMap: { ...eventMap },
363
+ customEventNames: new Set(),
364
+ unloaders: new Set(),
365
+ registers: new Set(),
366
+ registerUnloaders: new Set(),
367
+ refs: config.data?.refs ?? new Map(),
368
+ clients: Object.assign([], {
369
+ next(key = "global") {
370
+ this.indexes[key] = ((this.indexes[key] ?? -1) + 1) % this.length;
371
+ return this[this.indexes[key]];
372
+ },
373
+ random(size?: number) {
374
+ if (typeof size === "number") {
375
+ return this.sort(() => Math.random() - 0.5).slice(0, size);
376
+ } else {
377
+ return this[Math.floor(Math.random() * this.length)];
378
+ }
379
+ },
380
+ first() {
381
+ return this[0];
382
+ },
383
+ get(namespace: string) {
384
+ return this.find((i: any) => i.namespace === namespace);
385
+ },
386
+ indexes: {},
387
+ }) as any,
388
+ };
389
+
390
+ this.events = new Events(this as any);
391
+
392
+ config.discord = Array.isArray(config.discord)
393
+ ? config.discord
394
+ : [
395
+ {
396
+ token: config.discord.token,
397
+ options: config.discord.options,
398
+ namespace: "default",
399
+ },
400
+ ];
401
+
402
+ this.data.clients.push(...(config.discord as any));
403
+ for (let clientContext of this.data.clients) {
404
+ let client = new Discord.Client({
405
+ ...((clientContext.options || {}) as any),
406
+ ...(config.sharding == "hybrid"
407
+ ? {
408
+ shards: Sharding.getInfo().SHARD_LIST,
409
+ shardCount: Sharding.getInfo().TOTAL_SHARDS,
410
+ }
411
+ : {}),
412
+ });
413
+ clientContext.client = client as Discord.Client<true>;
414
+ }
415
+
416
+ if (this.data.clients.length === 0) throw new Error("No clients provided.");
417
+ if (
418
+ this.data.clients.length !== 1 &&
419
+ !(config.sharding && config.sharding === "off")
420
+ )
421
+ throw new Error("Sharding only supports 1 client.");
422
+
423
+ this.cluster =
424
+ config.sharding == "hybrid"
425
+ ? new Sharding.ClusterClient(this.data.clients[0].client)
426
+ : undefined;
427
+ this._loaded = false;
428
+ this._hooked = false;
429
+ }
430
+
431
+ private async _hookListeners() {
432
+ if (this._hooked) return;
433
+ const self = this;
434
+ this._hooked = true;
435
+ this.data.unloaders.add(hookInteractionListeners(this as any));
436
+ this.data.unloaders.add(hookEventListeners(this as any));
437
+ if (typeof this.config.references.autoClear !== "undefined") {
438
+ this.data.unloaders.add(
439
+ (() => {
440
+ let interval = setInterval(() => {
441
+ this.data.refs.forEach(({ at, ttl }, key) => {
442
+ if (
443
+ Date.now() >
444
+ at + (ttl || this.config.references.autoClear.ttl)
445
+ ) {
446
+ this.data.refs.delete(key);
447
+ }
448
+ });
449
+ }, this.config.references.autoClear.check);
450
+ return () => {
451
+ clearInterval(interval);
452
+ };
453
+ })()
454
+ );
455
+ }
456
+ if (typeof this.config.inlineListeners.autoClear !== "undefined") {
457
+ this.data.unloaders.add(
458
+ (() => {
459
+ let interval = setInterval(() => {
460
+ this.data.interactions.forEach((i, key) => {
461
+ if (
462
+ i.ttl &&
463
+ (Date.now() >
464
+ i.at + (i.ttl || this.config.inlineListeners.autoClear.ttl))
465
+ ) {
466
+ this.data.interactions.delete(key);
467
+ }
468
+ });
469
+ this.data.events.forEach((i, key) => {
470
+ if (
471
+ i.ttl &&
472
+ (Date.now() >
473
+ i.at + (i.ttl || this.config.inlineListeners.autoClear.ttl))
474
+ ) {
475
+ this.data.events.delete(key);
476
+ }
477
+ });
478
+ }, this.config.inlineListeners.autoClear.check);
479
+ return () => {
480
+ clearInterval(interval);
481
+ };
482
+ })()
483
+ );
484
+ }
485
+ if (typeof this.config.messageCommands !== "undefined") {
486
+ this.data.unloaders.add(
487
+ (() => {
488
+ const { client } = this.client();
489
+
490
+ function onMessage(message: Discord.Message) {
491
+ handleMessageCommands(self as any, message);
492
+ }
493
+
494
+ client.on("messageCreate", onMessage);
495
+ return () => {
496
+ client.off("messageCreate", onMessage);
497
+ };
498
+ })()
499
+ );
500
+ }
501
+ }
502
+
503
+ private async _unhookListeners() {
504
+ if (!this._hooked) return;
505
+ this._hooked = false;
506
+ this.data.unloaders.forEach((f) => {
507
+ f();
508
+ });
509
+ this.data.unloaders.clear();
510
+ }
511
+
512
+ private async _unregisterAll() {
513
+ for await (const cb of this.data.registerUnloaders) {
514
+ await cb();
515
+ }
516
+ this.data.events.clear();
517
+ this.data.interactions.clear();
518
+ this.data.interactionLocales.clear();
519
+ this.data.locales.clear();
520
+ this.data.registerUnloaders.clear();
521
+ this.data.refs.clear();
522
+
523
+ this.data.customEventNames.forEach((value) => {
524
+ delete this.data.eventMap[value];
525
+ });
526
+ this.data.customEventNames.clear();
527
+ }
528
+
529
+ private async _registerAll(flags: string[] = []) {
530
+ const self = this;
531
+ const ChatInputOptions = new DBIChatInputOptions(self);
532
+
533
+ const randomInlineId = () => `inline:${Math.random().toString(36).slice(2)}`;
534
+
535
+ for await (const cb of this.data.registers) {
536
+ let ChatInput = function (cfg: DBIChatInput<TNamespace>) {
537
+ let dbiChatInput = new DBIChatInput(self, cfg);
538
+ if (self.data.interactions.has(dbiChatInput.name))
539
+ throw new Error(
540
+ `DBIChatInput "${dbiChatInput.name}" already loaded as "${self.data.interactions.get(dbiChatInput.name)?.type
541
+ }"!`
542
+ );
543
+ if (!cfg.flag || flags.includes("all") || flags.includes(cfg.flag)) self.data.interactions.set(dbiChatInput.name, dbiChatInput);
544
+ return dbiChatInput;
545
+ };
546
+ ChatInput = Object.assign(
547
+ ChatInput,
548
+ class {
549
+ constructor(...args: any[]) {
550
+ return ChatInput.apply(this, args as any);
551
+ }
552
+ }
553
+ );
554
+
555
+ let Event = function (cfg: TDBIEventOmitted<TNamespace>) {
556
+ let dbiEvent = new DBIEvent(self as any, cfg);
557
+ if (
558
+ self.config.strict &&
559
+ self.data.events.has(dbiEvent.id || dbiEvent.name)
560
+ )
561
+ throw new Error(
562
+ `DBIEvent "${dbiEvent.id || dbiEvent.name}" already loaded!`
563
+ );
564
+ if (!cfg.flag || flags.includes("all") || flags.includes(cfg.flag)) self.data.events.set(dbiEvent.id || dbiEvent.name, dbiEvent);
565
+ return dbiEvent;
566
+ };
567
+ Event = Object.assign(
568
+ Event,
569
+ class {
570
+ constructor(...args: any[]) {
571
+ return Event.apply(this, args as any);
572
+ }
573
+ }
574
+ );
575
+
576
+ let createInlineEvent = function (cfg: Omit<TDBIEventOmitted<TNamespace>, "id">) {
577
+ return Event({ ...cfg, ttl: cfg?.ttl || self.config.inlineListeners.autoClear?.ttl, id: randomInlineId() } as any);
578
+ }
579
+
580
+ let Button = function (cfg: TDBIButtonOmitted<TNamespace>) {
581
+ let dbiButton = new DBIButton(self as any, cfg);
582
+ if (self.config.strict && self.data.interactions.has(dbiButton.name))
583
+ throw new Error(
584
+ `DBIButton "${dbiButton.name}" already loaded as "${self.data.interactions.get(dbiButton.name)?.type
585
+ }"!`
586
+ );
587
+ if (!cfg.flag || flags.includes("all") || flags.includes(cfg.flag)) self.data.interactions.set(dbiButton.name, dbiButton as any);
588
+ return dbiButton;
589
+ };
590
+ Button = Object.assign(
591
+ Button,
592
+ class {
593
+ constructor(...args: any[]) {
594
+ return Button.apply(this, args as any);
595
+ }
596
+ }
597
+ );
598
+
599
+ let createInlineButton = function (cfg: Omit<TDBIButtonOmitted<TNamespace>, "name" | "id">) {
600
+ let id = randomInlineId();
601
+ return Button({ ...cfg, ttl: cfg?.ttl || self.config.inlineListeners.autoClear?.ttl, id, name: id } as any);
602
+ }
603
+
604
+ let StringSelectMenu = function (
605
+ cfg: TDBIStringSelectMenuOmitted<TNamespace>
606
+ ) {
607
+ let dbiStringSelectMenu = new DBIStringSelectMenu(self as any, cfg);
608
+ if (
609
+ self.config.strict &&
610
+ self.data.interactions.has(dbiStringSelectMenu.name)
611
+ )
612
+ throw new Error(
613
+ `DBIStringSelectMenu "${dbiStringSelectMenu.name
614
+ }" already loaded as "${self.data.interactions.get(dbiStringSelectMenu.name)?.type
615
+ }"!`
616
+ );
617
+ if (!cfg.flag || flags.includes("all") || flags.includes(cfg.flag)) self.data.interactions.set(
618
+ dbiStringSelectMenu.name,
619
+ dbiStringSelectMenu as any
620
+ );
621
+ return dbiStringSelectMenu;
622
+ };
623
+ StringSelectMenu = Object.assign(
624
+ StringSelectMenu,
625
+ class {
626
+ constructor(...args: any[]) {
627
+ return StringSelectMenu.apply(this, args as any);
628
+ }
629
+ }
630
+ );
631
+
632
+ let createInlineStringSelectMenu = function (cfg: Omit<TDBIStringSelectMenuOmitted<TNamespace>, "id" | "name">) {
633
+ let id = randomInlineId();
634
+ return StringSelectMenu({ ...cfg, ttl: cfg?.ttl || self.config.inlineListeners.autoClear?.ttl, id, name: id } as any);
635
+ }
636
+
637
+ let UserSelectMenu = function (
638
+ cfg: TDBIUserSelectMenuOmitted<TNamespace>
639
+ ) {
640
+ let dbiUserSelectMenu = new DBIUserSelectMenu(self as any, cfg);
641
+ if (
642
+ self.config.strict &&
643
+ self.data.interactions.has(dbiUserSelectMenu.name)
644
+ )
645
+ throw new Error(
646
+ `DBIUserSelectMenu "${dbiUserSelectMenu.name}" already loaded as "${self.data.interactions.get(dbiUserSelectMenu.name)?.type
647
+ }"!`
648
+ );
649
+ if (!cfg.flag || flags.includes("all") || flags.includes(cfg.flag)) self.data.interactions.set(
650
+ dbiUserSelectMenu.name,
651
+ dbiUserSelectMenu as any
652
+ );
653
+ return dbiUserSelectMenu;
654
+ };
655
+ UserSelectMenu = Object.assign(
656
+ UserSelectMenu,
657
+ class {
658
+ constructor(...args: any[]) {
659
+ return UserSelectMenu.apply(this, args as any);
660
+ }
661
+ }
662
+ );
663
+
664
+ let createInlineUserSelectMenu = function (cfg: Omit<TDBIUserSelectMenuOmitted<TNamespace>, "id" | "name">) {
665
+ let id = randomInlineId();
666
+ return UserSelectMenu({ ...cfg, ttl: cfg?.ttl || self.config.inlineListeners.autoClear?.ttl, id, name: id } as any);
667
+ }
668
+
669
+ let RoleSelectMenu = function (
670
+ cfg: TDBIRoleSelectMenuOmitted<TNamespace>
671
+ ) {
672
+ let dbiRoleSelectMenu = new DBIRoleSelectMenu(self as any, cfg);
673
+ if (
674
+ self.config.strict &&
675
+ self.data.interactions.has(dbiRoleSelectMenu.name)
676
+ )
677
+ throw new Error(
678
+ `DBIRoleSelectMenu "${dbiRoleSelectMenu.name}" already loaded as "${self.data.interactions.get(dbiRoleSelectMenu.name)?.type
679
+ }"!`
680
+ );
681
+ if (!cfg.flag || flags.includes("all") || flags.includes(cfg.flag)) self.data.interactions.set(
682
+ dbiRoleSelectMenu.name,
683
+ dbiRoleSelectMenu as any
684
+ );
685
+ return dbiRoleSelectMenu;
686
+ };
687
+ RoleSelectMenu = Object.assign(
688
+ RoleSelectMenu,
689
+ class {
690
+ constructor(...args: any[]) {
691
+ return RoleSelectMenu.apply(this, args as any);
692
+ }
693
+ }
694
+ );
695
+
696
+ let createInlineRoleSelectMenu = function (cfg: Omit<TDBIRoleSelectMenuOmitted<TNamespace>, "id" | "name">) {
697
+ let id = randomInlineId();
698
+ return RoleSelectMenu({ ...cfg, ttl: cfg?.ttl || self.config.inlineListeners.autoClear?.ttl, id, name: id } as any);
699
+ }
700
+
701
+ let ChannelSelectMenu = function (
702
+ cfg: TDBIChannelSelectMenuOmitted<TNamespace>
703
+ ) {
704
+ let dbiChannelSelectMenu = new DBIChannelSelectMenu(self as any, cfg);
705
+ if (
706
+ self.config.strict &&
707
+ self.data.interactions.has(dbiChannelSelectMenu.name)
708
+ )
709
+ throw new Error(
710
+ `DBIChannelSelectMenu "${dbiChannelSelectMenu.name
711
+ }" already loaded as "${self.data.interactions.get(dbiChannelSelectMenu.name)?.type
712
+ }"!`
713
+ );
714
+ if (!cfg.flag || flags.includes("all") || flags.includes(cfg.flag)) self.data.interactions.set(
715
+ dbiChannelSelectMenu.name,
716
+ dbiChannelSelectMenu as any
717
+ );
718
+ return dbiChannelSelectMenu;
719
+ };
720
+ ChannelSelectMenu = Object.assign(
721
+ ChannelSelectMenu,
722
+ class {
723
+ constructor(...args: any[]) {
724
+ return ChannelSelectMenu.apply(this, args as any);
725
+ }
726
+ }
727
+ );
728
+
729
+ let createInlineChannelSelectMenu = function (cfg: Omit<TDBIChannelSelectMenuOmitted<TNamespace>, "id" | "name">) {
730
+ let id = randomInlineId();
731
+ return ChannelSelectMenu({ ...cfg, ttl: cfg?.ttl || self.config.inlineListeners.autoClear?.ttl, id, name: id } as any);
732
+ }
733
+
734
+ let MentionableSelectMenu = function (
735
+ cfg: TDBIMentionableSelectMenuOmitted<TNamespace>
736
+ ) {
737
+ let dbiMentionableSelectMenu = new DBIMentionableSelectMenu(
738
+ self as any,
739
+ cfg
740
+ );
741
+ if (
742
+ self.config.strict &&
743
+ self.data.interactions.has(dbiMentionableSelectMenu.name)
744
+ )
745
+ throw new Error(
746
+ `DBIMentionableSelectMenu "${dbiMentionableSelectMenu.name
747
+ }" already loaded as "${self.data.interactions.get(dbiMentionableSelectMenu.name)?.type
748
+ }"!`
749
+ );
750
+ if (!cfg.flag || flags.includes("all") || flags.includes(cfg.flag)) self.data.interactions.set(
751
+ dbiMentionableSelectMenu.name,
752
+ dbiMentionableSelectMenu as any
753
+ );
754
+ return dbiMentionableSelectMenu;
755
+ };
756
+ MentionableSelectMenu = Object.assign(
757
+ MentionableSelectMenu,
758
+ class {
759
+ constructor(...args: any[]) {
760
+ return MentionableSelectMenu.apply(this, args as any);
761
+ }
762
+ }
763
+ );
764
+
765
+ let createInlineMentionableSelectMenu = function (cfg: Omit<TDBIMentionableSelectMenuOmitted<TNamespace>, "id" | "name">) {
766
+ let id = randomInlineId();
767
+ return MentionableSelectMenu({ ...cfg, ttl: cfg?.ttl || self.config.inlineListeners.autoClear?.ttl, id, name: id } as any);
768
+ }
769
+
770
+ let MessageContextMenu = function (
771
+ cfg: TDBIMessageContextMenuOmitted<TNamespace>
772
+ ) {
773
+ let dbiMessageContextMenu = new DBIMessageContextMenu(self as any, cfg);
774
+ if (
775
+ self.config.strict &&
776
+ self.data.interactions.has(dbiMessageContextMenu.name)
777
+ )
778
+ throw new Error(
779
+ `DBIMessageContextMenu "${dbiMessageContextMenu.name
780
+ }" already loaded as "${self.data.interactions.get(dbiMessageContextMenu.name)?.type
781
+ }"!`
782
+ );
783
+ if (!cfg.flag || flags.includes("all") || flags.includes(cfg.flag)) self.data.interactions.set(
784
+ dbiMessageContextMenu.name,
785
+ dbiMessageContextMenu as any
786
+ );
787
+ return dbiMessageContextMenu;
788
+ };
789
+ MessageContextMenu = Object.assign(
790
+ MessageContextMenu,
791
+ class {
792
+ constructor(...args: any[]) {
793
+ return MessageContextMenu.apply(this, args as any);
794
+ }
795
+ }
796
+ );
797
+
798
+ let UserContextMenu = function (
799
+ cfg: TDBIUserContextMenuOmitted<TNamespace>
800
+ ) {
801
+ let dbiUserContextMenu = new DBIUserContextMenu(self as any, cfg);
802
+ if (
803
+ self.config.strict &&
804
+ self.data.interactions.has(dbiUserContextMenu.name)
805
+ )
806
+ throw new Error(
807
+ `DBIUserContextMenu "${dbiUserContextMenu.name
808
+ }" already loaded as "${self.data.interactions.get(dbiUserContextMenu.name)?.type
809
+ }"!`
810
+ );
811
+ if (!cfg.flag || flags.includes("all") || flags.includes(cfg.flag)) self.data.interactions.set(
812
+ dbiUserContextMenu.name,
813
+ dbiUserContextMenu as any
814
+ );
815
+ return dbiUserContextMenu;
816
+ };
817
+ UserContextMenu = Object.assign(
818
+ UserContextMenu,
819
+ class {
820
+ constructor(...args: any[]) {
821
+ return UserContextMenu.apply(this, args as any);
822
+ }
823
+ }
824
+ );
825
+
826
+ let Modal = function (cfg: TDBIModalOmitted<TNamespace>) {
827
+ let dbiModal = new DBIModal(self as any, cfg);
828
+ if (self.config.strict && self.data.interactions.has(dbiModal.name))
829
+ throw new Error(
830
+ `DBIModal "${dbiModal.name}" already loaded as "${self.data.interactions.get(dbiModal.name)?.type
831
+ }"!`
832
+ );
833
+ if (!cfg.flag || flags.includes("all") || flags.includes(cfg.flag)) self.data.interactions.set(dbiModal.name, dbiModal as any);
834
+ return dbiModal;
835
+ };
836
+ Modal = Object.assign(
837
+ Modal,
838
+ class {
839
+ constructor(...args: any[]) {
840
+ return Modal.apply(this, args as any);
841
+ }
842
+ }
843
+ );
844
+
845
+ let createInlineModal = function (cfg: Omit<TDBIModalOmitted<TNamespace>, "name" | "id">) {
846
+ let id = randomInlineId();
847
+ return Modal({ ...cfg, ttl: cfg?.ttl || self.config.inlineListeners.autoClear?.ttl, id, name: id } as any);
848
+ }
849
+
850
+ let Locale = function (cfg: TDBILocaleConstructor<TNamespace>) {
851
+ let dbiLocale = new DBILocale(self as any, cfg);
852
+ if (
853
+ self.config.strict &&
854
+ self.data.interactionLocales.has(dbiLocale.name)
855
+ )
856
+ throw new Error(`DBILocale "${dbiLocale.name}" already loaded!`);
857
+ if (self.data.locales.has(dbiLocale.name))
858
+ dbiLocale.mergeLocale(self.data.locales.get(dbiLocale.name));
859
+ if (!cfg.flag || flags.includes("all") || flags.includes(cfg.flag)) self.data.locales.set(dbiLocale.name, dbiLocale);
860
+ return dbiLocale;
861
+ };
862
+ Locale = Object.assign(
863
+ Locale,
864
+ class {
865
+ constructor(...args: any[]) {
866
+ return Locale.apply(this, args as any);
867
+ }
868
+ }
869
+ );
870
+
871
+ let CustomEvent = function (cfg: TDBICustomEventOmitted<TNamespace>) {
872
+ let dbiCustomEvent = new DBICustomEvent(self, cfg) as any;
873
+ if (self.config.strict && self.data.eventMap[dbiCustomEvent.name])
874
+ throw new Error(
875
+ `DBICustomEvent "${dbiCustomEvent.name}" already loaded!`
876
+ );
877
+ self.data.eventMap[dbiCustomEvent.name] = dbiCustomEvent.map;
878
+ self.data.customEventNames.add(dbiCustomEvent.name);
879
+ return dbiCustomEvent;
880
+ };
881
+ CustomEvent = Object.assign(
882
+ CustomEvent,
883
+ class {
884
+ constructor(...args: any[]) {
885
+ return CustomEvent.apply(this, args as any);
886
+ }
887
+ }
888
+ );
889
+
890
+ let InteractionLocale = function (cfg: TDBIInteractionLocaleOmitted) {
891
+ let dbiInteractionLocale = new DBIInteractionLocale(self, cfg);
892
+ if (
893
+ self.config.strict &&
894
+ self.data.interactionLocales.has(dbiInteractionLocale.name)
895
+ )
896
+ throw new Error(
897
+ `DBIInteractionLocale "${dbiInteractionLocale.name}" already loaded!`
898
+ );
899
+ if (!cfg.flag || flags.includes("all") || flags.includes(cfg.flag)) self.data.interactionLocales.set(
900
+ dbiInteractionLocale.name,
901
+ dbiInteractionLocale
902
+ );
903
+ return dbiInteractionLocale;
904
+ };
905
+ InteractionLocale = Object.assign(
906
+ InteractionLocale,
907
+ class {
908
+ constructor(...args: any[]) {
909
+ return InteractionLocale.apply(this, args as any);
910
+ }
911
+ }
912
+ );
913
+
914
+ await cb({
915
+ ChatInput,
916
+ Event,
917
+ ChatInputOptions,
918
+ Locale,
919
+ Button,
920
+ StringSelectMenu,
921
+ UserSelectMenu,
922
+ RoleSelectMenu,
923
+ ChannelSelectMenu,
924
+ MentionableSelectMenu,
925
+ MessageContextMenu,
926
+ UserContextMenu,
927
+ CustomEvent,
928
+ Modal,
929
+ InteractionLocale,
930
+ createInlineButton,
931
+ createInlineEvent,
932
+ createInlineStringSelectMenu,
933
+ createInlineUserSelectMenu,
934
+ createInlineRoleSelectMenu,
935
+ createInlineChannelSelectMenu,
936
+ createInlineMentionableSelectMenu,
937
+ createInlineModal,
938
+ onUnload(cb: () => Promise<any> | any) {
939
+ self.data.registerUnloaders.add(cb);
940
+ },
941
+ });
942
+ }
943
+ self.data.interactions.sort((a, b) => b.name.length - a.name.length);
944
+ }
945
+
946
+ emit<
947
+ TEventName extends keyof (NamespaceData[TNamespace]["customEvents"] &
948
+ ClientEvents)
949
+ >(
950
+ name: TEventName,
951
+ args: (NamespaceData[TNamespace]["customEvents"] & ClientEvents)[TEventName]
952
+ ): void {
953
+ this.data.clients.forEach((d) =>
954
+ d.client.emit(name as any, { ...args, _DIRECT_: true } as any)
955
+ );
956
+ }
957
+
958
+ /**
959
+ * this.data.interactions.get(name)
960
+ */
961
+ interaction<
962
+ TInteractionName extends keyof NamespaceData[TNamespace]["interactionMapping"]
963
+ >(
964
+ name: TInteractionName
965
+ ): NamespaceData[TNamespace]["interactionMapping"][TInteractionName] {
966
+ return this.data.interactions.get(name as any) as any;
967
+ }
968
+
969
+ client<TClientName extends NamespaceData[TNamespace]["clientNamespaces"]>(
970
+ name?: TClientName
971
+ ): TDBIClientData<TNamespace> {
972
+ return name ? this.data.clients.get(name) : this.data.clients.first();
973
+ }
974
+ /**
975
+ * this.data.events.get(name)
976
+ */
977
+ event<TEventName extends NamespaceData[TNamespace]["eventNames"]>(
978
+ name: TEventName
979
+ ): DBIEvent<TNamespace> {
980
+ return this.data.events.get(name);
981
+ }
982
+
983
+ /**
984
+ * this.data.locales.get(name)
985
+ */
986
+ locale<TLocaleName extends NamespaceData[TNamespace]["localeNames"]>(
987
+ name: TLocaleName
988
+ ): DBILocale<TNamespace> {
989
+ return this.data.locales.get(name) as any;
990
+ }
991
+
992
+ /**
993
+ * Shorthands for modifying `dbi.data.other`
994
+ */
995
+ get<K extends keyof TOtherData>(
996
+ k: K,
997
+ defaultValue?: TOtherData[K]
998
+ ): TOtherData[K] {
999
+ if (defaultValue && !this.has(k as any)) {
1000
+ this.set(k, defaultValue);
1001
+ return defaultValue;
1002
+ }
1003
+ return _.get(this.data.other, k);
1004
+ }
1005
+
1006
+ /**
1007
+ * Shorthands for modifying `dbi.data.other`
1008
+ */
1009
+ set<K extends keyof TOtherData>(k: K, v: TOtherData[K]): any {
1010
+ this.data.other = _.set(this.data.other as any, k, v);
1011
+ }
1012
+
1013
+ /**
1014
+ * Shorthands for modifying `dbi.data.other`
1015
+ */
1016
+ has(k: string): boolean {
1017
+ return _.has(this.data.other, k as any);
1018
+ }
1019
+
1020
+ /**
1021
+ * Shorthands for modifying `dbi.data.other`
1022
+ */
1023
+ delete(k: string): boolean {
1024
+ return _.unset(this.data.other, k);
1025
+ }
1026
+
1027
+ async login(): Promise<any> {
1028
+ await aaq.quickForEach(this.data.clients, async (clientContext) => {
1029
+ await clientContext.client.login(
1030
+ this.config.sharding == "default" ? null : clientContext.token
1031
+ );
1032
+ });
1033
+ this.events.trigger("clientsReady", undefined, true);
1034
+ }
1035
+
1036
+ async register(cb: (api: DBIRegisterAPI<TNamespace>) => void): Promise<any> {
1037
+ this.data.registers.add(cb);
1038
+ }
1039
+
1040
+ async load(...flags: string[]): Promise<boolean> {
1041
+ if (this._loaded) return false;
1042
+ await this._registerAll(flags);
1043
+ await this._hookListeners();
1044
+ this._loaded = true;
1045
+ return true;
1046
+ }
1047
+
1048
+ async unload(): Promise<boolean> {
1049
+ if (!this._loaded) return false;
1050
+ await this._unregisterAll();
1051
+ await this._unhookListeners();
1052
+ this._loaded = false;
1053
+ return true;
1054
+ }
1055
+
1056
+ get loaded(): boolean {
1057
+ return this._loaded;
1058
+ }
1059
+
1060
+ async publish(type: "Global", clear?: boolean): Promise<any>;
1061
+ async publish(type: "Guild", guildId: string, clear?: boolean): Promise<any>;
1062
+
1063
+ async publish(...args: any[]) {
1064
+ let interactions = this.data.interactions.filter(
1065
+ (i) =>
1066
+ i.type == "ChatInput" ||
1067
+ i.type == "MessageContextMenu" ||
1068
+ i.type == "UserContextMenu"
1069
+ ) as any;
1070
+ switch (args[0]) {
1071
+ case "Global": {
1072
+ return await publishInteractions(
1073
+ this.data.clients,
1074
+ args[1] ? new Discord.Collection() : interactions,
1075
+ this.data.interactionLocales,
1076
+ args[0]
1077
+ );
1078
+ }
1079
+ case "Guild": {
1080
+ return await publishInteractions(
1081
+ this.data.clients,
1082
+ args[2] ? new Discord.Collection() : interactions,
1083
+ this.data.interactionLocales,
1084
+ args[0],
1085
+ args[1]
1086
+ );
1087
+ }
1088
+ }
1089
+ }
1090
+ }