@spatulox/simplediscordbot 1.0.30 → 1.0.32

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 (82) hide show
  1. package/.npmignore_old +23 -0
  2. package/dist/index.d.mts +915 -0
  3. package/dist/index.d.ts +915 -17
  4. package/dist/index.js +2576 -36
  5. package/dist/index.mjs +2554 -0
  6. package/package.json +3 -2
  7. package/dist/SimpleDiscordBotInfo.d.ts +0 -8
  8. package/dist/SimpleDiscordBotInfo.js +0 -14
  9. package/dist/bot/Bot.d.ts +0 -35
  10. package/dist/bot/Bot.js +0 -92
  11. package/dist/bot/BotEnv.d.ts +0 -6
  12. package/dist/bot/BotEnv.js +0 -24
  13. package/dist/bot/BotInteraction.d.ts +0 -21
  14. package/dist/bot/BotInteraction.js +0 -74
  15. package/dist/bot/BotLog.d.ts +0 -52
  16. package/dist/bot/BotLog.js +0 -134
  17. package/dist/bot/BotMessage.d.ts +0 -20
  18. package/dist/bot/BotMessage.js +0 -110
  19. package/dist/manager/FileManager.d.ts +0 -37
  20. package/dist/manager/FileManager.js +0 -136
  21. package/dist/manager/builder/SendableComponentBuilder.d.ts +0 -3
  22. package/dist/manager/builder/SendableComponentBuilder.js +0 -63
  23. package/dist/manager/direct/BasicUserManager.d.ts +0 -28
  24. package/dist/manager/direct/BasicUserManager.js +0 -81
  25. package/dist/manager/direct/UserManager.d.ts +0 -6
  26. package/dist/manager/direct/UserManager.js +0 -18
  27. package/dist/manager/guild/ChannelManager/ForumChannelManager.d.ts +0 -9
  28. package/dist/manager/guild/ChannelManager/ForumChannelManager.js +0 -33
  29. package/dist/manager/guild/ChannelManager/GuildChannelList.d.ts +0 -17
  30. package/dist/manager/guild/ChannelManager/GuildChannelList.js +0 -20
  31. package/dist/manager/guild/ChannelManager/GuildChannelManager.d.ts +0 -18
  32. package/dist/manager/guild/ChannelManager/GuildChannelManager.js +0 -91
  33. package/dist/manager/guild/ChannelManager/GuildMessageManager.d.ts +0 -23
  34. package/dist/manager/guild/ChannelManager/GuildMessageManager.js +0 -93
  35. package/dist/manager/guild/ChannelManager/GuildTextChannelManager.d.ts +0 -9
  36. package/dist/manager/guild/ChannelManager/GuildTextChannelManager.js +0 -33
  37. package/dist/manager/guild/ChannelManager/GuildVoiceChannelManager.d.ts +0 -9
  38. package/dist/manager/guild/ChannelManager/GuildVoiceChannelManager.js +0 -33
  39. package/dist/manager/guild/ChannelManager/NewsChannelManager.d.ts +0 -9
  40. package/dist/manager/guild/ChannelManager/NewsChannelManager.js +0 -33
  41. package/dist/manager/guild/ChannelManager/StageChannelManager.d.ts +0 -9
  42. package/dist/manager/guild/ChannelManager/StageChannelManager.js +0 -33
  43. package/dist/manager/guild/ChannelManager/ThreadChannelManager.d.ts +0 -13
  44. package/dist/manager/guild/ChannelManager/ThreadChannelManager.js +0 -49
  45. package/dist/manager/guild/GuildManager.d.ts +0 -32
  46. package/dist/manager/guild/GuildManager.js +0 -144
  47. package/dist/manager/guild/GuildUserManager.d.ts +0 -49
  48. package/dist/manager/guild/GuildUserManager.js +0 -251
  49. package/dist/manager/guild/InviteManager.d.ts +0 -21
  50. package/dist/manager/guild/InviteManager.js +0 -68
  51. package/dist/manager/guild/InviteManager_old.d.ts +0 -24
  52. package/dist/manager/guild/InviteManager_old.js +0 -89
  53. package/dist/manager/guild/RoleManager.d.ts +0 -24
  54. package/dist/manager/guild/RoleManager.js +0 -83
  55. package/dist/manager/interactions/ModalManager.d.ts +0 -23
  56. package/dist/manager/interactions/ModalManager.js +0 -113
  57. package/dist/manager/interactions/SelectMenuManager.d.ts +0 -58
  58. package/dist/manager/interactions/SelectMenuManager.js +0 -123
  59. package/dist/manager/messages/EmbedManager.d.ts +0 -97
  60. package/dist/manager/messages/EmbedManager.js +0 -161
  61. package/dist/manager/messages/ReactionManager.d.ts +0 -26
  62. package/dist/manager/messages/ReactionManager.js +0 -99
  63. package/dist/manager/messages/WebhookManager.d.ts +0 -33
  64. package/dist/manager/messages/WebhookManager.js +0 -108
  65. package/dist/test/client.d.ts +0 -3
  66. package/dist/test/client.js +0 -15
  67. package/dist/test/index.d.ts +0 -2
  68. package/dist/test/index.js +0 -31
  69. package/dist/test/randomActivityList.d.ts +0 -3
  70. package/dist/test/randomActivityList.js +0 -9
  71. package/dist/type/FolderName.d.ts +0 -2
  72. package/dist/type/FolderName.js +0 -10
  73. package/dist/utils/DiscordRegex.d.ts +0 -66
  74. package/dist/utils/DiscordRegex.js +0 -117
  75. package/dist/utils/Log.d.ts +0 -9
  76. package/dist/utils/Log.js +0 -28
  77. package/dist/utils/SimpleMutex.d.ts +0 -16
  78. package/dist/utils/SimpleMutex.js +0 -39
  79. package/dist/utils/network/InternetChecker.d.ts +0 -10
  80. package/dist/utils/network/InternetChecker.js +0 -54
  81. package/dist/utils/times/UnitTime.d.ts +0 -187
  82. package/dist/utils/times/UnitTime.js +0 -85
package/dist/index.js CHANGED
@@ -1,37 +1,2577 @@
1
1
  "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.SimpleDiscordBotInfo = exports.DiscordRegex = exports.SimpleMutex = exports.Log = exports.Time = exports.SelectMenuManager = exports.ModalManager = exports.UserManager = exports.GuildManager = exports.ReactionManager = exports.WebhookManager = exports.EmbedColor = exports.EmbedManager = exports.FileManager = exports.BotEnv = exports.Bot = void 0;
