djs-builder 0.5.41 → 0.6.0

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 (156) hide show
  1. package/README.md +140 -303
  2. package/function/function.js +236 -0
  3. package/function/log.js +736 -0
  4. package/handler/helper.js +277 -0
  5. package/handler/starter.js +335 -0
  6. package/package.json +10 -42
  7. package/.tsbuildinfo +0 -1
  8. package/dist/discord/builder/components/Buttons.d.ts +0 -22
  9. package/dist/discord/builder/components/Buttons.d.ts.map +0 -1
  10. package/dist/discord/builder/components/Buttons.js +0 -91
  11. package/dist/discord/builder/components/Buttons.js.map +0 -1
  12. package/dist/discord/builder/components/Menus.d.ts +0 -31
  13. package/dist/discord/builder/components/Menus.d.ts.map +0 -1
  14. package/dist/discord/builder/components/Menus.js +0 -82
  15. package/dist/discord/builder/components/Menus.js.map +0 -1
  16. package/dist/discord/builder/permissions/perms.d.ts +0 -6
  17. package/dist/discord/builder/permissions/perms.d.ts.map +0 -1
  18. package/dist/discord/builder/permissions/perms.js +0 -66
  19. package/dist/discord/builder/permissions/perms.js.map +0 -1
  20. package/dist/discord/builder/system/Pagination.d.ts +0 -70
  21. package/dist/discord/builder/system/Pagination.d.ts.map +0 -1
  22. package/dist/discord/builder/system/Pagination.js +0 -227
  23. package/dist/discord/builder/system/Pagination.js.map +0 -1
  24. package/dist/discord/builder/system/collectors.d.ts +0 -27
  25. package/dist/discord/builder/system/collectors.d.ts.map +0 -1
  26. package/dist/discord/builder/system/collectors.js +0 -137
  27. package/dist/discord/builder/system/collectors.js.map +0 -1
  28. package/dist/discord/builder/utils.d.ts +0 -5
  29. package/dist/discord/builder/utils.d.ts.map +0 -1
  30. package/dist/discord/builder/utils.js +0 -10
  31. package/dist/discord/builder/utils.js.map +0 -1
  32. package/dist/discord/events-handler/eventLoader.d.ts +0 -13
  33. package/dist/discord/events-handler/eventLoader.d.ts.map +0 -1
  34. package/dist/discord/events-handler/eventLoader.js +0 -169
  35. package/dist/discord/events-handler/eventLoader.js.map +0 -1
  36. package/dist/discord/events-handler/events.d.ts +0 -8
  37. package/dist/discord/events-handler/events.d.ts.map +0 -1
  38. package/dist/discord/events-handler/events.js +0 -186
  39. package/dist/discord/events-handler/events.js.map +0 -1
  40. package/dist/discord/events-handler/login.d.ts +0 -9
  41. package/dist/discord/events-handler/login.d.ts.map +0 -1
  42. package/dist/discord/events-handler/login.js +0 -273
  43. package/dist/discord/events-handler/login.js.map +0 -1
  44. package/dist/discord/events-handler/prefix-register.d.ts +0 -23
  45. package/dist/discord/events-handler/prefix-register.d.ts.map +0 -1
  46. package/dist/discord/events-handler/prefix-register.js +0 -109
  47. package/dist/discord/events-handler/prefix-register.js.map +0 -1
  48. package/dist/discord/events-handler/prefix-responder.d.ts +0 -5
  49. package/dist/discord/events-handler/prefix-responder.d.ts.map +0 -1
  50. package/dist/discord/events-handler/prefix-responder.js +0 -155
  51. package/dist/discord/events-handler/prefix-responder.js.map +0 -1
  52. package/dist/discord/events-handler/prefixLoader.d.ts +0 -7
  53. package/dist/discord/events-handler/prefixLoader.d.ts.map +0 -1
  54. package/dist/discord/events-handler/prefixLoader.js +0 -74
  55. package/dist/discord/events-handler/prefixLoader.js.map +0 -1
  56. package/dist/discord/events-handler/slash-register.d.ts +0 -4
  57. package/dist/discord/events-handler/slash-register.d.ts.map +0 -1
  58. package/dist/discord/events-handler/slash-register.js +0 -85
  59. package/dist/discord/events-handler/slash-register.js.map +0 -1
  60. package/dist/discord/events-handler/slash-responder.d.ts +0 -3
  61. package/dist/discord/events-handler/slash-responder.d.ts.map +0 -1
  62. package/dist/discord/events-handler/slash-responder.js +0 -112
  63. package/dist/discord/events-handler/slash-responder.js.map +0 -1
  64. package/dist/discord/events-handler/slashLoader.d.ts +0 -7
  65. package/dist/discord/events-handler/slashLoader.d.ts.map +0 -1
  66. package/dist/discord/events-handler/slashLoader.js +0 -94
  67. package/dist/discord/events-handler/slashLoader.js.map +0 -1
  68. package/dist/discord/events-handler/starter.d.ts +0 -6
  69. package/dist/discord/events-handler/starter.d.ts.map +0 -1
  70. package/dist/discord/events-handler/starter.js +0 -85
  71. package/dist/discord/events-handler/starter.js.map +0 -1
  72. package/dist/discord/functions/anticrash.d.ts +0 -3
  73. package/dist/discord/functions/anticrash.d.ts.map +0 -1
  74. package/dist/discord/functions/anticrash.js +0 -55
  75. package/dist/discord/functions/anticrash.js.map +0 -1
  76. package/dist/discord/functions/devLogs.d.ts +0 -2
  77. package/dist/discord/functions/devLogs.d.ts.map +0 -1
  78. package/dist/discord/functions/devLogs.js +0 -137
  79. package/dist/discord/functions/devLogs.js.map +0 -1
  80. package/dist/discord/functions/logger.d.ts +0 -5
  81. package/dist/discord/functions/logger.d.ts.map +0 -1
  82. package/dist/discord/functions/logger.js +0 -57
  83. package/dist/discord/functions/logger.js.map +0 -1
  84. package/dist/discord/functions/mongoDb.d.ts +0 -4
  85. package/dist/discord/functions/mongoDb.d.ts.map +0 -1
  86. package/dist/discord/functions/mongoDb.js +0 -39
  87. package/dist/discord/functions/mongoDb.js.map +0 -1
  88. package/dist/discord/functions/similarity.d.ts +0 -3
  89. package/dist/discord/functions/similarity.d.ts.map +0 -1
  90. package/dist/discord/functions/similarity.js +0 -56
  91. package/dist/discord/functions/similarity.js.map +0 -1
  92. package/dist/discord/functions/terminal.d.ts +0 -2
  93. package/dist/discord/functions/terminal.d.ts.map +0 -1
  94. package/dist/discord/functions/terminal.js +0 -127
  95. package/dist/discord/functions/terminal.js.map +0 -1
  96. package/dist/discord/functions/utils.d.ts +0 -5
  97. package/dist/discord/functions/utils.d.ts.map +0 -1
  98. package/dist/discord/functions/utils.js +0 -11
  99. package/dist/discord/functions/utils.js.map +0 -1
  100. package/dist/discord/functions/versedb.d.ts +0 -3
  101. package/dist/discord/functions/versedb.d.ts.map +0 -1
  102. package/dist/discord/functions/versedb.js +0 -21
  103. package/dist/discord/functions/versedb.js.map +0 -1
  104. package/dist/discord/games/X-O.d.ts +0 -20
  105. package/dist/discord/games/X-O.d.ts.map +0 -1
  106. package/dist/discord/games/X-O.js +0 -166
  107. package/dist/discord/games/X-O.js.map +0 -1
  108. package/dist/discord/games/rps.d.ts +0 -21
  109. package/dist/discord/games/rps.d.ts.map +0 -1
  110. package/dist/discord/games/rps.js +0 -99
  111. package/dist/discord/games/rps.js.map +0 -1
  112. package/dist/discord/types/starter.d.ts +0 -144
  113. package/dist/discord/types/starter.d.ts.map +0 -1
  114. package/dist/discord/types/starter.js +0 -3
  115. package/dist/discord/types/starter.js.map +0 -1
  116. package/dist/discord/types/utils.d.ts +0 -3
  117. package/dist/discord/types/utils.d.ts.map +0 -1
  118. package/dist/discord/types/utils.js +0 -3
  119. package/dist/discord/types/utils.js.map +0 -1
  120. package/dist/discord/utils.d.ts +0 -15
  121. package/dist/discord/utils.d.ts.map +0 -1
  122. package/dist/discord/utils.js +0 -41
  123. package/dist/discord/utils.js.map +0 -1
  124. package/dist/index.d.ts +0 -4
  125. package/dist/index.d.ts.map +0 -1
  126. package/dist/index.js +0 -71
  127. package/dist/index.js.map +0 -1
  128. package/lib/discord/builder/components/Buttons.ts +0 -123
  129. package/lib/discord/builder/components/Menus.ts +0 -106
  130. package/lib/discord/builder/permissions/perms.ts +0 -66
  131. package/lib/discord/builder/system/Pagination.ts +0 -323
  132. package/lib/discord/builder/system/collectors.ts +0 -197
  133. package/lib/discord/builder/utils.ts +0 -9
  134. package/lib/discord/events-handler/eventLoader.ts +0 -166
  135. package/lib/discord/events-handler/events.ts +0 -160
  136. package/lib/discord/events-handler/login.ts +0 -265
  137. package/lib/discord/events-handler/prefix-register.ts +0 -117
  138. package/lib/discord/events-handler/prefix-responder.ts +0 -176
  139. package/lib/discord/events-handler/prefixLoader.ts +0 -83
  140. package/lib/discord/events-handler/slash-register.ts +0 -81
  141. package/lib/discord/events-handler/slash-responder.ts +0 -136
  142. package/lib/discord/events-handler/slashLoader.ts +0 -104
  143. package/lib/discord/events-handler/starter.ts +0 -85
  144. package/lib/discord/functions/anticrash.ts +0 -60
  145. package/lib/discord/functions/devLogs.ts +0 -128
  146. package/lib/discord/functions/logger.ts +0 -58
  147. package/lib/discord/functions/mongoDb.ts +0 -38
  148. package/lib/discord/functions/similarity.ts +0 -70
  149. package/lib/discord/functions/terminal.ts +0 -162
  150. package/lib/discord/functions/utils.ts +0 -4
  151. package/lib/discord/functions/versedb.ts +0 -17
  152. package/lib/discord/types/starter.ts +0 -158
  153. package/lib/discord/types/utils.ts +0 -2
  154. package/lib/discord/utils.ts +0 -17
  155. package/lib/index.ts +0 -37
  156. package/tsconfig.json +0 -21