4
- var Bot_1 = require("./bot/Bot");
5
- Object.defineProperty(exports, "Bot", { enumerable: true, get: function () { return Bot_1.Bot; } });
6
- var BotEnv_1 = require("./bot/BotEnv");
7
- Object.defineProperty(exports, "BotEnv", { enumerable: true, get: function () { return BotEnv_1.BotEnv; } });
8
- // Manager
9
- var FileManager_1 = require("./manager/FileManager");
10
- Object.defineProperty(exports, "FileManager", { enumerable: true, get: function () { return FileManager_1.FileManager; } });
11
- var EmbedManager_1 = require("./manager/messages/EmbedManager");
12
- Object.defineProperty(exports, "EmbedManager", { enumerable: true, get: function () { return EmbedManager_1.EmbedManager; } });
13
- Object.defineProperty(exports, "EmbedColor", { enumerable: true, get: function () { return EmbedManager_1.EmbedColor; } });
14
- var WebhookManager_1 = require("./manager/messages/WebhookManager");
15
- Object.defineProperty(exports, "WebhookManager", { enumerable: true, get: function () { return WebhookManager_1.WebhookManager; } });
16
- var ReactionManager_1 = require("./manager/messages/ReactionManager");
17
- Object.defineProperty(exports, "ReactionManager", { enumerable: true, get: function () { return ReactionManager_1.ReactionManager; } });
18
- var GuildManager_1 = require("./manager/guild/GuildManager");
19
- Object.defineProperty(exports, "GuildManager", { enumerable: true, get: function () { return GuildManager_1.GuildManager; } });
20
- var UserManager_1 = require("./manager/direct/UserManager");
21
- Object.defineProperty(exports, "UserManager", { enumerable: true, get: function () { return UserManager_1.UserManager; } });
22
- // Handlers
23
- var ModalManager_1 = require("./manager/interactions/ModalManager");
24
- Object.defineProperty(exports, "ModalManager", { enumerable: true, get: function () { return ModalManager_1.ModalManager; } });
25
- var SelectMenuManager_1 = require("./manager/interactions/SelectMenuManager");
26
- Object.defineProperty(exports, "SelectMenuManager", { enumerable: true, get: function () { return SelectMenuManager_1.SelectMenuManager; } });
27
- // Utils
28
- var UnitTime_1 = require("./utils/times/UnitTime");
29
- Object.defineProperty(exports, "Time", { enumerable: true, get: function () { return UnitTime_1.Time; } });
30
- var Log_1 = require("./utils/Log");
31
- Object.defineProperty(exports, "Log", { enumerable: true, get: function () { return Log_1.Log; } });
32
- var SimpleMutex_1 = require("./utils/SimpleMutex");
33
- Object.defineProperty(exports, "SimpleMutex", { enumerable: true, get: function () { return SimpleMutex_1.SimpleMutex; } });
34
- var DiscordRegex_1 = require("./utils/DiscordRegex");
35
- Object.defineProperty(exports, "DiscordRegex", { enumerable: true, get: function () { return DiscordRegex_1.DiscordRegex; } });
36
- var SimpleDiscordBotInfo_1 = require("./SimpleDiscordBotInfo");
37
- Object.defineProperty(exports, "SimpleDiscordBotInfo", { enumerable: true, get: function () { return SimpleDiscordBotInfo_1.SimpleDiscordBotInfo; } });
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/index.ts
31
+ var index_exports = {};
32
+ __export(index_exports, {
33
+ Bot: () => Bot,
34
+ BotEnv: () => BotEnv,
35
+ DiscordRegex: () => DiscordRegex,
36
+ EmbedColor: () => EmbedColor,
37
+ EmbedManager: () => EmbedManager,
38
+ FileManager: () => FileManager,
39
+ GuildManager: () => GuildManager,
40
+ Log: () => Log,
41
+ ModalManager: () => ModalManager,
42
+ ReactionManager: () => ReactionManager,
43
+ SelectMenuManager: () => SelectMenuManager,
44
+ SimpleDiscordBotInfo: () => SimpleDiscordBotInfo,
45
+ SimpleMutex: () => SimpleMutex,
46
+ Time: () => Time,
47
+ UserManager: () => UserManager,
48
+ WebhookManager: () => WebhookManager
49
+ });
50
+ module.exports = __toCommonJS(index_exports);
51
+
52
+ // src/bot/Bot.ts
53
+ var import_discord5 = require("discord.js");
54
+
55
+ // src/utils/times/UnitTime.ts
56
+ var UnitTime = class {
57
+ constructor(val) {
58
+ this.val = val;
59
+ }
60
+ toMilliseconds() {
61
+ return this.val;
62
+ }
63
+ toSeconds() {
64
+ return this.val / 1e3;
65
+ }
66
+ toMinutes() {
67
+ return this.val / (60 * 1e3);
68
+ }
69
+ toHours() {
70
+ return this.val / (60 * 60 * 1e3);
71
+ }
72
+ toDays() {
73
+ return this.val / (24 * 60 * 60 * 1e3);
74
+ }
75
+ toString() {
76
+ return this.val.toString();
77
+ }
78
+ valueOf() {
79
+ return this.val;
80
+ }
81
+ value() {
82
+ return this.val;
83
+ }
84
+ };
85
+ var Milliseconds = {
86
+ MS_100: new UnitTime(100),
87
+ MS_200: new UnitTime(200),
88
+ MS_500: new UnitTime(500),
89
+ MS_800: new UnitTime(800),
90
+ MS_1000: new UnitTime(1e3)
91
+ };
92
+ var Seconds = {
93
+ SEC_01: new UnitTime(1e3),
94
+ SEC_02: new UnitTime(2e3),
95
+ SEC_03: new UnitTime(3e3),
96
+ SEC_04: new UnitTime(4e3),
97
+ SEC_05: new UnitTime(5e3),
98
+ SEC_06: new UnitTime(6e3),
99
+ SEC_07: new UnitTime(7e3),
100
+ SEC_08: new UnitTime(8e3),
101
+ SEC_09: new UnitTime(9e3),
102
+ SEC_10: new UnitTime(1e4),
103
+ SEC_11: new UnitTime(11e3),
104
+ SEC_12: new UnitTime(12e3),
105
+ SEC_13: new UnitTime(13e3),
106
+ SEC_14: new UnitTime(14e3),
107
+ SEC_15: new UnitTime(15e3),
108
+ SEC_16: new UnitTime(16e3),
109
+ SEC_17: new UnitTime(17e3),
110
+ SEC_18: new UnitTime(18e3),
111
+ SEC_19: new UnitTime(19e3),
112
+ SEC_20: new UnitTime(2e4),
113
+ SEC_21: new UnitTime(21e3),
114
+ SEC_22: new UnitTime(22e3),
115
+ SEC_23: new UnitTime(23e3),
116
+ SEC_24: new UnitTime(24e3),
117
+ SEC_25: new UnitTime(25e3),
118
+ SEC_26: new UnitTime(26e3),
119
+ SEC_27: new UnitTime(27e3),
120
+ SEC_28: new UnitTime(28e3),
121
+ SEC_29: new UnitTime(29e3),
122
+ SEC_30: new UnitTime(3e4),
123
+ SEC_31: new UnitTime(31e3),
124
+ SEC_32: new UnitTime(32e3),
125
+ SEC_33: new UnitTime(33e3),
126
+ SEC_34: new UnitTime(34e3),
127
+ SEC_35: new UnitTime(35e3),
128
+ SEC_36: new UnitTime(36e3),
129
+ SEC_37: new UnitTime(37e3),
130
+ SEC_38: new UnitTime(38e3),
131
+ SEC_39: new UnitTime(39e3),
132
+ SEC_40: new UnitTime(4e4),
133
+ SEC_41: new UnitTime(41e3),
134
+ SEC_42: new UnitTime(42e3),
135
+ SEC_43: new UnitTime(43e3),
136
+ SEC_44: new UnitTime(44e3),
137
+ SEC_45: new UnitTime(45e3),
138
+ SEC_46: new UnitTime(46e3),
139
+ SEC_47: new UnitTime(47e3),
140
+ SEC_48: new UnitTime(48e3),
141
+ SEC_49: new UnitTime(49e3),
142
+ SEC_50: new UnitTime(5e4),
143
+ SEC_51: new UnitTime(51e3),
144
+ SEC_52: new UnitTime(52e3),
145
+ SEC_53: new UnitTime(53e3),
146
+ SEC_54: new UnitTime(54e3),
147
+ SEC_55: new UnitTime(55e3),
148
+ SEC_56: new UnitTime(56e3),
149
+ SEC_57: new UnitTime(57e3),
150
+ SEC_58: new UnitTime(58e3),
151
+ SEC_59: new UnitTime(59e3),
152
+ SEC_60: new UnitTime(6e4)
153
+ };
154
+ var Minutes = {
155
+ MIN_01: new UnitTime(6e4),
156
+ MIN_02: new UnitTime(12e4),
157
+ MIN_03: new UnitTime(18e4),
158
+ MIN_04: new UnitTime(24e4),
159
+ MIN_05: new UnitTime(3e5),
160
+ MIN_06: new UnitTime(36e4),
161
+ MIN_07: new UnitTime(42e4),
162
+ MIN_08: new UnitTime(48e4),
163
+ MIN_09: new UnitTime(54e4),
164
+ MIN_10: new UnitTime(6e5),
165
+ MIN_11: new UnitTime(66e4),
166
+ MIN_12: new UnitTime(72e4),
167
+ MIN_13: new UnitTime(78e4),
168
+ MIN_14: new UnitTime(84e4),
169
+ MIN_15: new UnitTime(9e5),
170
+ MIN_16: new UnitTime(96e4),
171
+ MIN_17: new UnitTime(102e4),
172
+ MIN_18: new UnitTime(108e4),
173
+ MIN_19: new UnitTime(114e4),
174
+ MIN_20: new UnitTime(12e5),
175
+ MIN_21: new UnitTime(126e4),
176
+ MIN_22: new UnitTime(132e4),
177
+ MIN_23: new UnitTime(138e4),
178
+ MIN_24: new UnitTime(144e4),
179
+ MIN_25: new UnitTime(15e5),
180
+ MIN_26: new UnitTime(156e4),
181
+ MIN_27: new UnitTime(162e4),
182
+ MIN_28: new UnitTime(168e4),
183
+ MIN_29: new UnitTime(174e4),
184
+ MIN_30: new UnitTime(18e5),
185
+ MIN_31: new UnitTime(186e4),
186
+ MIN_32: new UnitTime(192e4),
187
+ MIN_33: new UnitTime(198e4),
188
+ MIN_34: new UnitTime(204e4),
189
+ MIN_35: new UnitTime(21e5),
190
+ MIN_36: new UnitTime(216e4),
191
+ MIN_37: new UnitTime(222e4),
192
+ MIN_38: new UnitTime(228e4),
193
+ MIN_39: new UnitTime(234e4),
194
+ MIN_40: new UnitTime(24e5),
195
+ MIN_41: new UnitTime(246e4),
196
+ MIN_42: new UnitTime(252e4),
197
+ MIN_43: new UnitTime(258e4),
198
+ MIN_44: new UnitTime(264e4),
199
+ MIN_45: new UnitTime(27e5),
200
+ MIN_46: new UnitTime(276e4),
201
+ MIN_47: new UnitTime(282e4),
202
+ MIN_48: new UnitTime(288e4),
203
+ MIN_49: new UnitTime(294e4),
204
+ MIN_50: new UnitTime(3e6),
205
+ MIN_51: new UnitTime(306e4),
206
+ MIN_52: new UnitTime(312e4),
207
+ MIN_53: new UnitTime(318e4),
208
+ MIN_54: new UnitTime(324e4),
209
+ MIN_55: new UnitTime(33e5),
210
+ MIN_56: new UnitTime(336e4),
211
+ MIN_57: new UnitTime(342e4),
212
+ MIN_58: new UnitTime(348e4),
213
+ MIN_59: new UnitTime(354e4),
214
+ MIN_60: new UnitTime(36e5)
215
+ };
216
+ var Hours = {
217
+ HOUR_01: new UnitTime(36e5),
218
+ HOUR_02: new UnitTime(72e5),
219
+ HOUR_03: new UnitTime(108e5),
220
+ HOUR_04: new UnitTime(144e5),
221
+ HOUR_05: new UnitTime(18e6),
222
+ HOUR_06: new UnitTime(216e5),
223
+ HOUR_07: new UnitTime(252e5),
224
+ HOUR_08: new UnitTime(288e5),
225
+ HOUR_09: new UnitTime(324e5),
226
+ HOUR_10: new UnitTime(36e6),
227
+ HOUR_11: new UnitTime(396e5),
228
+ HOUR_12: new UnitTime(432e5),
229
+ HOUR_13: new UnitTime(468e5),
230
+ HOUR_14: new UnitTime(504e5),
231
+ HOUR_15: new UnitTime(54e6),
232
+ HOUR_16: new UnitTime(576e5),
233
+ HOUR_17: new UnitTime(612e5),
234
+ HOUR_18: new UnitTime(648e5),
235
+ HOUR_19: new UnitTime(684e5),
236
+ HOUR_20: new UnitTime(72e6),
237
+ HOUR_21: new UnitTime(756e5),
238
+ HOUR_22: new UnitTime(792e5),
239
+ HOUR_23: new UnitTime(828e5),
240
+ HOUR_24: new UnitTime(864e5)
241
+ };
242
+ var Days = {
243
+ DAY_01: new UnitTime(864e5),
244
+ DAY_02: new UnitTime(1728e5),
245
+ DAY_03: new UnitTime(2592e5),
246
+ DAY_04: new UnitTime(3456e5),
247
+ DAY_05: new UnitTime(432e6),
248
+ DAY_06: new UnitTime(5184e5),
249
+ DAY_07: new UnitTime(6048e5),
250
+ DAY_08: new UnitTime(6912e5),
251
+ DAY_09: new UnitTime(7776e5),
252
+ DAY_10: new UnitTime(864e6)
253
+ };
254
+ var Time = {
255
+ milisecond: Milliseconds,
256
+ second: Seconds,
257
+ minute: Minutes,
258
+ hour: Hours,
259
+ day: Days,
260
+ get DAY() {
261
+ const h = (/* @__PURE__ */ new Date()).getHours();
262
+ return h >= 7 && h < 23;
263
+ },
264
+ get NIGHT() {
265
+ return !this.DAY;
266
+ }
267
+ };
268
+
269
+ // src/utils/Log.ts
270
+ var Log = class {
271
+ static getPrefix(level) {
272
+ const now = /* @__PURE__ */ new Date();
273
+ const timestamp = `[${now.toLocaleDateString()} - ${now.toLocaleTimeString()}]`;
274
+ return `${timestamp} [${level.toUpperCase()}]`;
275
+ }
276
+ static info(message) {
277
+ console.info(`${this.getPrefix("info")} ${message}`);
278
+ }
279
+ static warn(message) {
280
+ console.warn(`${this.getPrefix("warn")} ${message}`);
281
+ }
282
+ static error(message) {
283
+ console.error(`${this.getPrefix("error")} ${message}`);
284
+ }
285
+ static debug(message) {
286
+ console.debug(`${this.getPrefix("debug")} ${message}`);
287
+ }
288
+ static table(data) {
289
+ const prefix = this.getPrefix("table");
290
+ console.info(`${prefix} Table output:`);
291
+ console.table(data);
292
+ }
293
+ };
294
+
295
+ // src/utils/network/InternetChecker.ts
296
+ var InternetChecker = class {
297
+ /**
298
+ * Check internet connection towards 1.1.1.1 (Cloudflare DNS)
299
+ * @param tries Number of attempts (0 = infini)
300
+ */
301
+ static async checkConnection(tries = 0) {
302
+ let attempt = 0;
303
+ Log.info(
304
+ tries > 0 ? `HTTP ping ${this.TARGET} (max ${tries} attempts)...` : `HTTP ping ${this.TARGET} (infinite attempts)...`
305
+ );
306
+ while (tries === 0 || attempt < tries) {
307
+ try {
308
+ const controller = new AbortController();
309
+ const timeoutId = setTimeout(() => controller.abort(), 5e3);
310
+ const response = await fetch(this.TARGET, {
311
+ method: "HEAD",
312
+ signal: controller.signal,
313
+ cache: "no-store"
314
+ });
315
+ clearTimeout(timeoutId);
316
+ if (response.ok) {
317
+ const latency = response.headers.get("x-response-time") || "<1ms";
318
+ Log.info(`Internet connection OK (${latency})`);
319
+ return true;
320
+ }
321
+ } catch (error) {
322
+ attempt++;
323
+ const errorMsg = error.name === "AbortError" ? "Timeout (5s)" : error.message || "Unknown";
324
+ Log.warn(
325
+ tries > 0 ? `Ping failed (${errorMsg}) - Attempt ${attempt}/${tries}` : `Ping failed (${errorMsg}) - Retrying in ${this.RETRY_TIME.toSeconds()} seconds...`
326
+ );
327
+ try {
328
+ await new Promise((resolve) => setTimeout(resolve, this.RETRY_TIME.toMilliseconds()));
329
+ } catch {
330
+ Log.error("Retry delay failed.");
331
+ }
332
+ }
333
+ }
334
+ Log.error(`No response from ${this.TARGET} after all attempts.`);
335
+ return false;
336
+ }
337
+ };
338
+ InternetChecker.TARGET = "https://1.1.1.1";
339
+ // Cloudflare DNS HTTPS
340
+ InternetChecker.RETRY_TIME = Time.second.SEC_30;
341
+
342
+ // src/bot/BotLog.ts
343
+ var import_discord = require("discord.js");
344
+ var _BotLog = class _BotLog {
345
+ constructor() {
346
+ }
347
+ static config() {
348
+ return Bot.config.log;
349
+ }
350
+ /**
351
+ * Initialize Discord logging channels and update Bot.log references
352
+ */
353
+ static async initDiscordLogging() {
354
+ if (!Bot.client.isReady()) {
355
+ Log.warn("Client not ready for Discord logging init");
356
+ return;
357
+ }
358
+ if (Bot.config.log?.logChannelId) {
359
+ try {
360
+ const logCh = await Bot.client.channels.fetch(Bot.config.log.logChannelId);
361
+ if (logCh?.isTextBased()) {
362
+ _BotLog.logChannel = logCh;
363
+ } else {
364
+ Log.warn(`\u274C Log channel ${Bot.config.log.logChannelId} invalid`);
365
+ }
366
+ } catch (error) {
367
+ Log.error(`\u274C Log channel fetch failed: ${error}`);
368
+ }
369
+ }
370
+ if (Bot.config.log?.errorChannelId) {
371
+ try {
372
+ const errorCh = await Bot.client.channels.fetch(Bot.config.log.errorChannelId);
373
+ if (errorCh?.isTextBased()) {
374
+ _BotLog.errorChannel = errorCh;
375
+ } else {
376
+ Log.warn(`\u274C Error channel ${Bot.config.log.errorChannelId} invalid`);
377
+ }
378
+ } catch (error) {
379
+ Log.error(`\u274C Error channel fetch failed: ${error}`);
380
+ }
381
+ }
382
+ }
383
+ /**
384
+ * Send content to specific Discord channel
385
+ */
386
+ static async _sendToChannel(channel, content, prefix = "info") {
387
+ if (!channel) return;
388
+ let msg;
389
+ try {
390
+ if (content instanceof import_discord.EmbedBuilder) {
391
+ msg = await channel.send({ embeds: [content] });
392
+ } else {
393
+ const timestamp = `\`${(/* @__PURE__ */ new Date()).toISOString()}\``;
394
+ msg = await channel.send(`${prefix.toUpperCase()} ${timestamp} ${content}`);
395
+ }
396
+ } catch (error) {
397
+ Log.error(`Failed to send to Discord channel: ${error}`);
398
+ }
399
+ return msg;
400
+ }
401
+ /**
402
+ * Send INFO log - TEXT or EMBED ! Respecte config.log.info
403
+ */
404
+ static async info(content) {
405
+ const logConfig = Bot.config.log;
406
+ if (!logConfig || logConfig.info.console) {
407
+ if (!(content instanceof import_discord.EmbedBuilder)) {
408
+ Log.info(content);
409
+ }
410
+ }
411
+ if (logConfig?.info.discord && this.logChannel) {
412
+ return await this._sendToChannel(this.logChannel, content, "info");
413
+ }
414
+ }
415
+ /**
416
+ * Send ERROR log - TEXT or EMBED ! Respecte config.log.error
417
+ */
418
+ static async error(content) {
419
+ const logConfig = Bot.config.log;
420
+ if (!logConfig || logConfig.error.console) {
421
+ if (!(content instanceof import_discord.EmbedBuilder)) {
422
+ Log.error(content);
423
+ }
424
+ }
425
+ if (logConfig?.error.discord && this.errorChannel) {
426
+ return await this._sendToChannel(this.errorChannel, content, "error");
427
+ }
428
+ }
429
+ /**
430
+ * Send WARNING log - TEXT or EMBED ! Respecte config.log.warn
431
+ */
432
+ static async warn(content) {
433
+ const logConfig = Bot.config.log;
434
+ if (!logConfig || logConfig?.warn.console) {
435
+ if (!(content instanceof import_discord.EmbedBuilder)) {
436
+ Log.warn(content);
437
+ }
438
+ }
439
+ if (logConfig?.warn.discord && this.logChannel) {
440
+ return await this._sendToChannel(this.logChannel, content, "warn");
441
+ }
442
+ }
443
+ /**
444
+ * Send DEBUG log - TEXT or EMBED ! Respecte config.log.debug
445
+ */
446
+ static async debug(content) {
447
+ const logConfig = Bot.config.log;
448
+ if (!logConfig || logConfig?.debug.console) {
449
+ if (!(content instanceof import_discord.EmbedBuilder)) {
450
+ Log.debug(content);
451
+ }
452
+ }
453
+ if (logConfig?.debug.discord && this.logChannel) {
454
+ return await this._sendToChannel(this.logChannel, content, "debug");
455
+ }
456
+ }
457
+ };
458
+ _BotLog.logChannel = null;
459
+ _BotLog.errorChannel = null;
460
+ var BotLog = _BotLog;
461
+
462
+ // src/manager/messages/EmbedManager.ts
463
+ var import_discord2 = require("discord.js");
464
+ var EmbedColor = /* @__PURE__ */ ((EmbedColor3) => {
465
+ EmbedColor3[EmbedColor3["error"] = 8912917] = "error";
466
+ EmbedColor3[EmbedColor3["success"] = 65280] = "success";
467
+ EmbedColor3[EmbedColor3["black"] = 0] = "black";
468
+ EmbedColor3[EmbedColor3["white"] = 16777215] = "white";
469
+ EmbedColor3[EmbedColor3["red"] = 16711680] = "red";
470
+ EmbedColor3[EmbedColor3["green"] = 65280] = "green";
471
+ EmbedColor3[EmbedColor3["blue"] = 255] = "blue";
472
+ EmbedColor3[EmbedColor3["yellow"] = 16776960] = "yellow";
473
+ EmbedColor3[EmbedColor3["cyan"] = 65535] = "cyan";
474
+ EmbedColor3[EmbedColor3["magenta"] = 16711935] = "magenta";
475
+ EmbedColor3[EmbedColor3["gray"] = 8421504] = "gray";
476
+ EmbedColor3[EmbedColor3["lightgray"] = 13882323] = "lightgray";
477
+ EmbedColor3[EmbedColor3["darkgray"] = 11119017] = "darkgray";
478
+ EmbedColor3[EmbedColor3["orange"] = 16753920] = "orange";
479
+ EmbedColor3[EmbedColor3["purple"] = 8388736] = "purple";
480
+ EmbedColor3[EmbedColor3["pink"] = 16761035] = "pink";
481
+ EmbedColor3[EmbedColor3["brown"] = 10824234] = "brown";
482
+ EmbedColor3[EmbedColor3["lime"] = 65280] = "lime";
483
+ EmbedColor3[EmbedColor3["navy"] = 128] = "navy";
484
+ EmbedColor3[EmbedColor3["teal"] = 32896] = "teal";
485
+ EmbedColor3[EmbedColor3["olive"] = 8421376] = "olive";
486
+ EmbedColor3[EmbedColor3["gold"] = 16766720] = "gold";
487
+ EmbedColor3[EmbedColor3["silver"] = 12632256] = "silver";
488
+ EmbedColor3[EmbedColor3["coral"] = 16744272] = "coral";
489
+ EmbedColor3[EmbedColor3["salmon"] = 16416882] = "salmon";
490
+ EmbedColor3[EmbedColor3["khaki"] = 15787660] = "khaki";
491
+ EmbedColor3[EmbedColor3["plum"] = 14524637] = "plum";
492
+ EmbedColor3[EmbedColor3["lavender"] = 15132410] = "lavender";
493
+ EmbedColor3[EmbedColor3["beige"] = 16119260] = "beige";
494
+ EmbedColor3[EmbedColor3["mint"] = 10026904] = "mint";
495
+ EmbedColor3[EmbedColor3["peach"] = 16767673] = "peach";
496
+ EmbedColor3[EmbedColor3["chocolate"] = 13789470] = "chocolate";
497
+ EmbedColor3[EmbedColor3["crimson"] = 14423100] = "crimson";
498
+ EmbedColor3[EmbedColor3["youtube"] = 16718362] = "youtube";
499
+ EmbedColor3[EmbedColor3["default"] = 6064856] = "default";
500
+ EmbedColor3[EmbedColor3["minecraft"] = 25600] = "minecraft";
501
+ return EmbedColor3;
502
+ })(EmbedColor || {});
503
+ var EmbedManager = class {
504
+ static get BOT_ICON() {
505
+ return Bot.config.botIconUrl || "";
506
+ }
507
+ static get DEFAULT_COLOR() {
508
+ return Bot.config.defaultEmbedColor || 6064856 /* default */;
509
+ }
510
+ /**
511
+ * Creates base embed - SAME SIMPLE API !
512
+ */
513
+ static create(color = null) {
514
+ const embed = new import_discord2.EmbedBuilder().setColor(color ?? this.DEFAULT_COLOR).setTimestamp(/* @__PURE__ */ new Date());
515
+ if (this.BOT_ICON && Bot.config.botName) {
516
+ embed.setFooter({
517
+ text: Bot.config.botName,
518
+ iconURL: this.BOT_ICON
519
+ });
520
+ }
521
+ return embed;
522
+ }
523
+ /**
524
+ * Creates simple embed with just description
525
+ */
526
+ static simple(description, color = null) {
527
+ return this.create(color).setTitle("").setDescription(description).setTimestamp(null);
528
+ }
529
+ /**
530
+ * Creates error embed
531
+ */
532
+ static error(description) {
533
+ return this.create(8912917 /* error */).setTitle("Something went Wrong").setDescription(description);
534
+ }
535
+ /**
536
+ * Creates success embed
537
+ */
538
+ static success(description) {
539
+ return this.create(25600 /* minecraft */).setTitle("Success").setDescription(description);
540
+ }
541
+ /**
542
+ * Creates success embed
543
+ */
544
+ static description(description) {
545
+ return this.create(25600 /* minecraft */).setDescription(description);
546
+ }
547
+ /**
548
+ * Creates debug embed
549
+ */
550
+ static debug(description) {
551
+ return this.create(65280 /* green */).setTitle("Debug").setDescription(description);
552
+ }
553
+ /**
554
+ * Defer ephemeral reply
555
+ */
556
+ static deferEphemeral() {
557
+ return { flags: import_discord2.MessageFlags.Ephemeral };
558
+ }
559
+ /**
560
+ * Quick field adder
561
+ */
562
+ static field(embed, name, value, inline = false) {
563
+ return embed.addFields({ name, value, inline });
564
+ }
565
+ static fields(embed, fields) {
566
+ fields.forEach((f) => {
567
+ embed.addFields({ name: f.name, value: f.value, inline: f.inline ?? false });
568
+ });
569
+ return embed;
570
+ }
571
+ /**
572
+ * Fluent API shortcuts
573
+ */
574
+ static title(embed, title) {
575
+ return embed.setTitle(title);
576
+ }
577
+ static desc(embed, description) {
578
+ return embed.setDescription(description);
579
+ }
580
+ static thumb(embed, url) {
581
+ return embed.setThumbnail(url);
582
+ }
583
+ static image(embed, url) {
584
+ return embed.setImage(url);
585
+ }
586
+ static footer(embed, text) {
587
+ return embed.setFooter({ text, iconURL: this.BOT_ICON });
588
+ }
589
+ /**
590
+ * Transform embed into objet for interaction.reply()
591
+ */
592
+ static toInteraction(embed, ephemeral = false) {
593
+ return {
594
+ embeds: [embed],
595
+ flags: ephemeral ? [import_discord2.MessageFlags.Ephemeral] : void 0
596
+ };
597
+ }
598
+ /**
599
+ * Transform embed into objet to send a message
600
+ */
601
+ static toMessage(embed) {
602
+ return {
603
+ embeds: [embed]
604
+ };
605
+ }
606
+ };
607
+
608
+ // src/bot/BotMessage.ts
609
+ var import_discord4 = require("discord.js");
610
+
611
+ // src/manager/builder/SendableComponentBuilder.ts
612
+ var import_discord3 = require("discord.js");
613
+ var SendableComponentBuilder = class {
614
+ static isSendableComponent(thing) {
615
+ return thing instanceof import_discord3.EmbedBuilder || thing instanceof import_discord3.ActionRowBuilder;
616
+ }
617
+ static build(base, content, components) {
618
+ if (content) {
619
+ base.content = content;
620
+ }
621
+ const comps = Array.isArray(components) ? components : [components].filter(Boolean);
622
+ for (const comp of comps) {
623
+ if (comp instanceof import_discord3.EmbedBuilder) {
624
+ base.embeds = base.embeds || [];
625
+ base.embeds.push(comp);
626
+ }
627
+ if (comp instanceof import_discord3.ActionRowBuilder) {
628
+ base.components = base.components || [];
629
+ base.components.push(comp);
630
+ }
631
+ }
632
+ return base;
633
+ }
634
+ static buildInteraction(contentOrComponent, component, ephemeral = false) {
635
+ let base = {};
636
+ if (typeof contentOrComponent === "string" && !component) {
637
+ base = this.build(base, contentOrComponent);
638
+ }
639
+ if (typeof contentOrComponent !== "string" && !component) {
640
+ base = this.build(base, null, contentOrComponent);
641
+ }
642
+ if (contentOrComponent && typeof contentOrComponent === "string" && component) {
643
+ base = this.build(base, contentOrComponent, component);
644
+ }
645
+ if (ephemeral) {
646
+ base.flags = [import_discord3.MessageFlags.Ephemeral];
647
+ }
648
+ return base;
649
+ }
650
+ static buildMessage(contentOrComponent, component) {
651
+ let base = {};
652
+ if (typeof contentOrComponent === "string" && !component) {
653
+ return this.build(base, contentOrComponent);
654
+ }
655
+ if (typeof contentOrComponent !== "string" && !component) {
656
+ return this.build(base, null, contentOrComponent);
657
+ }
658
+ if (typeof contentOrComponent == "string" && component) {
659
+ return this.build(base, contentOrComponent, component);
660
+ }
661
+ throw new Error("At least content or component need to be defined to build a message");
662
+ }
663
+ };
664
+
665
+ // src/bot/BotMessage.ts
666
+ var BotMessage = class {
667
+ static async send(channel, content, component) {
668
+ try {
669
+ if (!channel) {
670
+ Log.warn("Cannot send message: invalid channel");
671
+ return null;
672
+ }
673
+ if (typeof channel === "string") {
674
+ const fetchedChannel = Bot.client.channels.cache.get(channel);
675
+ if (!fetchedChannel?.isTextBased()) {
676
+ Log.warn(`Invalid channel ID: ${channel}`);
677
+ return null;
678
+ }
679
+ channel = fetchedChannel;
680
+ }
681
+ let messageCreate;
682
+ if (typeof content !== "string" && !component) {
683
+ if (SendableComponentBuilder.isSendableComponent(content)) {
684
+ messageCreate = SendableComponentBuilder.buildMessage(content);
685
+ } else {
686
+ messageCreate = content;
687
+ }
688
+ } else {
689
+ content = content;
690
+ if (content && component) {
691
+ messageCreate = SendableComponentBuilder.buildMessage(content, component);
692
+ } else if (content) {
693
+ messageCreate = SendableComponentBuilder.buildMessage(content);
694
+ } else if (component) {
695
+ messageCreate = SendableComponentBuilder.buildMessage(component);
696
+ } else {
697
+ throw new Error("content and component cannot be null at the same time");
698
+ }
699
+ }
700
+ try {
701
+ return await channel.send(messageCreate);
702
+ } catch (e) {
703
+ throw e;
704
+ }
705
+ } catch (e) {
706
+ Log.error(`Failed to send message : ${e}`);
707
+ return null;
708
+ }
709
+ }
710
+ static async sendDM(user, content, component) {
711
+ try {
712
+ let targetUser;
713
+ if (user instanceof import_discord4.User || user instanceof import_discord4.GuildMember) {
714
+ targetUser = user instanceof import_discord4.GuildMember ? user.user : user;
715
+ } else {
716
+ targetUser = await Bot.client.users.fetch(user);
717
+ }
718
+ let messageCreate;
719
+ if (content && component) {
720
+ messageCreate = SendableComponentBuilder.buildMessage(content, component);
721
+ } else if (content) {
722
+ messageCreate = SendableComponentBuilder.buildMessage(content);
723
+ } else if (component) {
724
+ messageCreate = SendableComponentBuilder.buildMessage(component);
725
+ } else {
726
+ throw new Error("content and component cannot be null at the same time");
727
+ }
728
+ return await targetUser.send(messageCreate);
729
+ } catch (error) {
730
+ Log.error(`Failed to send message to ${user}: ${error}`);
731
+ return null;
732
+ }
733
+ }
734
+ /**
735
+ * Quick success message
736
+ */
737
+ static success(channel, message) {
738
+ const embed = EmbedManager.success(message);
739
+ if (channel instanceof import_discord4.User || channel instanceof import_discord4.GuildMember) {
740
+ return this.sendDM(channel, message, embed);
741
+ }
742
+ return this.send(channel, message, embed);
743
+ }
744
+ /**
745
+ * Quick error message
746
+ */
747
+ static error(channel, message) {
748
+ const embed = EmbedManager.error(message);
749
+ if (channel instanceof import_discord4.User || channel instanceof import_discord4.GuildMember) {
750
+ return this.sendDM(channel, message, embed);
751
+ }
752
+ return this.send(channel, message, embed);
753
+ }
754
+ };
755
+
756
+ // src/utils/DiscordRegex.ts
757
+ var _DiscordRegex = class _DiscordRegex {
758
+ /**
759
+ * Validate Discord ID Discord (18)
760
+ */
761
+ static isDiscordId(id) {
762
+ return this.USER_ID.test(id) || this.GUILD_ID.test(id) || this.CHANNEL_ID.test(id);
763
+ }
764
+ /**
765
+ * Validate a bot ID (19)
766
+ */
767
+ static isBotMention(mention) {
768
+ return this.BOT_REGEX.test(mention);
769
+ }
770
+ /**
771
+ * Validate a User ping
772
+ */
773
+ static isUserMention(mention) {
774
+ return this.USER_REGEX.test(mention);
775
+ }
776
+ /**
777
+ * Validate a Discord username
778
+ */
779
+ static isUsername(username) {
780
+ return this.USERNAME.test(username);
781
+ }
782
+ /**
783
+ * Type guard for Discord ID
784
+ */
785
+ static isDiscordIdType(id) {
786
+ return this.isDiscordId(id);
787
+ }
788
+ /**
789
+ * Any Discord URL
790
+ */
791
+ static isDiscordUrl(url) {
792
+ return this.URL_REGEX.test(url) || this.INVITE.test(url);
793
+ }
794
+ /**
795
+ * Any discord mention
796
+ */
797
+ static isAnyMention(text) {
798
+ return this.DISCORD_MENTION_REGEX.test(text);
799
+ }
800
+ /**
801
+ * List all regex
802
+ */
803
+ static listAll() {
804
+ return {
805
+ SPACE: this.SPACE,
806
+ URL_REGEX: this.URL_REGEX,
807
+ USER_REGEX: this.USER_REGEX,
808
+ BOT_REGEX: this.BOT_REGEX,
809
+ CHANNEL_REGEX: this.CHANNEL_REGEX,
810
+ ROLE_REGEX: this.ROLE_REGEX,
811
+ DISCORD_PING_REGEX: this.DISCORD_PING_REGEX,
812
+ DISCORD_MENTION_REGEX: this.DISCORD_MENTION_REGEX,
813
+ USER_ID: this.USER_ID,
814
+ CHANNEL_ID: this.CHANNEL_ID,
815
+ GUILD_ID: this.GUILD_ID,
816
+ USERNAME: this.USERNAME,
817
+ USERNAME_DISCRIM: this.USERNAME_DISCRIM,
818
+ CHANNEL_MENTION: this.CHANNEL_MENTION,
819
+ USER_MENTION: this.USER_MENTION,
820
+ ROLE_MENTION: this.ROLE_MENTION,
821
+ INVITE: this.INVITE,
822
+ EMOJI: this.EMOJI
823
+ };
824
+ }
825
+ };
826
+ // Caractères spéciaux
827
+ _DiscordRegex.SPACE = "\u200B";
828
+ // URLs basiques
829
+ _DiscordRegex.URL_REGEX = /(https?:\/\/[^s]+)/;
830
+ /* DISCORD REGEX */
831
+ _DiscordRegex.USER_REGEX = /<@\d{18}>/;
832
+ _DiscordRegex.BOT_REGEX = /<@\d{19}>/;
833
+ _DiscordRegex.CHANNEL_REGEX = /(<#\d{19}>)|(<id:(browse|customize|guide)>)/;
834
+ _DiscordRegex.ROLE_REGEX = /<@&\d{19}>/;
835
+ /**
836
+ * Mention a User
837
+ * Mention a Role
838
+ */
839
+ _DiscordRegex.DISCORD_PING_REGEX = new RegExp(
840
+ `(${_DiscordRegex.USER_REGEX.source})|(${_DiscordRegex.BOT_REGEX.source})|(${_DiscordRegex.ROLE_REGEX.source})`
841
+ );
842
+ /**
843
+ * Mention a User
844
+ * Mention a Role
845
+ * Mention a Channel
846
+ */
847
+ _DiscordRegex.DISCORD_MENTION_REGEX = new RegExp(
848
+ `(${_DiscordRegex.DISCORD_PING_REGEX.source})|(${_DiscordRegex.CHANNEL_REGEX.source})`
849
+ );
850
+ // ID Discord (user, channel guild)
851
+ _DiscordRegex.USER_ID = /^[0-9]{18}$/;
852
+ _DiscordRegex.CHANNEL_ID = /^[0-9]{18}$/;
853
+ _DiscordRegex.GUILD_ID = /^[0-9]{19}$/;
854
+ _DiscordRegex.BOT_ID = /^[0-9]{19}$/;
855
+ // Username Discord (2-32 caractères alphanumériques + _ .)
856
+ _DiscordRegex.USERNAME = /^[a-zA-Z0-9_]{2,32}$/;
857
+ // Username + discrim (ancien format)
858
+ _DiscordRegex.USERNAME_DISCRIM = /^[a-zA-Z0-9_]{2,32}#\d{4}$/;
859
+ // Channel mention <#123456789012345678>
860
+ _DiscordRegex.CHANNEL_MENTION = /^<#([0-9]{18})>$/;
861
+ // User mention <@123456789012345678> ou <@!123456789012345678>
862
+ _DiscordRegex.USER_MENTION = /^<@!?([0-9]{18})>$/;
863
+ // Role mention <@&123456789012345678>
864
+ _DiscordRegex.ROLE_MENTION = /^<@&([0-9]{18})>$/;
865
+ // URL Invite Discord
866
+ _DiscordRegex.INVITE = /^discord(?:app\.com\/invite|gg)\/[a-zA-Z0-9]+$/;
867
+ // Emoji Discord (custom or unicode)
868
+ _DiscordRegex.EMOJI = /^<a?:[a-zA-Z0-9_]{2,32}:[0-9]{18}>$|^[\u{1F300}-\u{1F5FF}\u{1F600}-\u{1F64F}\u{1F680}-\u{1F6FF}\u{2600}-\u{26FF}\u{2700}-\u{27BF}]+$/u;
869
+ var DiscordRegex = _DiscordRegex;
870
+
871
+ // src/bot/BotEnv.ts
872
+ var BotEnv = {
873
+ get token() {
874
+ const token = process.env.DISCORD_BOT_TOKEN;
875
+ if (!token) throw new Error("Missing environment variable : DISCORD_BOT_TOKEN");
876
+ return token;
877
+ },
878
+ get dev() {
879
+ return process.env.DEV === "true";
880
+ },
881
+ get clientId() {
882
+ const token = process.env.DISCORD_BOT_CLIENTID;
883
+ if (!token) throw new Error("Missing environment variable : DISCORD_BOT_CLIENTID");
884
+ if (!DiscordRegex.BOT_ID.test(token)) {
885
+ throw new Error("Invalid token format");
886
+ }
887
+ return token;
888
+ }
889
+ };
890
+
891
+ // src/bot/BotInteraction.ts
892
+ var BotInteraction = class {
893
+ /**
894
+ * InteractionReplyOptions && InteractionUpdateOptions
895
+ * The two have "content", "embeds" & "flags" field, so an internal cast is ok, unless discord/discordjs deprecate it
896
+ */
897
+ static buildReplyOptions(content, component, ephemeral) {
898
+ return this._buildOptions(content, component, ephemeral);
899
+ }
900
+ static buildUpdateOptions(content, component) {
901
+ return this._buildOptions(content, component, false);
902
+ }
903
+ static _buildOptions(content, component, ephemeral) {
904
+ return SendableComponentBuilder.buildInteraction(content, component, ephemeral);
905
+ }
906
+ static async send(interaction, content, component = false, ephemeral = false) {
907
+ if (!interaction.isRepliable()) return false;
908
+ const options = this.buildReplyOptions(
909
+ typeof content === "string" ? content : "",
910
+ typeof content === "string" ? component : content,
911
+ typeof content === "string" ? ephemeral : component
912
+ );
913
+ if (!interaction.deferred && !interaction.replied) {
914
+ return await interaction.reply(options);
915
+ } else {
916
+ return await interaction.followUp(options);
917
+ }
918
+ }
919
+ static async reply(interaction, content, component = false, ephemeral = false) {
920
+ if (!interaction.isRepliable()) return false;
921
+ const options = this.buildReplyOptions(
922
+ typeof content === "string" ? content : "",
923
+ typeof content === "string" ? component : content,
924
+ typeof content === "string" ? ephemeral : component
925
+ );
926
+ return interaction.reply(options);
927
+ }
928
+ static async followUp(interaction, content, component = false, ephemeral = false) {
929
+ if (!interaction.isRepliable()) return false;
930
+ const options = this.buildReplyOptions(
931
+ typeof content === "string" ? content : "",
932
+ typeof content === "string" ? component : content,
933
+ typeof content === "string" ? ephemeral : component
934
+ );
935
+ return interaction.followUp(options);
936
+ }
937
+ static async defer(interaction) {
938
+ if (!interaction.isRepliable()) return;
939
+ if (interaction.isChatInputCommand() || interaction.isContextMenuCommand()) {
940
+ if (!interaction.deferred && !interaction.replied) {
941
+ await interaction.deferReply();
942
+ }
943
+ return;
944
+ }
945
+ if (interaction.isButton() || interaction.isAnySelectMenu() || interaction.isModalSubmit()) {
946
+ if (!interaction.deferred && !interaction.replied) {
947
+ await interaction.deferUpdate();
948
+ }
949
+ }
950
+ }
951
+ static async update(interaction, content, component) {
952
+ if (!interaction.isRepliable()) return false;
953
+ const options = this.buildUpdateOptions(
954
+ typeof content === "string" ? content : "",
955
+ typeof content === "string" ? component : content
956
+ );
957
+ if (interaction.isMessageComponent()) {
958
+ return await interaction.update(options);
959
+ }
960
+ if (interaction.deferred || interaction.replied) {
961
+ return await interaction.editReply(options);
962
+ }
963
+ return false;
964
+ }
965
+ };
966
+
967
+ // src/bot/Bot.ts
968
+ var _Bot = class _Bot {
969
+ get config() {
970
+ return _Bot._config;
971
+ }
972
+ get client() {
973
+ return _Bot._client;
974
+ }
975
+ static get client() {
976
+ return _Bot._client;
977
+ }
978
+ static get config() {
979
+ return _Bot._config;
980
+ }
981
+ constructor(client, config) {
982
+ Log.info("----------------------------------------------------");
983
+ Log.info("Starting Bot");
984
+ _Bot.criticConfig = { dev: BotEnv.dev, token: BotEnv.token };
985
+ _Bot._config = { ...config, clientId: BotEnv.clientId };
986
+ _Bot._client = client;
987
+ (async () => {
988
+ Log.info(`Using discord.js version: ${import_discord5.version}`);
989
+ Log.info("Trying to connect to Discord Servers");
990
+ await InternetChecker.checkConnection(3);
991
+ await this.login();
992
+ })();
993
+ }
994
+ async login(maxTries = 3) {
995
+ let success = false;
996
+ let tries = 0;
997
+ while (!success && tries < maxTries) {
998
+ try {
999
+ await _Bot._client.login(_Bot.criticConfig.token);
1000
+ success = true;
1001
+ _Bot._client.on(import_discord5.Events.ClientReady, async () => {
1002
+ if (_Bot._client.user) {
1003
+ await _Bot.log.initDiscordLogging();
1004
+ Log.info(`Connected on ${_Bot._client.guilds.cache.size} servers as ${_Bot._client.user.tag}`);
1005
+ _Bot.log.info(EmbedManager.description("Bot Started"));
1006
+ }
1007
+ });
1008
+ } catch (error) {
1009
+ Log.error(`Connection error : ${error}. Trying again...`);
1010
+ tries++;
1011
+ await new Promise(
1012
+ (resolve) => setTimeout(resolve, Time.second.SEC_03.toMilliseconds())
1013
+ );
1014
+ }
1015
+ }
1016
+ if (!success) {
1017
+ Log.error("Impossible to connect the bot after 3 attempts");
1018
+ return false;
1019
+ }
1020
+ return true;
1021
+ }
1022
+ static setActivity(message, type) {
1023
+ if (_Bot._client.user) {
1024
+ _Bot._client.user.setActivity({ name: message, type });
1025
+ Log.info(`Activity defined : ${message}`);
1026
+ }
1027
+ }
1028
+ static setRandomActivity(randomActivity, intervalMs = null) {
1029
+ if (randomActivity.length == 0) {
1030
+ Log.error("Bot.randomActivity = [{}] is empty");
1031
+ return;
1032
+ }
1033
+ const pickRandom = () => {
1034
+ const random = randomActivity[Math.floor(Math.random() * randomActivity.length)];
1035
+ _Bot.setActivity(random.message, random.type);
1036
+ return random;
1037
+ };
1038
+ if (intervalMs === null) {
1039
+ pickRandom();
1040
+ Log.info(`Activity set ONCE`);
1041
+ return;
1042
+ }
1043
+ pickRandom();
1044
+ setInterval(async () => {
1045
+ pickRandom();
1046
+ }, intervalMs);
1047
+ Log.info(`Random activity started (every ${Math.round(intervalMs / 6e4)}min)`);
1048
+ return;
1049
+ }
1050
+ };
1051
+ // Static ref
1052
+ _Bot.log = BotLog;
1053
+ _Bot.message = BotMessage;
1054
+ _Bot.interaction = BotInteraction;
1055
+ var Bot = _Bot;
1056
+
1057
+ // src/manager/FileManager.ts
1058
+ var import_path = __toESM(require("path"));
1059
+ var import_promises = __toESM(require("fs/promises"));
1060
+ var FileManager = class {
1061
+ /**
1062
+ * Reads a JSON file synchronously.
1063
+ * @param filePath Full path to the JSON file
1064
+ * @returns Parsed JSON object or 'Error' string on failure
1065
+ */
1066
+ static async readJsonFile(filePath) {
1067
+ try {
1068
+ const data = await import_promises.default.readFile(filePath, "utf8");
1069
+ return JSON.parse(data);
1070
+ } catch (error) {
1071
+ Log.error(`Failed to read JSON file ${filePath}: ${error}`);
1072
+ return false;
1073
+ }
1074
+ }
1075
+ /**
1076
+ * Lists all directories in a given path.
1077
+ * @param directoryPath Path to scan for directories
1078
+ * @returns Array of directory names or false on error
1079
+ */
1080
+ static async listDirectories(directoryPath) {
1081
+ try {
1082
+ const files = await import_promises.default.readdir(directoryPath, { withFileTypes: true });
1083
+ const directories = files.filter((file) => file.isDirectory()).map((dir) => dir.name);
1084
+ return directories;
1085
+ } catch (error) {
1086
+ Log.error(`Failed to read directory ${directoryPath}: ${error}`);
1087
+ return false;
1088
+ }
1089
+ }
1090
+ /**
1091
+ * Lists all JSON files in a directory.
1092
+ * @param directoryPath Path to scan for JSON files
1093
+ * @returns Array of JSON filenames or false on error
1094
+ */
1095
+ static async listJsonFiles(directoryPath) {
1096
+ try {
1097
+ const files = await import_promises.default.readdir(directoryPath);
1098
+ return files.filter((file) => import_path.default.extname(file) === ".json");
1099
+ } catch (error) {
1100
+ Log.error(`Failed to read directory ${directoryPath}: ${error}`);
1101
+ return false;
1102
+ }
1103
+ }
1104
+ /**
1105
+ * Lists files with specific extension in a directory.
1106
+ * @param directoryPath Path to scan
1107
+ * @param extension File extension (with or without dot)
1108
+ * @returns Array of matching filenames or 'Error' string on failure
1109
+ */
1110
+ static async listFiles(directoryPath, extension) {
1111
+ if (typeof directoryPath !== "string" || typeof extension !== "string") {
1112
+ Log.error("Directory path and extension must be strings");
1113
+ return false;
1114
+ }
1115
+ try {
1116
+ let ext = extension;
1117
+ if (ext.startsWith(".")) {
1118
+ ext = ext.slice(1);
1119
+ }
1120
+ const files = await import_promises.default.readdir(directoryPath);
1121
+ return files.filter((file) => import_path.default.extname(file) === `.${ext}`);
1122
+ } catch (error) {
1123
+ Log.error(`Failed to read directory ${directoryPath}: ${error}`);
1124
+ return false;
1125
+ }
1126
+ }
1127
+ /**
1128
+ * Creates directory structure and writes JSON data to file.
1129
+ * @param directoryPath Full directory path (creates if missing)
1130
+ * @param filename Filename without extension
1131
+ * @param data Data to write (JSON serializable)
1132
+ * @param sendErrorToErrorChannel Send error to the error channel
1133
+ * @returns true on success, false on failure
1134
+ */
1135
+ static async writeJsonFile(directoryPath, filename, data, sendErrorToErrorChannel = true) {
1136
+ if (Array.isArray(data) && data.length === 1 && data[0] === "Error") {
1137
+ Log.error(`Cannot save data for ${filename}: data contains 'Error'`);
1138
+ return false;
1139
+ }
1140
+ try {
1141
+ const directories = directoryPath.split(import_path.default.sep).filter(Boolean);
1142
+ let currentPath = "";
1143
+ for (const dir of directories) {
1144
+ currentPath = import_path.default.join(currentPath, dir);
1145
+ try {
1146
+ await import_promises.default.access(currentPath);
1147
+ } catch {
1148
+ await import_promises.default.mkdir(currentPath, { recursive: true });
1149
+ }
1150
+ }
1151
+ if (!filename || filename.trim() === "") {
1152
+ Log.error("Cannot write JSON file: empty filename");
1153
+ return false;
1154
+ }
1155
+ const cleanFilename = filename.replace(/\.json$/i, "");
1156
+ const filePath = import_path.default.join(directoryPath, `${cleanFilename}.json`);
1157
+ const jsonContent = JSON.stringify(data, null, 2);
1158
+ await import_promises.default.writeFile(filePath, jsonContent);
1159
+ Log.info(`Successfully wrote data to ${filePath}`);
1160
+ return true;
1161
+ } catch (error) {
1162
+ const cleanFilename = filename.replace(/\.json$/i, "") || "unknown";
1163
+ if (sendErrorToErrorChannel) {
1164
+ await Bot.log.info(EmbedManager.error(`Failed to write file ${directoryPath}/${cleanFilename}.json: ${error}`));
1165
+ } else {
1166
+ Log.error(`Failed to write file ${directoryPath}/${cleanFilename}.json: ${error}`);
1167
+ }
1168
+ return false;
1169
+ }
1170
+ }
1171
+ };
1172
+
1173
+ // src/manager/messages/WebhookManager.ts
1174
+ var import_discord6 = require("discord.js");
1175
+ var WebhookManager = class {
1176
+ constructor(channel, name = Bot.config.botName || "", avatarURL) {
1177
+ this.channel = channel;
1178
+ this.name = name;
1179
+ this.avatarURL = avatarURL;
1180
+ this.webhook = null;
1181
+ }
1182
+ get textChannel() {
1183
+ return this.channel instanceof import_discord6.ThreadChannel ? this.channel.parent : this.channel;
1184
+ }
1185
+ /**
1186
+ * Get or create webhook (lazy initialization)
1187
+ */
1188
+ async getWebhook() {
1189
+ if (this.webhook) return this.webhook;
1190
+ try {
1191
+ const webhooks = await this.textChannel.fetchWebhooks();
1192
+ this.webhook = webhooks.find((h) => h.name === this.name) ?? await this.textChannel.createWebhook({
1193
+ name: this.name,
1194
+ avatar: this.avatarURL,
1195
+ reason: "Auto-created by WebhookManager"
1196
+ });
1197
+ Log.info(`Webhook ${this.webhook.id} ready for ${this.textChannel.id}`);
1198
+ return this.webhook;
1199
+ } catch (error) {
1200
+ Log.error(`Failed to setup webhook: ${error}`);
1201
+ throw error;
1202
+ }
1203
+ }
1204
+ async send(content) {
1205
+ const webhook = await this.getWebhook();
1206
+ const options = {};
1207
+ if (SendableComponentBuilder.isSendableComponent(content)) {
1208
+ const t = SendableComponentBuilder.buildMessage(content);
1209
+ options.embeds = t.embeds;
1210
+ options.components = t.components;
1211
+ } else if (typeof content == "string") {
1212
+ options.content = content;
1213
+ } else if (typeof content === "object") {
1214
+ Object.assign(options, content);
1215
+ } else {
1216
+ options.content = content;
1217
+ }
1218
+ if (this.channel instanceof import_discord6.ThreadChannel) {
1219
+ options.threadId = this.channel.id;
1220
+ }
1221
+ try {
1222
+ const message = await webhook.send(options);
1223
+ Log.info(`Webhook sent to ${this.channel.id}: ${content}`);
1224
+ return message;
1225
+ } catch (error) {
1226
+ Log.error(`Webhook send failed ${this.channel.id}: ${error}`);
1227
+ return null;
1228
+ }
1229
+ }
1230
+ /**
1231
+ * Quick success embed
1232
+ */
1233
+ async success(message) {
1234
+ return await this.send(EmbedManager.success(message));
1235
+ }
1236
+ /**
1237
+ * Quick error embed
1238
+ */
1239
+ async error(message) {
1240
+ return await this.send(EmbedManager.error(message));
1241
+ }
1242
+ /**
1243
+ * Delete webhook
1244
+ */
1245
+ async delete(reason) {
1246
+ if (!this.webhook) return;
1247
+ try {
1248
+ await this.webhook.delete(reason ?? "Deleted by WebhookManager");
1249
+ Log.info(`Webhook ${this.webhook.id} deleted`);
1250
+ } catch (error) {
1251
+ if (error.message.includes("Unknown Webhook")) {
1252
+ Log.warn("Webhook already deleted");
1253
+ } else {
1254
+ Log.error(`Failed to delete webhook: ${error}`);
1255
+ }
1256
+ } finally {
1257
+ this.webhook = null;
1258
+ }
1259
+ }
1260
+ };
1261
+
1262
+ // src/manager/guild/ChannelManager/GuildTextChannelManager.ts
1263
+ var import_discord7 = require("discord.js");
1264
+
1265
+ // src/manager/guild/ChannelManager/GuildMessageManager.ts
1266
+ var GuildMessageManager = class {
1267
+ /**
1268
+ * Impl
1269
+ */
1270
+ static async send(channelId, content_or_component_or_options) {
1271
+ try {
1272
+ const channel = await GuildTextChannelManager.find(channelId);
1273
+ if (!channel) {
1274
+ Log.error(`Channel ${channelId} not found in guild`);
1275
+ return null;
1276
+ }
1277
+ let payload;
1278
+ if (typeof content_or_component_or_options === "string") {
1279
+ payload = SendableComponentBuilder.buildMessage(content_or_component_or_options);
1280
+ } else if (SendableComponentBuilder.isSendableComponent(content_or_component_or_options) || Array.isArray(content_or_component_or_options)) {
1281
+ payload = SendableComponentBuilder.buildMessage(content_or_component_or_options);
1282
+ } else {
1283
+ payload = content_or_component_or_options;
1284
+ }
1285
+ return await channel.send(payload);
1286
+ } catch (error) {
1287
+ Log.error(`Failed to send message to ${channelId}: ${error}`);
1288
+ throw error;
1289
+ }
1290
+ }
1291
+ /**
1292
+ * Delete message
1293
+ */
1294
+ static async delete(channelId, messageId) {
1295
+ try {
1296
+ const channel = await GuildTextChannelManager.find(channelId);
1297
+ if (!channel) {
1298
+ Log.error(`Channel ${channelId} not found`);
1299
+ return false;
1300
+ }
1301
+ const message = await channel.messages.fetch(messageId);
1302
+ await message.delete();
1303
+ Log.info(`Deleted message ${messageId} from ${channelId}`);
1304
+ return true;
1305
+ } catch (error) {
1306
+ Log.error(`Failed to delete message ${messageId} from ${channelId}: ${error}`);
1307
+ return false;
1308
+ }
1309
+ }
1310
+ /**
1311
+ * Fetch messages (last X messages, default 10)
1312
+ */
1313
+ static async fetch(channelId, limit = 10) {
1314
+ try {
1315
+ const channel = await GuildTextChannelManager.find(channelId);
1316
+ if (!channel) {
1317
+ Log.error(`Channel ${channelId} not found`);
1318
+ return [];
1319
+ }
1320
+ const messages = await channel.messages.fetch({ limit });
1321
+ Log.info(`Fetched ${messages.size} messages from ${channelId}`);
1322
+ return Array.from(messages.values());
1323
+ } catch (error) {
1324
+ Log.error(`Failed to fetch messages from ${channelId}: ${error}`);
1325
+ return [];
1326
+ }
1327
+ }
1328
+ /**
1329
+ * Fetch single message
1330
+ */
1331
+ static async fetchOne(channelId, messageId) {
1332
+ try {
1333
+ const channel = await GuildTextChannelManager.find(channelId);
1334
+ if (!channel) {
1335
+ Log.error(`Channel ${channelId} not found`);
1336
+ return null;
1337
+ }
1338
+ const message = await channel.messages.fetch(messageId);
1339
+ return message;
1340
+ } catch (error) {
1341
+ Log.error(`Failed to fetch message ${messageId} from ${channelId}: ${error}`);
1342
+ return null;
1343
+ }
1344
+ }
1345
+ };
1346
+
1347
+ // src/manager/guild/ChannelManager/GuildChannelManager.ts
1348
+ var _GuildChannelManager = class _GuildChannelManager {
1349
+ /**
1350
+ * Recherche un channel par ID dans une guild spécifique
1351
+ */
1352
+ static async findInGuild(guildId, channelId) {
1353
+ try {
1354
+ const guild = Bot.client.guilds.cache.get(guildId);
1355
+ if (!guild) {
1356
+ Log.warn(`Guild ${guildId} not found`);
1357
+ return null;
1358
+ }
1359
+ const channel = await guild.channels.fetch(channelId);
1360
+ return channel ?? null;
1361
+ } catch (error) {
1362
+ Log.error(`Failed to find channel ${channelId} in guild ${guildId}: ${error}`);
1363
+ return null;
1364
+ }
1365
+ }
1366
+ static async find(channelId) {
1367
+ for (const guild of Bot.client.guilds.cache.values()) {
1368
+ try {
1369
+ const channel = await guild.channels.fetch(channelId);
1370
+ if (channel) return channel;
1371
+ } catch {
1372
+ }
1373
+ }
1374
+ Log.warn(`Channel ${channelId} not found in any guild`);
1375
+ return null;
1376
+ }
1377
+ static findAll(guildId) {
1378
+ const guild = Bot.client.guilds.cache.get(guildId);
1379
+ if (!guild) {
1380
+ Log.warn(`Guild ${guildId} not found`);
1381
+ return [];
1382
+ }
1383
+ return Array.from(guild.channels.cache.values());
1384
+ }
1385
+ /**
1386
+ * Recherche channels par nom (insensible à la casse)
1387
+ */
1388
+ static findByName(guildId, name) {
1389
+ const guild = Bot.client.guilds.cache.get(guildId);
1390
+ if (!guild) {
1391
+ Log.warn(`Guild ${guildId} not found`);
1392
+ return [];
1393
+ }
1394
+ return Array.from(guild.channels.cache.values()).filter(
1395
+ (channel) => channel.name.toLowerCase().includes(name.toLowerCase())
1396
+ );
1397
+ }
1398
+ static async _create(guildId, options) {
1399
+ try {
1400
+ const guild = Bot.client.guilds.cache.get(guildId);
1401
+ if (!guild) {
1402
+ throw new Error(`Guild ${guildId} not found`);
1403
+ }
1404
+ const channel = await guild.channels.create(options);
1405
+ Log.info(`Created channel ${channel.name} (${channel.id}) in guild ${guildId}`);
1406
+ return channel;
1407
+ } catch (error) {
1408
+ Log.error(`Failed to create channel in guild ${guildId}: ${error}`);
1409
+ throw error;
1410
+ }
1411
+ }
1412
+ static async delete(channelId) {
1413
+ try {
1414
+ const channel = await _GuildChannelManager.find(channelId);
1415
+ if (!channel) {
1416
+ throw new Error(`Channel ${channelId} not found`);
1417
+ }
1418
+ await channel.delete();
1419
+ Log.info(`Deleted channel ${channelId}`);
1420
+ return true;
1421
+ } catch (error) {
1422
+ Log.error(`Failed to delete channel ${channelId}: ${error}`);
1423
+ throw error;
1424
+ }
1425
+ }
1426
+ };
1427
+ _GuildChannelManager.message = GuildMessageManager;
1428
+ var GuildChannelManager = _GuildChannelManager;
1429
+
1430
+ // src/manager/guild/ChannelManager/GuildTextChannelManager.ts
1431
+ var GuildTextChannelManager = class extends GuildChannelManager {
1432
+ static async findInGuild(guildId, channelId) {
1433
+ const channel = await super.findInGuild(guildId, channelId);
1434
+ return channel?.isTextBased() ? channel : null;
1435
+ }
1436
+ static async find(channelId) {
1437
+ const channel = await super.find(channelId);
1438
+ return channel?.isTextBased() ? channel : null;
1439
+ }
1440
+ static findAll(guildId) {
1441
+ const guild = Bot.client.guilds.cache.get(guildId);
1442
+ if (!guild) {
1443
+ Log.warn(`Guild ${guildId} not found`);
1444
+ return [];
1445
+ }
1446
+ return Array.from(guild.channels.cache.values()).filter((c) => c instanceof import_discord7.TextChannel);
1447
+ }
1448
+ static async create(guildId, name, options) {
1449
+ return await super._create(guildId, {
1450
+ name,
1451
+ type: import_discord7.ChannelType.GuildText,
1452
+ ...options
1453
+ });
1454
+ }
1455
+ };
1456
+
1457
+ // src/manager/messages/ReactionManager.ts
1458
+ var ReactionManager = class {
1459
+ /**
1460
+ * Add a reaction to a message
1461
+ */
1462
+ static async add(channelId, messageId, emoji) {
1463
+ try {
1464
+ const channel = await GuildTextChannelManager.find(channelId);
1465
+ if (!channel) {
1466
+ throw new Error(`Channel ${channelId} not found`);
1467
+ }
1468
+ if (!channel.isTextBased()) {
1469
+ throw new Error(`Channel ${channelId} is not text based`);
1470
+ }
1471
+ const message = await channel.messages.fetch(messageId);
1472
+ await message.react(emoji);
1473
+ Log.info(`Added reaction ${emoji} to message ${messageId}`);
1474
+ } catch (error) {
1475
+ Log.error(`Failed to add reaction to ${messageId}: ${error}`);
1476
+ throw error;
1477
+ }
1478
+ }
1479
+ /**
1480
+ * Delete a reaction from a user
1481
+ */
1482
+ static async remove(channelId, messageId, emoji, userId) {
1483
+ try {
1484
+ const channel = await GuildTextChannelManager.find(channelId);
1485
+ if (!channel) {
1486
+ throw new Error(`Channel ${channelId} not found`);
1487
+ }
1488
+ const message = await channel.messages.fetch(messageId);
1489
+ const reaction = message.reactions.resolve(emoji);
1490
+ if (!reaction) {
1491
+ throw new Error(`Reaction ${emoji} not found on message ${messageId}`);
1492
+ }
1493
+ const user = await Bot.client.users.fetch(userId);
1494
+ await reaction.users.remove(user);
1495
+ Log.info(`Removed reaction ${emoji} from user ${userId} on message ${messageId}`);
1496
+ } catch (error) {
1497
+ Log.error(`Failed to remove reaction from ${messageId}: ${error}`);
1498
+ throw error;
1499
+ }
1500
+ }
1501
+ /**
1502
+ * Get all reaction of a message
1503
+ */
1504
+ static async getAll(channelId, messageId) {
1505
+ try {
1506
+ const channel = await GuildTextChannelManager.find(channelId);
1507
+ if (!channel) {
1508
+ throw new Error(`Channel ${channelId} not found`);
1509
+ }
1510
+ const message = await channel.messages.fetch(messageId);
1511
+ const reactions = message.reactions.cache;
1512
+ const reactionList = [];
1513
+ for (const reaction of reactions.values()) {
1514
+ const users = await reaction.users.fetch();
1515
+ reactionList.push({
1516
+ emoji: reaction.emoji,
1517
+ count: reaction.count,
1518
+ users: Array.from(users.values())
1519
+ });
1520
+ }
1521
+ Log.info(`Fetched ${reactionList.length} reactions for message ${messageId}`);
1522
+ return reactionList;
1523
+ } catch (error) {
1524
+ Log.error(`Failed to fetch reactions for ${messageId}: ${error}`);
1525
+ throw error;
1526
+ }
1527
+ }
1528
+ /**
1529
+ * Delete all reaction
1530
+ */
1531
+ static async clear(channelId, messageId) {
1532
+ try {
1533
+ const channel = await GuildTextChannelManager.find(channelId);
1534
+ if (!channel) {
1535
+ throw new Error(`Channel ${channelId} not found`);
1536
+ }
1537
+ const message = await channel.messages.fetch(messageId);
1538
+ await message.reactions.removeAll();
1539
+ Log.info(`Cleared all reactions from message ${messageId}`);
1540
+ } catch (error) {
1541
+ Log.error(`Failed to clear reactions from ${messageId}: ${error}`);
1542
+ throw error;
1543
+ }
1544
+ }
1545
+ };
1546
+
1547
+ // src/manager/guild/GuildManager.ts
1548
+ var import_discord14 = require("discord.js");
1549
+
1550
+ // src/manager/direct/BasicUserManager.ts
1551
+ var import_discord8 = require("discord.js");
1552
+ var BasicUserManager = class {
1553
+ /**
1554
+ * Find member in specific guild
1555
+ */
1556
+ static async findInGuild(guildId, memberId) {
1557
+ try {
1558
+ const guild = Bot.client.guilds.cache.get(guildId);
1559
+ if (!guild) throw new Error(`Guild ${guildId} not found`);
1560
+ const member = await guild.members.fetch({ user: memberId, force: true });
1561
+ return member ?? null;
1562
+ } catch (error) {
1563
+ Log.error(`UserManager: Member ${memberId} not found in ${guildId}`);
1564
+ return null;
1565
+ }
1566
+ }
1567
+ /**
1568
+ * Check if user is still in guild
1569
+ */
1570
+ static async isInGuild(guildId, userId) {
1571
+ try {
1572
+ const guild = Bot.client.guilds.cache.get(guildId);
1573
+ if (!guild) return false;
1574
+ await guild.members.fetch({ user: userId, force: true });
1575
+ return true;
1576
+ } catch (error) {
1577
+ return error.code !== 10007;
1578
+ }
1579
+ }
1580
+ /**
1581
+ * Impl
1582
+ */
1583
+ static async send(user_id_or_user, content_or_component_or_options, component) {
1584
+ try {
1585
+ let user;
1586
+ if (typeof user_id_or_user === "string") {
1587
+ user = await Bot.client.users.fetch(user_id_or_user);
1588
+ } else {
1589
+ user = user_id_or_user;
1590
+ }
1591
+ const dmChannel = await user.createDM();
1592
+ let payload;
1593
+ if (component && typeof content_or_component_or_options == "string") {
1594
+ payload = SendableComponentBuilder.buildMessage(
1595
+ content_or_component_or_options,
1596
+ component
1597
+ );
1598
+ } else if (typeof content_or_component_or_options === "string") {
1599
+ payload = SendableComponentBuilder.buildMessage(content_or_component_or_options);
1600
+ } else if (SendableComponentBuilder.isSendableComponent(content_or_component_or_options)) {
1601
+ payload = SendableComponentBuilder.buildMessage(content_or_component_or_options);
1602
+ } else {
1603
+ payload = content_or_component_or_options;
1604
+ }
1605
+ const message = await dmChannel.send(payload);
1606
+ if (user instanceof import_discord8.GuildMember) {
1607
+ Log.info(`Sent DM to ${user.id} (${user.user.username}): "${(payload.content || "Embed/Component").substring(0, 50)}..."`);
1608
+ } else {
1609
+ Log.info(`Sent DM to ${user.id} (${user.username}): "${(payload.content || "Embed/Component").substring(0, 50)}..."`);
1610
+ }
1611
+ return message;
1612
+ } catch (error) {
1613
+ Log.error(`Failed to send DM to ${user_id_or_user}: ${error}`);
1614
+ throw new Error(`Cannot send DM to ${user_id_or_user}`);
1615
+ }
1616
+ }
1617
+ };
1618
+
1619
+ // src/manager/guild/GuildUserManager.ts
1620
+ var import_discord9 = require("discord.js");
1621
+ var import_promises2 = require("timers/promises");
1622
+ var MAX_NICKNAME_LENGTH = 32;
1623
+ var GuildUserManager = class extends BasicUserManager {
1624
+ static async find(userId, guild) {
1625
+ try {
1626
+ if (guild instanceof import_discord9.Guild) {
1627
+ return await guild.members.fetch(userId);
1628
+ } else {
1629
+ return await (await GuildManager.find(guild)).members.fetch(userId);
1630
+ }
1631
+ } catch (error) {
1632
+ Log.error(`UserManager: Member ${userId} not found`);
1633
+ return null;
1634
+ }
1635
+ }
1636
+ static async rename(member, nickname, maxAttempts = 3) {
1637
+ if (nickname.length > MAX_NICKNAME_LENGTH) {
1638
+ nickname = nickname.slice(0, MAX_NICKNAME_LENGTH);
1639
+ }
1640
+ for (let attempts = 0; attempts < maxAttempts; attempts++) {
1641
+ try {
1642
+ const oldName = member.displayName;
1643
+ await member.setNickname(nickname.trim());
1644
+ Log.info(`Renaming user: ${oldName} \u2192 ${nickname.trim()}`);
1645
+ await (0, import_promises2.setTimeout)(1500);
1646
+ return true;
1647
+ } catch (error) {
1648
+ console.error(`Attempt ${attempts + 1} failed when renaming ${member.displayName} into ${nickname.trim()}:`, error);
1649
+ await (0, import_promises2.setTimeout)(1e3);
1650
+ }
1651
+ }
1652
+ Bot.log.info(EmbedManager.error(`Failed to rename ${member.displayName} to ${nickname.trim()} after ${maxAttempts} attempts.`));
1653
+ return false;
1654
+ }
1655
+ /**
1656
+ * Check if user is banned from guild
1657
+ */
1658
+ static async isBanned(guildId, userId) {
1659
+ try {
1660
+ const guild = Bot.client.guilds.cache.get(guildId);
1661
+ if (!guild) {
1662
+ Log.warn(`Guild ${guildId} not found`);
1663
+ return false;
1664
+ }
1665
+ const ban = await guild.bans.fetch(userId);
1666
+ return !!ban;
1667
+ } catch (error) {
1668
+ Log.debug(`User ${userId} is not banned from guild ${guildId}`);
1669
+ return false;
1670
+ }
1671
+ }
1672
+ /**
1673
+ * Deconnect a member from a voice
1674
+ */
1675
+ static async deconnectFromVoice(guildId, memberId) {
1676
+ try {
1677
+ const guild = Bot.client.guilds.cache.get(guildId);
1678
+ if (!guild) {
1679
+ throw new Error(`Guild ${guildId} not found`);
1680
+ }
1681
+ const member = await guild.members.fetch(memberId);
1682
+ if (!member.voice.channel) {
1683
+ throw new Error(`Member ${memberId} is not in a voice channel`);
1684
+ }
1685
+ await member.voice.disconnect();
1686
+ Log.info(`Disconnected member ${memberId} from voice in guild ${guildId}`);
1687
+ } catch (error) {
1688
+ Log.error(`Failed to disconnect member ${memberId} from voice in ${guildId}: ${error}`);
1689
+ throw error;
1690
+ }
1691
+ }
1692
+ /**
1693
+ * Check if a member is in voice
1694
+ */
1695
+ static async isInVoice(memberId, guildId) {
1696
+ try {
1697
+ const guild = Bot.client.guilds.cache.get(guildId);
1698
+ if (!guild) return false;
1699
+ const member = await guild.members.fetch(memberId);
1700
+ return member.voice.channelId !== null;
1701
+ } catch (error) {
1702
+ Log.debug(`Member ${memberId} not found or not in voice in guild ${guildId}`);
1703
+ return false;
1704
+ }
1705
+ }
1706
+ /**
1707
+ * Mute a member
1708
+ */
1709
+ static async mute(guildId, memberId, reason) {
1710
+ try {
1711
+ const guild = Bot.client.guilds.cache.get(guildId);
1712
+ if (!guild) throw new Error(`Guild ${guildId} not found`);
1713
+ const member = await guild.members.fetch(memberId);
1714
+ await member.voice.setMute(true, reason);
1715
+ Log.info(`Server muted ${memberId} in guild ${guildId}: ${reason || "No reason"}`);
1716
+ } catch (error) {
1717
+ Log.error(`Failed to server mute ${memberId} in ${guildId}:, error`);
1718
+ throw error;
1719
+ }
1720
+ }
1721
+ /**
1722
+ * Unmute a member
1723
+ */
1724
+ static async unmute(guildId, memberId, reason) {
1725
+ try {
1726
+ const guild = Bot.client.guilds.cache.get(guildId);
1727
+ if (!guild) throw new Error(`Guild ${guildId} not found`);
1728
+ const member = await guild.members.fetch(memberId);
1729
+ await member.voice.setMute(false, reason);
1730
+ Log.info(`Server unmuted ${memberId} in guild ${guildId}: ${reason || "No reason"}`);
1731
+ } catch (error) {
1732
+ Log.error(`Failed to server unmute ${memberId} in ${guildId}: ${error}`);
1733
+ throw error;
1734
+ }
1735
+ }
1736
+ /**
1737
+ * Deafen a member
1738
+ */
1739
+ static async deafen(guildId, memberId, reason) {
1740
+ try {
1741
+ const guild = Bot.client.guilds.cache.get(guildId);
1742
+ if (!guild) throw new Error(`Guild ${guildId} not found`);
1743
+ const member = await guild.members.fetch(memberId);
1744
+ await member.voice.setDeaf(true, reason);
1745
+ Log.info(`Server deafened ${memberId} in guild ${guildId}: ${reason || "No reason"}`);
1746
+ } catch (error) {
1747
+ Log.error(`Failed to server deafen ${memberId} in ${guildId}: ${error}`);
1748
+ throw error;
1749
+ }
1750
+ }
1751
+ /**
1752
+ * Undeafen member voice
1753
+ */
1754
+ static async undeafen(guildId, memberId, reason) {
1755
+ try {
1756
+ const guild = Bot.client.guilds.cache.get(guildId);
1757
+ if (!guild) throw new Error(`Guild ${guildId} not found`);
1758
+ const member = await guild.members.fetch(memberId);
1759
+ await member.voice.setDeaf(false, reason);
1760
+ Log.info(`Server undeafened ${memberId} in guild ${guildId}: ${reason || "No reason"}`);
1761
+ } catch (error) {
1762
+ Log.error(`Failed to server undeafen ${memberId} in ${guildId}: ${error}`);
1763
+ throw error;
1764
+ }
1765
+ }
1766
+ /**
1767
+ * Timeout a member
1768
+ */
1769
+ static async timeout(guildId, memberId, duration, reason) {
1770
+ try {
1771
+ const guild = Bot.client.guilds.cache.get(guildId);
1772
+ if (!guild) throw new Error(`Guild ${guildId} not found`);
1773
+ const member = await guild.members.fetch(memberId);
1774
+ const expires = Date.now() + duration;
1775
+ await member.timeout(expires, reason);
1776
+ Log.info(`Timed out ${memberId} for ${duration}ms in guild ${guildId}: ${reason || "No reason"}`);
1777
+ } catch (error) {
1778
+ Log.error(`Failed to timeout ${memberId} in ${guildId}: ${error}`);
1779
+ throw error;
1780
+ }
1781
+ }
1782
+ /**
1783
+ * Remove the timeout of a member
1784
+ */
1785
+ static async untimeout(guildId, memberId, reason) {
1786
+ try {
1787
+ const guild = Bot.client.guilds.cache.get(guildId);
1788
+ if (!guild) throw new Error(`Guild ${guildId} not found`);
1789
+ const member = await guild.members.fetch(memberId);
1790
+ await member.timeout(null, reason);
1791
+ Log.info(`Untimed out ${memberId} in guild ${guildId}: ${reason || "No reason"}`);
1792
+ } catch (error) {
1793
+ Log.error(`Failed to untimeout ${memberId} in ${guildId}: ${error}`);
1794
+ throw error;
1795
+ }
1796
+ }
1797
+ /**
1798
+ * Kick a member
1799
+ */
1800
+ static async kick(guildId, memberId, reason) {
1801
+ try {
1802
+ const guild = Bot.client.guilds.cache.get(guildId);
1803
+ if (!guild) throw new Error(`Guild ${guildId} not found`);
1804
+ const member = await guild.members.fetch(memberId);
1805
+ await member.kick(reason);
1806
+ Log.info(`Kicked ${memberId} from guild ${guildId}: ${reason || "No reason"}`);
1807
+ } catch (error) {
1808
+ Log.error(`Failed to kick ${memberId} from ${guildId}: ${error}`);
1809
+ throw error;
1810
+ }
1811
+ }
1812
+ static async ban(guildId, userId, banOption) {
1813
+ const guild = Bot.client.guilds.cache.get(guildId);
1814
+ if (!guild) {
1815
+ throw new Error(`Guild ${guildId} not found`);
1816
+ }
1817
+ try {
1818
+ await guild.members.ban(userId, banOption);
1819
+ Log.info(`Banned user ${userId} from guild ${guildId}`);
1820
+ } catch (error) {
1821
+ Log.error(`Failed to ban user ${userId} from guild ${guildId}: ${error}`);
1822
+ throw error;
1823
+ }
1824
+ }
1825
+ static async unban(guildId, userId, reason) {
1826
+ const guild = Bot.client.guilds.cache.get(guildId);
1827
+ if (!guild) {
1828
+ throw new Error(`Guild ${guildId} not found`);
1829
+ }
1830
+ try {
1831
+ await guild.members.unban(userId, reason);
1832
+ Log.info(`Unbanned user ${userId} from guild ${guildId}`);
1833
+ } catch (error) {
1834
+ Log.error(`Failed to unban user ${userId} from guild ${guildId}: ${error}`);
1835
+ throw error;
1836
+ }
1837
+ }
1838
+ };
1839
+
1840
+ // src/manager/guild/RoleManager.ts
1841
+ var RoleManager = class {
1842
+ /**
1843
+ * Add role - CACHE ONLY
1844
+ * @param member - GuildMember ALREADY FETCHED
1845
+ * @param roleId - Role ID (string)
1846
+ */
1847
+ static async add(member, roleId) {
1848
+ try {
1849
+ const role = member.roles.cache.get(roleId);
1850
+ if (!role) {
1851
+ Log.warn(`Role ${roleId} not found in cache`);
1852
+ return false;
1853
+ }
1854
+ await member.roles.add(role);
1855
+ Log.info(`\u2705 Added ${role.name} to ${member.displayName}`);
1856
+ return true;
1857
+ } catch (error) {
1858
+ Log.error(`Failed to add role ${roleId}: ${error}`);
1859
+ return false;
1860
+ }
1861
+ }
1862
+ /**
1863
+ * Remove role - CACHE ONLY
1864
+ * @param member - GuildMember ALREADY FETCHED
1865
+ * @param roleIdOrName - Role ID or name
1866
+ */
1867
+ static async remove(member, roleIdOrName) {
1868
+ try {
1869
+ let role;
1870
+ if (typeof roleIdOrName === "string" && roleIdOrName.length === 18) {
1871
+ role = member.roles.cache.get(roleIdOrName);
1872
+ } else {
1873
+ role = member.roles.cache.find(
1874
+ (r) => r.id === roleIdOrName || r.name.toLowerCase() === roleIdOrName.toString().toLowerCase()
1875
+ );
1876
+ }
1877
+ if (!role) {
1878
+ Log.warn(`Role ${roleIdOrName} not found for ${member.displayName}`);
1879
+ return false;
1880
+ }
1881
+ await member.roles.remove(role);
1882
+ Log.info(`\u2705 Removed ${role.name} from ${member.displayName}`);
1883
+ return true;
1884
+ } catch (error) {
1885
+ Log.error(`Failed to remove role ${roleIdOrName}: ${error}`);
1886
+ return false;
1887
+ }
1888
+ }
1889
+ /**
1890
+ * Toggle role (add/remove)
1891
+ */
1892
+ static async toggle(member, roleIdOrName) {
1893
+ const role = member.roles.cache.get(roleIdOrName) || member.roles.cache.find((r) => r.name.toLowerCase() === roleIdOrName.toString().toLowerCase());
1894
+ if (!role) {
1895
+ Log.warn(`Role ${roleIdOrName} not found`);
1896
+ throw new Error(`Role not found`);
1897
+ }
1898
+ if (member.roles.cache.has(role.id)) {
1899
+ await this.remove(member, role.id);
1900
+ return "removed";
1901
+ } else {
1902
+ await this.add(member, role.id);
1903
+ return "added";
1904
+ }
1905
+ }
1906
+ /**
1907
+ * Check if member has role
1908
+ */
1909
+ static hasRole(member, roleIdOrName) {
1910
+ if (typeof roleIdOrName === "string" && roleIdOrName.length === 18) {
1911
+ return member.roles.cache.has(roleIdOrName);
1912
+ }
1913
+ return member.roles.cache.some(
1914
+ (r) => r.id === roleIdOrName || r.name.toLowerCase() === roleIdOrName.toString().toLowerCase()
1915
+ );
1916
+ }
1917
+ };
1918
+
1919
+ // src/manager/guild/ChannelManager/ForumChannelManager.ts
1920
+ var import_discord10 = require("discord.js");
1921
+ var ForumChannelManager = class extends GuildChannelManager {
1922
+ static async findInGuild(guildId, channelId) {
1923
+ const channel = await super.findInGuild(guildId, channelId);
1924
+ return channel instanceof import_discord10.ForumChannel ? channel : null;
1925
+ }
1926
+ static async find(channelId) {
1927
+ const channel = await super.find(channelId);
1928
+ return channel instanceof import_discord10.ForumChannel ? channel : null;
1929
+ }
1930
+ static findAll(guildId) {
1931
+ const guild = Bot.client.guilds.cache.get(guildId);
1932
+ if (!guild) {
1933
+ Log.warn(`Guild ${guildId} not found`);
1934
+ return [];
1935
+ }
1936
+ return Array.from(guild.channels.cache.values()).filter((c) => c instanceof import_discord10.ForumChannel);
1937
+ }
1938
+ static async create(guildId, name, options) {
1939
+ return await super._create(guildId, {
1940
+ name,
1941
+ type: import_discord10.ChannelType.GuildForum,
1942
+ ...options
1943
+ });
1944
+ }
1945
+ };
1946
+
1947
+ // src/manager/guild/ChannelManager/NewsChannelManager.ts
1948
+ var import_discord11 = require("discord.js");
1949
+ var NewsChannelManager = class extends GuildChannelManager {
1950
+ static async findInGuild(guildId, channelId) {
1951
+ const channel = await super.findInGuild(guildId, channelId);
1952
+ return channel instanceof import_discord11.NewsChannel ? channel : null;
1953
+ }
1954
+ static async find(channelId) {
1955
+ const channel = await super.find(channelId);
1956
+ return channel instanceof import_discord11.NewsChannel ? channel : null;
1957
+ }
1958
+ static findAll(guildId) {
1959
+ const guild = Bot.client.guilds.cache.get(guildId);
1960
+ if (!guild) {
1961
+ Log.warn(`Guild ${guildId} not found`);
1962
+ return [];
1963
+ }
1964
+ return Array.from(guild.channels.cache.values()).filter((c) => c instanceof import_discord11.NewsChannel);
1965
+ }
1966
+ static async create(guildId, name, options) {
1967
+ return await super._create(guildId, {
1968
+ name,
1969
+ type: import_discord11.ChannelType.GuildAnnouncement,
1970
+ ...options
1971
+ });
1972
+ }
1973
+ };
1974
+
1975
+ // src/manager/guild/ChannelManager/StageChannelManager.ts
1976
+ var import_discord12 = require("discord.js");
1977
+ var StageChannelManager = class extends GuildChannelManager {
1978
+ static async findInGuild(guildId, channelId) {
1979
+ const channel = await super.findInGuild(guildId, channelId);
1980
+ return channel instanceof import_discord12.StageChannel ? channel : null;
1981
+ }
1982
+ static async find(channelId) {
1983
+ const channel = await super.find(channelId);
1984
+ return channel instanceof import_discord12.StageChannel ? channel : null;
1985
+ }
1986
+ static findAll(guildId) {
1987
+ const guild = Bot.client.guilds.cache.get(guildId);
1988
+ if (!guild) {
1989
+ Log.warn(`Guild ${guildId} not found`);
1990
+ return [];
1991
+ }
1992
+ return Array.from(guild.channels.cache.values()).filter((c) => c instanceof import_discord12.StageChannel);
1993
+ }
1994
+ static async create(guildId, name, options) {
1995
+ return await super._create(guildId, {
1996
+ name,
1997
+ type: import_discord12.ChannelType.GuildStageVoice,
1998
+ ...options
1999
+ });
2000
+ }
2001
+ };
2002
+
2003
+ // src/manager/guild/ChannelManager/ThreadChannelManager.ts
2004
+ var ThreadChannelManager = class {
2005
+ static async findInGuild(guildId, channelId) {
2006
+ const channel = await GuildChannelManager.findInGuild(guildId, channelId);
2007
+ return channel?.isThread() ? channel : null;
2008
+ }
2009
+ static async find(channelId) {
2010
+ const channel = await GuildChannelManager.find(channelId);
2011
+ return channel?.isThread() ? channel : null;
2012
+ }
2013
+ static findAll(guildId) {
2014
+ const channels = GuildChannelManager.findAll(guildId);
2015
+ return channels.filter((c) => c.isThread());
2016
+ }
2017
+ static async createFromChannel(parentId, options) {
2018
+ const channel = await GuildTextChannelManager.find(parentId);
2019
+ if (!channel || !channel.isTextBased()) {
2020
+ throw new Error("Parent must be a text-based channel");
2021
+ }
2022
+ const thread = await channel.threads.create(options);
2023
+ return thread;
2024
+ }
2025
+ static async createFromMessage(message, options) {
2026
+ const channel = await GuildChannelManager.find(message.id);
2027
+ if (!channel) throw new Error("Message channel not found");
2028
+ return await message.startThread(options);
2029
+ }
2030
+ /**
2031
+ * Impl
2032
+ */
2033
+ static async send(channelId, content_or_component_or_options) {
2034
+ if (typeof content_or_component_or_options == "string") {
2035
+ return await GuildTextChannelManager.message.send(channelId, content_or_component_or_options);
2036
+ } else if (SendableComponentBuilder.isSendableComponent(content_or_component_or_options) || Array.isArray(content_or_component_or_options)) {
2037
+ return await GuildTextChannelManager.message.send(channelId, content_or_component_or_options);
2038
+ } else {
2039
+ return await GuildTextChannelManager.message.send(channelId, content_or_component_or_options);
2040
+ }
2041
+ }
2042
+ };
2043
+
2044
+ // src/manager/guild/ChannelManager/GuildVoiceChannelManager.ts
2045
+ var import_discord13 = require("discord.js");
2046
+ var GuildVoiceChannelManager = class extends GuildChannelManager {
2047
+ static async findInGuild(guildId, channelId) {
2048
+ const channel = await super.findInGuild(guildId, channelId);
2049
+ return channel?.isVoiceBased() ? channel : null;
2050
+ }
2051
+ static async find(channelId) {
2052
+ const channel = await super.find(channelId);
2053
+ return channel?.isVoiceBased() ? channel : null;
2054
+ }
2055
+ static findAll(guildId) {
2056
+ const guild = Bot.client.guilds.cache.get(guildId);
2057
+ if (!guild) {
2058
+ Log.warn(`Guild ${guildId} not found`);
2059
+ return [];
2060
+ }
2061
+ return Array.from(guild.channels.cache.values()).filter((c) => c instanceof import_discord13.VoiceChannel);
2062
+ }
2063
+ static async create(guildId, name, options) {
2064
+ return await super._create(guildId, {
2065
+ name,
2066
+ type: import_discord13.ChannelType.GuildVoice,
2067
+ ...options
2068
+ });
2069
+ }
2070
+ };
2071
+
2072
+ // src/manager/guild/ChannelManager/GuildChannelList.ts
2073
+ var GuildChannelList = class {
2074
+ };
2075
+ GuildChannelList.forum = ForumChannelManager;
2076
+ GuildChannelList.any = GuildChannelManager;
2077
+ GuildChannelList.news = NewsChannelManager;
2078
+ GuildChannelList.stage = StageChannelManager;
2079
+ GuildChannelList.text = GuildTextChannelManager;
2080
+ GuildChannelList.thread = ThreadChannelManager;
2081
+ GuildChannelList.voice = GuildVoiceChannelManager;
2082
+
2083
+ // src/manager/guild/InviteManager.ts
2084
+ var InviteManager = class {
2085
+ /**
2086
+ * Create an invite for a channel
2087
+ */
2088
+ static async create(channelId, options = {}) {
2089
+ try {
2090
+ const channel = await GuildChannelManager.find(channelId);
2091
+ if (!channel) {
2092
+ throw new Error(`Channel ${channelId} not found`);
2093
+ }
2094
+ const guild = channel.guild;
2095
+ const inviteOptions = {
2096
+ maxAge: options.maxAge ?? 86400,
2097
+ maxUses: options.maxUses ?? 0,
2098
+ temporary: options.temporary ?? false,
2099
+ reason: options.reason
2100
+ };
2101
+ const invite = await guild.invites.create(channelId, inviteOptions);
2102
+ Log.info(`Created invite ${invite.code} for channel ${channelId}`);
2103
+ return invite;
2104
+ } catch (error) {
2105
+ Log.error(`Failed to create invite for channel ${channelId}: ${error}`);
2106
+ throw error;
2107
+ }
2108
+ }
2109
+ /**
2110
+ * Delete an invitation
2111
+ */
2112
+ static async delete(invite) {
2113
+ try {
2114
+ await invite.delete();
2115
+ Log.info(`Deleted invite ${invite.code} from guild ${invite.guild?.id}`);
2116
+ return true;
2117
+ } catch (error) {
2118
+ Log.error(`Failed to delete invite ${invite.code}: ${error}`);
2119
+ return false;
2120
+ }
2121
+ }
2122
+ /**
2123
+ * List every invitation from a guild
2124
+ */
2125
+ static async list(guildId) {
2126
+ try {
2127
+ const guild = Bot.client.guilds.cache.get(guildId);
2128
+ if (!guild) {
2129
+ throw new Error(`Guild ${guildId} not found`);
2130
+ }
2131
+ const invites = await guild.invites.fetch();
2132
+ const inviteList = Array.from(invites.values());
2133
+ Log.info(`Fetched ${inviteList.length} invites for guild ${guildId}`);
2134
+ return inviteList;
2135
+ } catch (error) {
2136
+ Log.error(`Failed to fetch invites for guild ${guildId}: ${error}`);
2137
+ throw error;
2138
+ }
2139
+ }
2140
+ };
2141
+
2142
+ // src/manager/guild/GuildManager.ts
2143
+ var GuildManager = class {
2144
+ static list() {
2145
+ return Array.from(Bot.client.guilds.cache.values());
2146
+ }
2147
+ static async find(guild_id) {
2148
+ return await Bot.client.guilds.fetch(guild_id);
2149
+ }
2150
+ /**
2151
+ * Search channel by ID (TextChannel, DMChannel, ThreadChannel)
2152
+ */
2153
+ static async searchChannel(guildId, channelId) {
2154
+ try {
2155
+ return await GuildChannelManager.findInGuild(guildId, channelId);
2156
+ } catch (error) {
2157
+ Log.error(`Failed to fetch channel ${channelId}: ${error}`);
2158
+ return null;
2159
+ }
2160
+ }
2161
+ /**
2162
+ * Search guild member by ID
2163
+ */
2164
+ static async searchMember(memberId, guildId) {
2165
+ try {
2166
+ return await this.user.findInGuild(guildId, guildId);
2167
+ } catch (error) {
2168
+ Log.error(`Failed to fetch member ${memberId} in guild ${guildId}: ${error}`);
2169
+ return null;
2170
+ }
2171
+ }
2172
+ /**
2173
+ * Check if member is still in guild
2174
+ */
2175
+ static async isMemberInGuild(memberId, guildId) {
2176
+ try {
2177
+ return await this.user.isInGuild(memberId, guildId);
2178
+ } catch (error) {
2179
+ return error.code !== 10007;
2180
+ }
2181
+ }
2182
+ /**
2183
+ * Fetch all members with retry (heavy operation)
2184
+ */
2185
+ static async fetchAllMembers(guildId, MAX_ATTEMPTS = 3, RETRY_DELAY = Time.minute.MIN_05.toMilliseconds()) {
2186
+ let guild;
2187
+ if (guildId instanceof import_discord14.Guild) {
2188
+ guild = guildId;
2189
+ } else {
2190
+ let tmp = Bot.client.guilds.cache.get(guildId);
2191
+ if (!tmp) throw new Error(`Guild ${guildId} not found`);
2192
+ guild = tmp;
2193
+ }
2194
+ for (let attempt = 1; attempt <= MAX_ATTEMPTS; attempt++) {
2195
+ try {
2196
+ Log.info(`UserManager: Fetching ${guild.name} members (attempt ${attempt})`);
2197
+ return await guild.members.fetch();
2198
+ } catch (error) {
2199
+ Log.error(`UserManager: Fetch failed (attempt ${attempt}): ${error}`);
2200
+ if (attempt < MAX_ATTEMPTS) {
2201
+ await new Promise((r) => setTimeout(r, RETRY_DELAY));
2202
+ }
2203
+ }
2204
+ }
2205
+ throw new Error(`Failed to fetch members after ${MAX_ATTEMPTS} attempts`);
2206
+ }
2207
+ static async listban(guildId, limit) {
2208
+ const guild = Bot.client.guilds.cache.get(guildId);
2209
+ if (!guild) {
2210
+ throw new Error(`Guild ${guildId} not found`);
2211
+ }
2212
+ try {
2213
+ const bans = await guild.bans.fetch({ limit });
2214
+ return Array.from(bans.values());
2215
+ } catch (error) {
2216
+ Log.error(`Failed to list bans in guild ${guildId}: ${error}`);
2217
+ throw error;
2218
+ }
2219
+ }
2220
+ static async moveMember(memberId, fromChannelId, toChannelId) {
2221
+ try {
2222
+ const guild = Bot.client.guilds.cache.find(
2223
+ (g) => g.channels.cache.has(fromChannelId) || g.channels.cache.has(toChannelId)
2224
+ );
2225
+ if (!guild) {
2226
+ throw new Error(`Guild containing channels ${fromChannelId} or ${toChannelId} not found`);
2227
+ }
2228
+ const member = await guild.members.fetch(memberId).catch(() => null);
2229
+ if (!member) {
2230
+ throw new Error(`Member ${memberId} not found in guild ${guild.id}`);
2231
+ }
2232
+ const fromChannel = guild.channels.cache.get(fromChannelId);
2233
+ const toChannel = guild.channels.cache.get(toChannelId);
2234
+ if (!fromChannel) {
2235
+ throw new Error(`From channel ${fromChannelId} not found`);
2236
+ }
2237
+ if (!toChannel) {
2238
+ throw new Error(`To channel ${toChannelId} not found`);
2239
+ }
2240
+ if (!(fromChannel instanceof import_discord14.VoiceChannel || fromChannel instanceof import_discord14.StageChannel)) {
2241
+ throw new Error(`From channel ${fromChannelId} is not a voice/stage channel`);
2242
+ }
2243
+ if (!(toChannel instanceof import_discord14.VoiceChannel || toChannel instanceof import_discord14.StageChannel)) {
2244
+ throw new Error(`To channel ${toChannelId} is not a voice/stage channel`);
2245
+ }
2246
+ if (member.voice.channelId !== fromChannelId) {
2247
+ throw new Error(`Member ${memberId} is not in channel ${fromChannelId}`);
2248
+ }
2249
+ try {
2250
+ await member.voice.setChannel(toChannel);
2251
+ Log.info(`Moved member ${memberId} from ${fromChannelId} to ${toChannelId}`);
2252
+ } catch (error) {
2253
+ Log.error(`Failed to move member ${memberId} from ${fromChannelId} to ${toChannelId}: ${error}`);
2254
+ throw error;
2255
+ }
2256
+ return true;
2257
+ } catch (e) {
2258
+ Log.error(`Failed to move member ${e}`);
2259
+ return false;
2260
+ }
2261
+ }
2262
+ };
2263
+ GuildManager.role = RoleManager;
2264
+ GuildManager.user = GuildUserManager;
2265
+ GuildManager.channel = GuildChannelList;
2266
+ GuildManager.invite = InviteManager;
2267
+
2268
+ // src/manager/direct/UserManager.ts
2269
+ var UserManager = class extends BasicUserManager {
2270
+ static async find(userId) {
2271
+ try {
2272
+ return await Bot.client.users.fetch(userId);
2273
+ } catch (error) {
2274
+ Log.error(`UserManager: Member ${userId} not found`);
2275
+ return null;
2276
+ }
2277
+ }
2278
+ };
2279
+
2280
+ // src/manager/interactions/ModalManager.ts
2281
+ var import_discord15 = require("discord.js");
2282
+ var ModalManager = class _ModalManager {
2283
+ /**
2284
+ * Load modal from JSON file and return ModalBuilder
2285
+ */
2286
+ static async load(filename) {
2287
+ try {
2288
+ const file = await FileManager.readJsonFile(`./handlers/${"modals" /* MODAL */}/${filename}`);
2289
+ if (!file) return false;
2290
+ return _ModalManager.jsonToBuilder(file);
2291
+ } catch {
2292
+ return false;
2293
+ }
2294
+ }
2295
+ /**
2296
+ * List all modal files
2297
+ */
2298
+ static async list() {
2299
+ try {
2300
+ const files = await FileManager.listJsonFiles(`./handlers/${"modals" /* MODAL */}`);
2301
+ return files || [];
2302
+ } catch {
2303
+ return false;
2304
+ }
2305
+ }
2306
+ static jsonToBuilder(json) {
2307
+ const modal = new import_discord15.ModalBuilder().setCustomId(json.customId).setTitle(json.title.slice(0, 45));
2308
+ const actionRows = [];
2309
+ for (const fieldJson of json.fields) {
2310
+ const input = this.fieldJsonToInput(fieldJson);
2311
+ const row = new import_discord15.ActionRowBuilder().addComponents(input);
2312
+ actionRows.push(row);
2313
+ }
2314
+ return modal.addComponents(...actionRows);
2315
+ }
2316
+ static fieldJsonToInput(fieldJson) {
2317
+ const input = new import_discord15.TextInputBuilder().setCustomId(fieldJson.customId).setLabel(fieldJson.title.slice(0, 45)).setPlaceholder(fieldJson.placeholder || "Enter value...").setRequired(fieldJson.required !== false).setMinLength(fieldJson.minLength || 0).setMaxLength(fieldJson.maxLength || 400);
2318
+ const style = fieldJson.style;
2319
+ if (typeof style === "number") {
2320
+ input.setStyle(style);
2321
+ } else {
2322
+ switch (style) {
2323
+ case "Number":
2324
+ case "Phone":
2325
+ case "Date":
2326
+ input.setStyle(import_discord15.TextInputStyle.Short);
2327
+ input.setPlaceholder(
2328
+ style === "Number" ? "123" : style === "Phone" ? "+33 6 12 34 56 78" : "2024-02-05"
2329
+ );
2330
+ break;
2331
+ default:
2332
+ input.setStyle(import_discord15.TextInputStyle.Short);
2333
+ }
2334
+ }
2335
+ return input;
2336
+ }
2337
+ static parseNumber(value) {
2338
+ if (!/^\d+$/.test(value)) return null;
2339
+ const num = parseInt(value);
2340
+ return isNaN(num) ? null : num;
2341
+ }
2342
+ static parsePhone(value) {
2343
+ const clean = value.replace(/[\s\-\(\)]/g, "");
2344
+ if (/^(06|07|09)\d{8}$/.test(clean) || /^(\+33|0033)?[6-9]\d{8}$/.test(clean)) {
2345
+ if (clean.startsWith("06") || clean.startsWith("07") || clean.startsWith("09")) {
2346
+ return "+33" + clean.slice(2);
2347
+ }
2348
+ return clean.startsWith("0033") ? "+33" + clean.slice(4) : clean;
2349
+ }
2350
+ return null;
2351
+ }
2352
+ static parseDate(value) {
2353
+ if (/^\d{4}-\d{2}-\d{2}$/.test(value)) {
2354
+ const [year, month, day] = value.split("-").map(Number);
2355
+ const date = new Date(year, month - 1, day);
2356
+ return isNaN(date.getTime()) ? null : date;
2357
+ }
2358
+ if (/^\d{2}\/\d{2}\/\d{4}$/.test(value)) {
2359
+ const [day, month, year] = value.split("/").map(Number);
2360
+ const date = new Date(year, month - 1, day);
2361
+ return isNaN(date.getTime()) ? null : date;
2362
+ }
2363
+ return null;
2364
+ }
2365
+ };
2366
+
2367
+ // src/manager/interactions/SelectMenuManager.ts
2368
+ var import_discord16 = require("discord.js");
2369
+ var SelectMenuManager = class {
2370
+ /**
2371
+ * Creates base StringSelectMenu - SIMPLE API !
2372
+ */
2373
+ static create(customId, placeholder = "Select an option...") {
2374
+ return new import_discord16.StringSelectMenuBuilder().setCustomId(customId).setPlaceholder(placeholder).setMinValues(1).setMaxValues(1);
2375
+ }
2376
+ /**
2377
+ * Quick StringSelectMenu
2378
+ */
2379
+ static simple(customId, options, placeholder = "Choose an option") {
2380
+ const menu = this.create(customId, placeholder);
2381
+ menu.addOptions(
2382
+ options.map((opt) => {
2383
+ return this.option(opt);
2384
+ })
2385
+ );
2386
+ return menu;
2387
+ }
2388
+ /**
2389
+ * Pagination menu
2390
+ */
2391
+ static paginated(customId, options, pageSize = 25) {
2392
+ const row = new import_discord16.ActionRowBuilder();
2393
+ for (let i = 0; i < options.length; i += pageSize) {
2394
+ const pageOptions = options.slice(i, i + pageSize);
2395
+ const menu = new import_discord16.StringSelectMenuBuilder().setCustomId(`${customId}_page_${Math.floor(i / pageSize)}`).setPlaceholder(`Page ${Math.floor(i / pageSize) + 1}`).addOptions(pageOptions.map((opt) => {
2396
+ return this.option(opt);
2397
+ }));
2398
+ row.addComponents(menu);
2399
+ }
2400
+ return row;
2401
+ }
2402
+ /**
2403
+ * User Select Menu (Components V2)
2404
+ */
2405
+ static users(customId, placeholder = "Select users...") {
2406
+ return new import_discord16.UserSelectMenuBuilder().setCustomId(customId).setPlaceholder(placeholder).setMinValues(1).setMaxValues(25);
2407
+ }
2408
+ /**
2409
+ * Role Select Menu (Components V2)
2410
+ */
2411
+ static roles(customId, placeholder = "Select roles...") {
2412
+ return new import_discord16.RoleSelectMenuBuilder().setCustomId(customId).setPlaceholder(placeholder).setMinValues(1).setMaxValues(25);
2413
+ }
2414
+ /**
2415
+ * Mentionable Select Menu (Components V2)
2416
+ */
2417
+ static mentionables(customId, placeholder = "Select users/roles...") {
2418
+ return new import_discord16.MentionableSelectMenuBuilder().setCustomId(customId).setPlaceholder(placeholder).setMinValues(1).setMaxValues(25);
2419
+ }
2420
+ /**
2421
+ * Channel Select Menu (Components V2)
2422
+ */
2423
+ static channels(customId, placeholder = "Select channels...", channelTypes = []) {
2424
+ return new import_discord16.ChannelSelectMenuBuilder().setCustomId(customId).setPlaceholder(placeholder).setMinValues(1).setMaxValues(25).setChannelTypes(...channelTypes);
2425
+ }
2426
+ static option(option) {
2427
+ if (Array.isArray(option)) {
2428
+ return option.map((opt) => this._createOption(opt));
2429
+ }
2430
+ return this._createOption(option);
2431
+ }
2432
+ static _createOption(option) {
2433
+ const builder = new import_discord16.StringSelectMenuOptionBuilder().setLabel(option.label).setValue(option.value);
2434
+ option.description && builder.setDescription(option.description);
2435
+ option.emoji && builder.setEmoji(option.emoji);
2436
+ return builder;
2437
+ }
2438
+ /**
2439
+ * Fluent API pour personnaliser
2440
+ */
2441
+ static placeholder(menu, placeholder) {
2442
+ return menu.setPlaceholder(placeholder);
2443
+ }
2444
+ static minMax(menu, min, max) {
2445
+ return menu.setMinValues(min).setMaxValues(Math.min(max, 25));
2446
+ }
2447
+ static disabled(menu, disabled) {
2448
+ return menu.setDisabled(disabled);
2449
+ }
2450
+ /**
2451
+ * ActionRow
2452
+ */
2453
+ static row(component) {
2454
+ return new import_discord16.ActionRowBuilder().addComponents(component);
2455
+ }
2456
+ /**
2457
+ * Rows multiples (5 max)
2458
+ */
2459
+ static rows(...components) {
2460
+ return components.slice(0, 5).map(
2461
+ (component) => this.row(component)
2462
+ );
2463
+ }
2464
+ };
2465
+
2466
+ // src/utils/SimpleMutex.ts
2467
+ var SimpleMutex = class {
2468
+ // File d'attente des fonctions de résolution
2469
+ constructor() {
2470
+ this._locked = false;
2471
+ this.queue = [];
2472
+ }
2473
+ /**
2474
+ * Verrouille le mutex. Si le mutex est déjà verrouillé, la méthode retourne une promesse qui sera résolue une fois que le mutex sera disponible.
2475
+ * @returns Une promesse résolue lorsque le mutex est verrouillé.
2476
+ */
2477
+ async lock() {
2478
+ if (this._locked) {
2479
+ return new Promise((resolve) => {
2480
+ this.queue.push(resolve);
2481
+ });
2482
+ }
2483
+ this._locked = true;
2484
+ return Promise.resolve();
2485
+ }
2486
+ /**
2487
+ * Déverrouille le mutex. Si une file d'attente existe, débloque le prochain élément dans la file.
2488
+ */
2489
+ unlock() {
2490
+ if (this.queue.length > 0) {
2491
+ const nextResolve = this.queue.shift();
2492
+ if (nextResolve) {
2493
+ nextResolve();
2494
+ }
2495
+ return;
2496
+ }
2497
+ this._locked = false;
2498
+ }
2499
+ get locked() {
2500
+ return this._locked;
2501
+ }
2502
+ };
2503
+
2504
+ // package.json
2505
+ var package_default = {
2506
+ name: "@spatulox/simplediscordbot",
2507
+ version: "1.0.31",
2508
+ author: "Spatulox",
2509
+ description: "Simple discord bot framework to set up a bot under 30 secondes",
2510
+ exports: {
2511
+ types: "./dist/index.d.ts",
2512
+ import: "./dist/index.js",
2513
+ require: "./dist/index.js"
2514
+ },
2515
+ types: "./dist/index.d.ts",
2516
+ scripts: {
2517
+ build: "rm -r dist/ && tsup",
2518
+ patch: "npm run build && npm version patch",
2519
+ pub: "npm run patch && npm publish --access public",
2520
+ "test-pack": "npm run patch && npm publish --access public",
2521
+ dev: "nodemon --exec tsx src/test/index.ts"
2522
+ },
2523
+ license: "MIT",
2524
+ dependencies: {
2525
+ "@spatulox/discord-interaction-manager": "^1.0.8",
2526
+ "discord.js": "^14.25.1"
2527
+ },
2528
+ devDependencies: {
2529
+ "@types/node": "^22.14.0",
2530
+ "@types/node-schedule": "^2.1.7",
2531
+ dotenv: "^17.2.4",
2532
+ nodemon: "^3.1.9",
2533
+ tsup: "^8.5.1",
2534
+ tsx: "^4.20.3",
2535
+ typescript: "^5.9.3"
2536
+ },
2537
+ keywords: [
2538
+ "discord",
2539
+ "framework",
2540
+ "bot",
2541
+ "client",
2542
+ "discordjs",
2543
+ "discord.js",
2544
+ "node"
2545
+ ],
2546
+ bugs: {
2547
+ url: "https://github.com/Spatulox/SimpleDiscordBot/issues"
2548
+ }
2549
+ };
2550
+
2551
+ // src/SimpleDiscordBotInfo.ts
2552
+ var SimpleDiscordBotInfo = {
2553
+ name: package_default.name,
2554
+ version: package_default.license,
2555
+ author: package_default.author,
2556
+ description: package_default.description,
2557
+ license: package_default.license
2558
+ };
2559
+ // Annotate the CommonJS export names for ESM import in node:
2560
+ 0 && (module.exports = {
2561
+ Bot,
2562
+ BotEnv,
2563
+ DiscordRegex,
2564
+ EmbedColor,
2565
+ EmbedManager,
2566
+ FileManager,
2567
+ GuildManager,
2568
+ Log,
2569
+ ModalManager,
2570
+ ReactionManager,
2571
+ SelectMenuManager,
2572
+ SimpleDiscordBotInfo,
2573
+ SimpleMutex,
2574
+ Time,
2575
+ UserManager,
2576
+ WebhookManager
2577
+ });