@@ -1,323 +0,0 @@
1
- import {
2
- ButtonBuilder,
3
- ActionRowBuilder,
4
- EmbedBuilder,
5
- Message,
6
- MessageComponentInteraction,
7
- MessageActionRowComponentBuilder,
8
- ButtonStyle,
9
- StringSelectMenuBuilder,
10
- } from "discord.js";
11
-
12
- interface PagerOptions {
13
- firstLast?: boolean;
14
- deleteOption?: boolean;
15
- otherComponents?: ActionRowBuilder<MessageActionRowComponentBuilder>[];
16
- home?: {
17
- home_Option?: boolean;
18
- home_page?: number;
19
- };
20
- timeOption?: {
21
- timeOut?: number;
22
- disable?: boolean;
23
- deletes?: boolean;
24
- custom?: (() => void);
25
- };
26
- user_only?: {
27
- user_status?: boolean;
28
- reply?: string;
29
- };
30
- style?: {
31
- nextAndBack?: ButtonStyle;
32
- firstAndLast?: ButtonStyle;
33
- homeStyle?: ButtonStyle;
34
- deleteStyle?: ButtonStyle;
35
- };
36
- label?: {
37
- labelNext?: string | null;
38
- labelBack?: string | null;
39
- labelFirst?: string | null;
40
- labelLast?: string | null;
41
- labelHome?: string | null;
42
- labelDelete?: string | null;
43
- };
44
- emoji?: {
45
- emojiNext?: string;
46
- emojiBack?: string;
47
- emojiFirst?: string;
48
- emojiLast?: string;
49
- emojiHome?: string;
50
- emojiDelete?: string;
51
- };
52
- pages?: {
53
- embeds?: EmbedBuilder[];
54
- attachment?: (string | Buffer)[];
55
- content?: string[];
56
- };
57
- navigationMenu?: {
58
- enabled?: boolean;
59
- placeHolder?: string;
60
- selects?: string[];
61
- };
62
- }
63
-
64
- const CUSTOM_IDS = {
65
- NEXT: "next-discobase",
66
- BACK: "back-discobase",
67
- FIRST: "first-discobase",
68
- LAST: "last-discobase",
69
- DELETE: "delete-discobase",
70
- HOME: "home-discobase",
71
- SELECT: "select-discobase"
72
- };
73
-
74
- const VALID_BUTTON_STYLES = [
75
- ButtonStyle.Primary,
76
- ButtonStyle.Secondary,
77
- ButtonStyle.Success,
78
- ButtonStyle.Danger
79
- ];
80
-
81
- const isValidEmoji = (emoji: string | undefined): boolean => {
82
- if (!emoji) return false;
83
- const unicodeEmojiPattern = /^[\u{1F600}-\u{1F64F}\u{1F300}-\u{1F5FF}\u{1F680}-\u{1F6FF}\u{1F700}-\u{1F77F}\u{1F780}-\u{1F7FF}\u{1F800}-\u{1F8FF}\u{1F900}-\u{1F9FF}\u{1FA00}-\u{1FA6F}\u{1FA70}-\u{1FAFF}\u{2600}-\u{26FF}\u{2700}-\u{27BF}\u{2300}-\u{23FF}\u{2B50}\u{2934}\u{2935}\u{3030}]+$/u;
84
- return unicodeEmojiPattern.test(emoji) || /^\d+$/.test(emoji);
85
- };
86
-
87
- export class Pagination {
88
- private message: Message;
89
- private options: Required<PagerOptions>;
90
- private buttons: ButtonBuilder[];
91
- private components: ActionRowBuilder<MessageActionRowComponentBuilder>[];
92
- private naw_page: number = 0;
93
-
94
- constructor(message: Message, options: PagerOptions) {
95
- this.message = message;
96
- this.options = {
97
- firstLast: false,
98
- deleteOption: false,
99
- otherComponents: [],
100
- home: { home_Option: false, home_page: 0 },
101
- timeOption: { timeOut: 86400000, disable: false, deletes: false, custom: undefined },
102
- user_only: { user_status: false, reply: "You are not the command owner" },
103
- style: { nextAndBack: ButtonStyle.Primary, firstAndLast: ButtonStyle.Secondary, homeStyle: ButtonStyle.Success, deleteStyle: ButtonStyle.Danger },
104
- label: {},
105
- emoji: { emojiNext: "➡", emojiBack: "⬅", emojiFirst: "⏪", emojiLast: "⏩", emojiHome: "🏠", emojiDelete: "🗑" },
106
- pages: { embeds: [], attachment: [], content: [] },
107
- navigationMenu: { enabled: false, placeHolder: "Choose a page", selects: [] },
108
- ...options,
109
- };
110
-
111
- this.validateOptions();
112
- this.buttons = this.createButtons();
113
- this.components = this.createComponents();
114
- }
115
- private validateOptions() {
116
- const { emoji } = this.options;
117
- if (!Object.values(emoji).every(isValidEmoji)) {
118
- throw new Error("Invalid emoji format. Must be either Unicode emojis or valid emoji IDs.");
119
- }
120
-
121
- const { style } = this.options;
122
- if (!Object.values(style).every(style => VALID_BUTTON_STYLES.includes(style))) {
123
- throw new Error("Invalid button style. Must be one of the predefined ButtonStyle values.");
124
- }
125
-
126
- if (this.options.deleteOption && this.options.home?.home_Option) {
127
- throw new Error("You can't use 'home' and 'delete' together.");
128
- }
129
-
130
- if (this.options.timeOption?.disable && this.options.timeOption?.deletes) {
131
- throw new Error("You can't use 'disable' and 'deletes' together.");
132
- }
133
- }
134
-
135
- private createButtons(): ButtonBuilder[] {
136
- const {
137
- nextAndBack,
138
- firstAndLast,
139
- homeStyle,
140
- deleteStyle,
141
- } = this.options.style;
142
-
143
- const {
144
- emojiNext,
145
- emojiBack,
146
- emojiFirst,
147
- emojiLast,
148
- emojiHome,
149
- emojiDelete,
150
- } = this.options.emoji;
151
-
152
- const next = new ButtonBuilder().setCustomId(CUSTOM_IDS.NEXT).setEmoji(emojiNext!).setStyle(nextAndBack!);
153
- const back = new ButtonBuilder().setCustomId(CUSTOM_IDS.BACK).setEmoji(emojiBack!).setStyle(nextAndBack!);
154
- const first = new ButtonBuilder().setCustomId(CUSTOM_IDS.FIRST).setEmoji(emojiFirst!).setStyle(firstAndLast!);
155
- const last = new ButtonBuilder().setCustomId(CUSTOM_IDS.LAST).setEmoji(emojiLast!).setStyle(firstAndLast!);
156
- const home = new ButtonBuilder().setCustomId(CUSTOM_IDS.HOME).setEmoji(emojiHome!).setStyle(homeStyle!);
157
- const deleteBtn = new ButtonBuilder().setCustomId(CUSTOM_IDS.DELETE).setEmoji(emojiDelete!).setStyle(deleteStyle!);
158
-
159
- const {
160
- labelNext,
161
- labelBack,
162
- labelFirst,
163
- labelLast,
164
- labelHome,
165
- labelDelete,
166
- } = this.options.label;
167
-
168
- if (labelNext) next.setLabel(labelNext);
169
- if (labelBack) back.setLabel(labelBack);
170
- if (labelFirst) first.setLabel(labelFirst);
171
- if (labelLast) last.setLabel(labelLast);
172
- if (labelHome) home.setLabel(labelHome);
173
- if (labelDelete) deleteBtn.setLabel(labelDelete);
174
-
175
- const buttons: ButtonBuilder[] = [];
176
-
177
- if (this.options.firstLast) buttons.push(first);
178
- buttons.push(back);
179
- if (this.options.home?.home_Option) buttons.push(home);
180
- else if (this.options.deleteOption) buttons.push(deleteBtn);
181
- buttons.push(next);
182
- if (this.options.firstLast) buttons.push(last);
183
-
184
- return buttons;
185
- }
186
-
187
- private createComponents(): ActionRowBuilder<MessageActionRowComponentBuilder>[] {
188
- const buttonRow = new ActionRowBuilder<MessageActionRowComponentBuilder>().addComponents(this.buttons);
189
-
190
- const otherRows = this.options.otherComponents || [];
191
- const selectMenus = this.options.navigationMenu?.enabled ? this.createSelectMenus() : [];
192
-
193
- return [buttonRow, ...selectMenus, ...otherRows];
194
- }
195
-
196
- private createSelectMenus(): ActionRowBuilder<StringSelectMenuBuilder>[] {
197
- const { embeds = [], content = [], attachment = [] } = this.options.pages || {};
198
- const longest_length = Math.max(embeds.length, content.length, attachment.length);
199
- const selectMenus: ActionRowBuilder<StringSelectMenuBuilder>[] = [];
200
- const select_status = this.options.navigationMenu?.enabled;
201
- const select_placeholder = this.options.navigationMenu?.placeHolder;
202
- const selects = this.options.navigationMenu?.selects || [];
203
-
204
- if (select_status) {
205
- for (let i = 0; i < longest_length; i += 25) {
206
- const menuOptions = Array.from({ length: Math.min(25, longest_length - i) }, (_, j) => ({
207
- label: selects[i + j] ? selects[i + j] : `Page ${i + j + 1}`,
208
- value: `${i + j}`
209
- }));
210
-
211
- const selectMenu = new StringSelectMenuBuilder()
212
- .setCustomId(`discobase_select_${i / 25}`)
213
- .setPlaceholder(`${select_placeholder || "Choose a page"} (${i + 1}-${Math.min(i + 25, longest_length)})`)
214
- .addOptions(menuOptions);
215
-
216
- selectMenus.push(new ActionRowBuilder<StringSelectMenuBuilder>().addComponents(selectMenu));
217
- }
218
- }
219
-
220
- return selectMenus;
221
- }
222
-
223
- public async send() {
224
- const { embeds = [], content = [], attachment = [] } = this.options.pages || {};
225
-
226
- if (embeds.length === 0) {
227
- throw new Error("No embeds provided.");
228
- }
229
-
230
- try {
231
- const msg = await this.message.reply({
232
- embeds: [embeds[0]],
233
- content: content[0] || "",
234
- files: attachment[0] ? [attachment[0]] : [],
235
- components: this.components,
236
- });
237
-
238
- const collector = this.createCollector(msg);
239
- collector.on("collect", async (i: MessageComponentInteraction) => this.handleCollect(i));
240
- collector.on("end", async () => this.handleEnd(msg));
241
- } catch (error) {
242
- console.error("Error sending message:", error);
243
- }
244
- }
245
-
246
- private createCollector(msg: Message) {
247
- const filter = this.options.user_only?.user_status
248
- ? async (i: MessageComponentInteraction) => {
249
- if (i.user.id !== this.message.author.id) {
250
- await i.reply({ content: this.options.user_only.reply!, ephemeral: true });
251
- return false;
252
- }
253
- return true;
254
- }
255
- : undefined;
256
-
257
- return msg.createMessageComponentCollector({
258
- filter,
259
- time: this.options.timeOption?.timeOut || 86400000,
260
- });
261
- }
262
-
263
-
264
- private async handleCollect(i: MessageComponentInteraction) {
265
- const { embeds = [], content = [], attachment = [] } = this.options.pages || {};
266
- const num = embeds.length;
267
-
268
- try {
269
- if (i.isButton()) {
270
- switch (i.customId) {
271
- case CUSTOM_IDS.NEXT:
272
- this.naw_page = (this.naw_page + 1) % num;
273
- break;
274
- case CUSTOM_IDS.BACK:
275
- this.naw_page = (this.naw_page - 1 + num) % num;
276
- break;
277
- case CUSTOM_IDS.FIRST:
278
- this.naw_page = 0;
279
- break;
280
- case CUSTOM_IDS.LAST:
281
- this.naw_page = num - 1;
282
- break;
283
- case CUSTOM_IDS.DELETE:
284
- await i.message.delete();
285
- return;
286
- case CUSTOM_IDS.HOME:
287
- this.naw_page = this.options.home?.home_page || 0;
288
- break;
289
- }
290
- } else if (i.isStringSelectMenu()) {
291
- if (i.customId.startsWith("discobase_select_")) {
292
- this.naw_page = parseInt(i.values[0], 10);
293
- }
294
- }
295
- await i.update({
296
- embeds: [embeds[this.naw_page]],
297
- content: content[this.naw_page] || "",
298
- files: attachment[this.naw_page] ? [attachment[this.naw_page]] : [],
299
- components: this.createComponents(),
300
- });
301
- } catch (error) {
302
- console.error("Error handling interaction:", error);
303
- }
304
- }
305
-
306
- private async handleEnd(msg: Message) {
307
- try {
308
- if (this.options.timeOption?.disable) {
309
- this.components[0].components.forEach((button) => button.setDisabled(true));
310
- await msg.edit({ components: this.components });
311
- }
312
- if (this.options.timeOption?.deletes) {
313
- await msg.edit({ components: [] });
314
- }
315
- if (typeof this.options.timeOption?.custom === "function") {
316
- this.options.timeOption.custom();
317
- }
318
- } catch (error) {
319
- console.error("Error handling end of collector:", error);
320
- }
321
- }
322
- }
323
-
@@ -1,197 +0,0 @@
1
- import {
2
- Message,
3
- Interaction,
4
- MessageCollector,
5
- InteractionCollector,
6
- CollectorFilter,
7
- Snowflake,
8
- ReadonlyCollection,
9
- CommandInteraction,
10
- ButtonInteraction,
11
- MessageReaction,
12
- ModalSubmitInteraction,
13
- StringSelectMenuInteraction,
14
- UserSelectMenuInteraction,
15
- RoleSelectMenuInteraction,
16
- ContextMenuCommandInteraction,
17
- Collector,
18
- } from 'discord.js';
19
-
20
- type EventSource = Message | CommandInteraction | ButtonInteraction | MessageReaction | Interaction;
21
-
22
- const collectorCache: Map<string, any> = new Map();
23
-
24
- /**
25
- * @param sources - The event source(s) (message, interaction, reaction, etc.) to collect from.
26
- * @param options - Custom options for collection (time, filter, max, idle).
27
- * @param events - Custom event handlers for `onCollect`, `onEnd`, `onError`, etc.
28
- */
29
- function Djs_Collectors<T extends EventSource>(
30
- sources: T | T[],
31
- options: {
32
- time?: number;
33
- filter?: CollectorFilter<[T]>;
34
- max?: number;
35
- idle?: number;
36
- log?: boolean;
37
- throttle?: number;
38
- uniqueId?: string;
39
- },
40
- events: {
41
- onCollect: (collectedItem: T, meta?: Record<string, any>) => void;
42
- onEnd?: (collected: ReadonlyCollection<Snowflake, T>, reason: string) => void;
43
- onError?: (error: Error) => void;
44
- onDispose?: (disposedItem: T) => void;
45
- onTimeout?: () => void;
46
- onStart?: () => void;
47
- },
48
- metadata?: Record<string, any>
49
- ): { stop: (reason?: string) => void } {
50
- const eventSources = Array.isArray(sources) ? sources : [sources];
51
- const filter: CollectorFilter<[T]> = options.filter || (() => true);
52
- const time: number = options.time || 60000;
53
-
54
- if (events.onStart) events.onStart();
55
-
56
- if (options.uniqueId && collectorCache.has(options.uniqueId)) {
57
- console.warn(`Collector with unique ID "${options.uniqueId}" is already active. Skipping creation.`);
58
- return { stop: () => {} };
59
- }
60
-
61
- if (options.uniqueId) {
62
- collectorCache.set(options.uniqueId, { sources: eventSources, time, max: options.max, idle: options.idle });
63
- }
64
-
65
- const collectors: any[] = [];
66
-
67
- for (const source of eventSources) {
68
- if (source instanceof Message) {
69
- const messageCollector = new MessageCollector(source.channel, {
70
- filter: filter as CollectorFilter<[Message]>,
71
- time,
72
- max: options.max,
73
- idle: options.idle,
74
- });
75
-
76
- collectors.push(messageCollector); // Store reference
77
- handleCollector(messageCollector, events, options, metadata);
78
-
79
- } else if (
80
- source instanceof CommandInteraction ||
81
- source instanceof ButtonInteraction ||
82
- source instanceof StringSelectMenuInteraction ||
83
- source instanceof UserSelectMenuInteraction ||
84
- source instanceof RoleSelectMenuInteraction ||
85
- source instanceof ContextMenuCommandInteraction ||
86
- source instanceof ModalSubmitInteraction
87
- ) {
88
- if (!source.client.isReady()) {
89
- throw new Error('Client is not ready. Please ensure the client is logged in and ready before creating a collector.');
90
- }
91
-
92
- const interactionCollector = new InteractionCollector(source.client, {
93
- filter: filter as CollectorFilter<[Interaction]>,
94
- time,
95
- max: options.max,
96
- idle: options.idle,
97
- });
98
-
99
- collectors.push(interactionCollector); // Store reference
100
- handleCollector(interactionCollector, events, options, metadata);
101
-
102
- } else if (source instanceof MessageReaction) {
103
- const reactionCollector = source.message.createReactionCollector({
104
- filter: filter as CollectorFilter<[MessageReaction]>,
105
- time,
106
- max: options.max,
107
- idle: options.idle,
108
- });
109
-
110
- collectors.push(reactionCollector); // Store reference
111
- handleCollector(reactionCollector, events, options, metadata);
112
-
113
- } else {
114
- throw new Error("Source must be either a Message, Interaction, or Reaction.");
115
- }
116
- }
117
-
118
- return {
119
- stop: (reason: string = 'manual') => {
120
- if (options.uniqueId) {
121
- const cached = collectorCache.get(options.uniqueId);
122
- if (cached) {
123
- collectors.forEach((collector) => collector.stop(reason));
124
- collectorCache.delete(options.uniqueId);
125
- console.log(`Collector with unique ID "${options.uniqueId}" has been ended. Reason: ${reason}`);
126
- } else {
127
- console.warn(`No collector found with unique ID "${options.uniqueId}".`);
128
- }
129
- } else {
130
- collectors.forEach((collector) => collector.stop(reason));
131
- console.log(`Collectors have been ended. Reason: ${reason}`);
132
- }
133
- },
134
- };
135
- }
136
-
137
- /**
138
- * Generic function to handle a collector's events and lifecycle.
139
- * @param collector - The specific collector (MessageCollector, InteractionCollector, etc.).
140
- * @param events - The event handlers for collection lifecycle.
141
- * @param options - Additional collection options.
142
- * @param metadata - Optional metadata attached to each collected item.
143
- */
144
- function handleCollector<T>(
145
- collector: any,
146
- events: {
147
- onCollect: (collectedItem: T, meta?: Record<string, any>) => void;
148
- onEnd?: (collected: ReadonlyCollection<Snowflake, T>, reason: string) => void;
149
- onError?: (error: Error) => void;
150
- onDispose?: (disposedItem: T) => void;
151
- onTimeout?: () => void;
152
- },
153
- options: { log?: boolean; throttle?: number; uniqueId?: string },
154
- metadata?: Record<string, any>
155
- ) {
156
- let lastCollectedTime = 0;
157
-
158
- collector.on('collect', (collectedItem: T) => {
159
- const now = Date.now();
160
- if (options.throttle && now - lastCollectedTime < options.throttle) {
161
- if (options.log) console.warn(`Throttled collect for ${collectedItem}`);
162
- return;
163
- }
164
- lastCollectedTime = now;
165
-
166
- if (options.log) console.log('Collected item:', collectedItem);
167
- events.onCollect(collectedItem, metadata);
168
- });
169
-
170
- collector.on('end', (collected: ReadonlyCollection<Snowflake, T>, reason: string) => {
171
- if (options.log) console.log(`Collector ended. Reason: ${reason}`);
172
- if (events.onEnd) events.onEnd(collected, reason);
173
- if (reason === 'time' && events.onTimeout) {
174
- events.onTimeout();
175
- }
176
-
177
- if (options.uniqueId) {
178
- collectorCache.delete(options.uniqueId);
179
- }
180
- });
181
-
182
- if (events.onError) {
183
- collector.on('error', (error: Error) => {
184
- if (options.log) console.error('Collector error:', error);
185
- (events.onError as (error: Error) => void)(error);
186
- });
187
- }
188
-
189
- if (events.onDispose) {
190
- collector.on('dispose', (disposedItem: T) => {
191
- if (options.log) console.log('Disposed item:', disposedItem);
192
- (events.onDispose as (disposedItem: T) => void)(disposedItem);
193
- });
194
- }
195
- }
196
-
197
- export { Djs_Collectors };
@@ -1,9 +0,0 @@
1
- import { ButtonManager } from './components/Buttons';
2
- import { MenuManager } from './components/Menus';
3
- import { PermissionChecker } from './permissions/perms';
4
-
5
- export {
6
- ButtonManager,
7
- MenuManager,
8
- PermissionChecker
9
- };
@@ -1,166 +0,0 @@
1
- import { Client, Collection } from 'discord.js';
2
- import { readdir } from 'fs/promises';
3
- import { resolve, extname } from 'path';
4
- import { Event } from '../types/utils';
5
- import { logError, logInfo } from '../functions/logger';
6
- import { botData } from './login';
7
- import { watch } from 'fs';
8
-
9
- const validExtensions = ['.js', '.ts'];
10
-
11
- interface Events {
12
- eventBlacklist?: string[];
13
- recursive?: boolean;
14
- }
15
-
16
- export async function eventLoader(client: any, eventsOptions: Events = {}): Promise<{ events: Collection<string, Event>; success: boolean }> {
17
- try {
18
- const eventsPath = botData.get('eventsPath') as string;
19
- const eventPath = resolve(process.cwd(), eventsPath);
20
-
21
- const getAllFiles = async (dirPath: string): Promise<string[]> => {
22
- let files: string[] = [];
23
- const dirents = await readdir(dirPath, { withFileTypes: true });
24
-
25
- for (const dirent of dirents) {
26
- const res = resolve(dirPath, dirent.name);
27
- if (dirent.isDirectory()) {
28
- if (eventsOptions.recursive) {
29
- files = files.concat(await getAllFiles(res));
30
- }
31
- } else if (validExtensions.includes(extname(dirent.name))) {
32
- files.push(res);
33
- }
34
- }
35
- return files;
36
- };
37
-
38
- const files = await getAllFiles(eventPath);
39
- if (files.length === 0) {
40
- logInfo(`No event files found in directory \`${eventPath}\`.`);
41
- return { events: new Collection<string, Event>(), success: false };
42
- }
43
-
44
- client.removeAllListeners();
45
-
46
- for (const file of files) {
47
- delete require.cache[require.resolve(file)];
48
- logInfo(`Unlinked cached module: ${file}`);
49
- }
50
-
51
- const newEvents = new Collection<string, Event>();
52
- for (const file of files) {
53
- try {
54
- const event: Event = await import(file);
55
- if (eventsOptions.eventBlacklist?.includes(file)) {
56
- continue;
57
- }
58
-
59
- let eventHandler: (...args: any[]) => Promise<void> = async (...args: any[]) => {
60
- if (event.initializer) {
61
- await new Promise(resolve => setTimeout(resolve, event.initializer));
62
- }
63
- await event.execute(...args, client);
64
-
65
- if (event.interval) {
66
- if (event.intervalId) clearInterval(event.intervalId);
67
- event.intervalId = setInterval(async () => {
68
- await event.execute(...args, client);
69
- }, event.interval);
70
- }
71
- };
72
-
73
- if (event.once) {
74
- client.once(event.name, eventHandler);
75
- } else {
76
- client.on(event.name, eventHandler);
77
- }
78
-
79
- if (event.maxExecution !== undefined) {
80
- eventHandler = await limitConcurrency(eventHandler, event.maxExecution);
81
- }
82
-
83
- if (event.retryAttempts !== undefined) {
84
- eventHandler = await withRetry(eventHandler, event.retryAttempts);
85
- }
86
-
87
- newEvents.set(event.name, event);
88
- } catch (error: any) {
89
- logError(`Error re-importing file: ${file}`);
90
- logError(error.message, error);
91
- }
92
- }
93
-
94
- client.eventSize = newEvents.size;
95
-
96
- return { events: newEvents, success: true };
97
- } catch (error: any) {
98
- logError('Error reloading events:');
99
- logError(error.message, error);
100
- return { events: new Collection<string, Event>(), success: false };
101
- }
102
- }
103
-
104
- async function limitConcurrency(handler: (...args: any[]) => void, maxConcurrentExecutions: number): Promise<(...args: any[]) => Promise<void>> {
105
- let executing = 0;
106
- const queue: any[] = [];
107
-
108
- return async function(...args: any[]) {
109
- if (executing < maxConcurrentExecutions) {
110
- executing++;
111
- handler(...args);
112
- executing--;
113
-
114
- if (queue.length > 0) {
115
- const next = queue.shift();
116
- next();
117
- }
118
- } else {
119
- queue.push(() => handler(...args));
120
- }
121
- };
122
- }
123
-
124
- async function withRetry(handler: (...args: any[]) => Promise<void>, retryAttempts: number): Promise<(...args: any[]) => Promise<void>> {
125
- return async function(...args: any[]) {
126
- let attempts = 0;
127
- while (attempts < retryAttempts) {
128
- try {
129
- await handler(...args);
130
- return;
131
- } catch (error: any) {
132
- logError('Error executing event:');
133
- logError(error.message, error);
134
- attempts++;
135
- }
136
- }
137
- logError('Reached maximum retry attempts.');
138
- };
139
- }
140
-
141
- export function autoEventLoader(client: Client, DEBOUNCE_DELAY: number = 10000, eventsOptions: Events = {}) {
142
-
143
- const slashPath = botData.get('slashCommandPath') as string;
144
- const commandPath = resolve(process.cwd(), slashPath);
145
-
146
- let debounceTimer: NodeJS.Timeout | null = null;
147
-
148
- const handleReload = async () => {
149
- if (debounceTimer) {
150
- clearTimeout(debounceTimer);
151
- }
152
- debounceTimer = setTimeout(async () => {
153
- await eventLoader(client, eventsOptions);
154
- logInfo('Slash commands successfully reloaded after debounce.');
155
- }, DEBOUNCE_DELAY);
156
- };
157
-
158
- watch(commandPath, { recursive: false }, (eventType: any, filename: any) => {
159
- if (filename && validExtensions.includes(extname(filename))) {
160
- logInfo(`Detected ${eventType} in ${filename}, waiting for debouncing...`);
161
- handleReload();
162
- }
163
- });
164
-
165
- logInfo('Started watching for changes in slash commands...');
166
- }