djs-next 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of djs-next might be problematic. Click here for more details.

package/dist/index.mjs ADDED
@@ -0,0 +1,1259 @@
1
+ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
2
+ get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
3
+ }) : x)(function(x) {
4
+ if (typeof require !== "undefined") return require.apply(this, arguments);
5
+ throw Error('Dynamic require of "' + x + '" is not supported');
6
+ });
7
+
8
+ // src/index.ts
9
+ import "dotenv/config";
10
+
11
+ // src/client.ts
12
+ import { Client, Collection as Collection3 } from "discord.js";
13
+
14
+ // src/handlers/commandHandler.ts
15
+ import { Collection, REST, Routes } from "discord.js";
16
+ import fs2 from "fs";
17
+ import path2 from "path";
18
+ import { pathToFileURL } from "url";
19
+
20
+ // src/handlers/utils.ts
21
+ import fs from "fs";
22
+ import path from "path";
23
+ function getAllFiles(dirPath, arrayOfFiles = []) {
24
+ const files = fs.readdirSync(dirPath);
25
+ files.forEach((file) => {
26
+ const fullPath = path.join(dirPath, file);
27
+ if (fs.statSync(fullPath).isDirectory()) {
28
+ arrayOfFiles = getAllFiles(fullPath, arrayOfFiles);
29
+ } else {
30
+ if (file.endsWith(".js") || file.endsWith(".ts") || file.endsWith(".mjs") || file.endsWith(".cjs")) {
31
+ if (!file.endsWith(".d.ts")) {
32
+ arrayOfFiles.push(fullPath);
33
+ }
34
+ }
35
+ }
36
+ });
37
+ return arrayOfFiles;
38
+ }
39
+
40
+ // src/handlers/commandHandler.ts
41
+ async function loadAndDeployCommands(commandsDir, token, clientId, guildId) {
42
+ const flatCommands = new Collection();
43
+ if (!fs2.existsSync(commandsDir)) {
44
+ console.warn(`[djs-next] Commands directory "${commandsDir}" does not exist.`);
45
+ return flatCommands;
46
+ }
47
+ const commandFiles = getAllFiles(commandsDir);
48
+ const rootNodes = /* @__PURE__ */ new Map();
49
+ function getOrCreateNode(pathParts) {
50
+ let currentMap = rootNodes;
51
+ let currentNode;
52
+ for (const part of pathParts) {
53
+ if (!currentMap.has(part)) {
54
+ currentMap.set(part, {
55
+ name: part,
56
+ description: `${part} command`,
57
+ // Fallback description
58
+ options: [],
59
+ children: /* @__PURE__ */ new Map()
60
+ });
61
+ }
62
+ currentNode = currentMap.get(part);
63
+ currentMap = currentNode.children;
64
+ }
65
+ return currentNode;
66
+ }
67
+ for (const file of commandFiles) {
68
+ const relativePath = path2.relative(commandsDir, file);
69
+ const parsed = path2.parse(relativePath);
70
+ const dirParts = parsed.dir ? parsed.dir.split(path2.sep) : [];
71
+ const name = parsed.name;
72
+ const pathParts = [...dirParts];
73
+ if (name !== "index") {
74
+ pathParts.push(name);
75
+ }
76
+ if (pathParts.length === 0) continue;
77
+ if (pathParts.length > 3) {
78
+ console.warn(`[djs-next] Command path too deep (Discord allows max 3 levels): ${relativePath}`);
79
+ continue;
80
+ }
81
+ const module = await import(pathToFileURL(file).href);
82
+ const commandData = module.default || module.command || module;
83
+ if (commandData) commandData.filepath = file;
84
+ const node = getOrCreateNode(pathParts);
85
+ if (commandData.description) node.description = commandData.description;
86
+ if (commandData.options) node.options = commandData.options;
87
+ if (commandData.execute) {
88
+ node.execute = commandData.execute;
89
+ flatCommands.set(pathParts.join(" "), commandData);
90
+ }
91
+ }
92
+ function buildCommandJSON(node, depth) {
93
+ const json = {
94
+ name: node.name,
95
+ description: node.description
96
+ };
97
+ if (node.children.size > 0) {
98
+ json.options = [];
99
+ for (const [_, childNode] of node.children) {
100
+ const childJson = buildCommandJSON(childNode, depth + 1);
101
+ if (depth === 0) {
102
+ childJson.type = childNode.children.size > 0 ? 2 : 1;
103
+ } else if (depth === 1) {
104
+ childJson.type = 1;
105
+ }
106
+ json.options.push(childJson);
107
+ }
108
+ } else if (node.options && node.options.length > 0) {
109
+ json.options = node.options;
110
+ }
111
+ return json;
112
+ }
113
+ const commandsData = Array.from(rootNodes.values()).map((node) => buildCommandJSON(node, 0));
114
+ const rest = new REST({ version: "10" }).setToken(token);
115
+ try {
116
+ console.log(`[djs-next] Started refreshing ${commandsData.length} File-System application (/) commands.`);
117
+ let data;
118
+ if (guildId) {
119
+ data = await rest.put(
120
+ Routes.applicationGuildCommands(clientId, guildId),
121
+ { body: commandsData }
122
+ );
123
+ } else {
124
+ data = await rest.put(
125
+ Routes.applicationCommands(clientId),
126
+ { body: commandsData }
127
+ );
128
+ }
129
+ console.log(`[djs-next] Successfully reloaded ${data.length} File-System application (/) commands.`);
130
+ } catch (error) {
131
+ console.error(`[djs-next] Failed to deploy commands:`, error);
132
+ }
133
+ return flatCommands;
134
+ }
135
+
136
+ // src/handlers/eventHandler.ts
137
+ import fs3 from "fs";
138
+ import { pathToFileURL as pathToFileURL2 } from "url";
139
+ async function loadEvents(client2, eventsDir) {
140
+ if (!fs3.existsSync(eventsDir)) {
141
+ console.warn(`[djs-next] Events directory "${eventsDir}" does not exist.`);
142
+ return;
143
+ }
144
+ const eventFiles = getAllFiles(eventsDir);
145
+ let loadedEvents = 0;
146
+ for (const file of eventFiles) {
147
+ const eventModule = await import(pathToFileURL2(file).href);
148
+ const eventData = eventModule.default?.event || eventModule.event || eventModule.default || eventModule;
149
+ if (eventData) eventData.filepath = file;
150
+ if (!eventData || !eventData.name || !eventData.execute) {
151
+ console.warn(`[djs-next] The event at ${file} is missing a required "name" or "execute" property.`);
152
+ continue;
153
+ }
154
+ if (eventData.once) {
155
+ client2.once(eventData.name, (...args2) => eventData.execute(client2, ...args2));
156
+ } else {
157
+ client2.on(eventData.name, (...args2) => eventData.execute(client2, ...args2));
158
+ }
159
+ loadedEvents++;
160
+ }
161
+ if (loadedEvents > 0) {
162
+ console.log(`[djs-next] Successfully loaded ${loadedEvents} events.`);
163
+ }
164
+ }
165
+
166
+ // src/handlers/componentHandler.ts
167
+ import { Collection as Collection2 } from "discord.js";
168
+ import fs4 from "fs";
169
+ import path3 from "path";
170
+ import { pathToFileURL as pathToFileURL3 } from "url";
171
+ async function loadComponents(componentsDir) {
172
+ const components2 = new Collection2();
173
+ if (!fs4.existsSync(componentsDir)) return components2;
174
+ const files = getAllFiles(componentsDir);
175
+ for (const file of files) {
176
+ const module = await import(pathToFileURL3(file).href);
177
+ const componentData = module.default || module.component || module;
178
+ if (componentData) componentData.filepath = file;
179
+ if (!componentData || !componentData.execute) continue;
180
+ const parsed = path3.parse(file);
181
+ const customId = componentData.customId || parsed.name;
182
+ components2.set(customId, componentData);
183
+ }
184
+ console.log(`[djs-next] Successfully loaded ${components2.size} components.`);
185
+ return components2;
186
+ }
187
+
188
+ // src/handlers/taskHandler.ts
189
+ import fs5 from "fs";
190
+ import { pathToFileURL as pathToFileURL4 } from "url";
191
+ async function loadTasks(client2, tasksDir) {
192
+ if (!fs5.existsSync(tasksDir)) return;
193
+ const files = getAllFiles(tasksDir);
194
+ let loaded = 0;
195
+ for (const file of files) {
196
+ const module = await import(pathToFileURL4(file).href);
197
+ const taskData = module.default || module.task || module;
198
+ if (taskData) taskData.filepath = file;
199
+ if (!taskData || !taskData.interval || !taskData.execute) continue;
200
+ const intervalId = setInterval(async () => {
201
+ try {
202
+ await taskData.execute(client2);
203
+ } catch (error) {
204
+ console.error(`[djs-next] Background Task error at ${file}:`, error);
205
+ }
206
+ }, taskData.interval);
207
+ if (!client2._activeTasks) client2._activeTasks = /* @__PURE__ */ new Map();
208
+ client2._activeTasks.set(file, intervalId);
209
+ loaded++;
210
+ }
211
+ if (loaded > 0) {
212
+ console.log(`[djs-next] Successfully scheduled ${loaded} background tasks.`);
213
+ }
214
+ }
215
+
216
+ // src/client.ts
217
+ import path6 from "path";
218
+ import fs8 from "fs";
219
+ import { pathToFileURL as pathToFileURL6 } from "url";
220
+
221
+ // src/utils/configLoader.ts
222
+ import path4 from "path";
223
+ import fs6 from "fs";
224
+ import { pathToFileURL as pathToFileURL5 } from "url";
225
+ async function loadConfig() {
226
+ const exts = [".js", ".mjs", ".cjs", ".ts", ".mts", ".cts"];
227
+ const cwd = process.cwd();
228
+ for (const ext of exts) {
229
+ const configPath = path4.join(cwd, `djs-next.config${ext}`);
230
+ if (fs6.existsSync(configPath)) {
231
+ try {
232
+ const configModule = await import(pathToFileURL5(configPath).href);
233
+ return configModule.default || configModule;
234
+ } catch (err) {
235
+ console.error(`[djs-next] Error loading config file ${configPath}:`, err);
236
+ return {};
237
+ }
238
+ }
239
+ }
240
+ return {};
241
+ }
242
+ function defineConfig(config2) {
243
+ return config2;
244
+ }
245
+
246
+ // src/utils/i18n.ts
247
+ import fs7 from "fs";
248
+ import path5 from "path";
249
+ var localesCache = {};
250
+ var defaultLoc = "en";
251
+ function loadLocales(localesDir, defaultLocale) {
252
+ if (defaultLocale) defaultLoc = defaultLocale;
253
+ if (!fs7.existsSync(localesDir)) return;
254
+ const files = fs7.readdirSync(localesDir);
255
+ for (const file of files) {
256
+ if (file.endsWith(".json")) {
257
+ const lang = file.replace(".json", "");
258
+ const content2 = fs7.readFileSync(path5.join(localesDir, file), "utf8");
259
+ try {
260
+ localesCache[lang] = JSON.parse(content2);
261
+ } catch (e) {
262
+ console.error(`[djs-next] Failed to parse locale file: ${file}`, e);
263
+ }
264
+ }
265
+ }
266
+ }
267
+ function translate(key, locale = defaultLoc, variables) {
268
+ const dict = localesCache[locale] || localesCache[defaultLoc] || {};
269
+ const keys = key.split(".");
270
+ let value = dict;
271
+ for (const k of keys) {
272
+ if (value && typeof value === "object") {
273
+ value = value[k];
274
+ } else {
275
+ value = void 0;
276
+ break;
277
+ }
278
+ }
279
+ if (typeof value !== "string") {
280
+ return key;
281
+ }
282
+ if (variables) {
283
+ for (const [varKey, varValue] of Object.entries(variables)) {
284
+ value = value.replace(new RegExp(`{{s*${varKey}s*}}`, "g"), String(varValue));
285
+ }
286
+ }
287
+ return value;
288
+ }
289
+ function getLocalesCache() {
290
+ return localesCache;
291
+ }
292
+
293
+ // src/plugins/dnxt.ts
294
+ import { version as djsVersion } from "discord.js";
295
+ import { exec } from "child_process";
296
+ import util from "util";
297
+ import os from "os";
298
+ var execAsync = util.promisify(exec);
299
+ function buildDisplayMessage(content2, color = 5397233) {
300
+ const djs = __require("discord.js");
301
+ const container = new djs.ContainerBuilder().setAccentColor(color).addTextDisplayComponents(
302
+ new djs.TextDisplayBuilder().setContent(content2)
303
+ );
304
+ return { components: [container], flags: 32768 };
305
+ }
306
+ async function handleDNXT(message, client, devPrefix) {
307
+ if (message.author.bot) return;
308
+ if (!client._developers.includes(message.author.id)) return;
309
+ if (client.config?.devGuildId && message.guildId !== client.config.devGuildId) return;
310
+ const originalReply = message.reply.bind(message);
311
+ message.reply = (async (content2) => {
312
+ if (typeof content2 === "string") {
313
+ return await originalReply({ ...buildDisplayMessage(content2), allowedMentions: { repliedUser: false } });
314
+ }
315
+ if (!content2.allowedMentions) content2.allowedMentions = { repliedUser: false };
316
+ return await originalReply(content2);
317
+ });
318
+ const content = message.content.trim();
319
+ const validTriggers = [devPrefix];
320
+ const clientPrefixes = client._prefixes || [];
321
+ for (const p of clientPrefixes) {
322
+ if (p !== "") validTriggers.push(`${p}${devPrefix}`);
323
+ }
324
+ let matchedTrigger = validTriggers.find((t) => content === t || content.startsWith(`${t} `));
325
+ if (!matchedTrigger) return;
326
+ const args = content.slice(matchedTrigger.length).trim().split(/ +/g);
327
+ const command = args.shift()?.toLowerCase();
328
+ if (command === "help") {
329
+ const djs = __require("discord.js");
330
+ const container = new djs.ContainerBuilder().setAccentColor(5397233).addTextDisplayComponents(
331
+ new djs.TextDisplayBuilder().setContent(`# \u{1F4D6} DNXT Toolkit Reference
332
+ > Current prefix trigger: \`${matchedTrigger}\``)
333
+ ).addSeparatorComponents(new djs.SeparatorBuilder()).addTextDisplayComponents(
334
+ new djs.TextDisplayBuilder().setContent(`### \u{1F4CA} Core Framework
335
+ - \`${matchedTrigger}\` \u2014 Developer system dashboard
336
+ - \`${matchedTrigger} help\` \u2014 Shows this reference menu`),
337
+ new djs.TextDisplayBuilder().setContent(`### \u{1F4BB} Execution & Diagnostics
338
+ - \`${matchedTrigger} js <code>\` \u2014 Evaluates raw JS code
339
+ - \`${matchedTrigger} sh <cmd>\` \u2014 Runs terminal shell script
340
+ - \`${matchedTrigger} debug <code>\` \u2014 Evaluates JS with precise memory deltas`),
341
+ new djs.TextDisplayBuilder().setContent(`### \u{1F4C2} File System & Network
342
+ - \`${matchedTrigger} cat <file>\` \u2014 Reads file contents
343
+ - \`${matchedTrigger} curl <url>\` \u2014 Fetches remote URL data
344
+ - \`${matchedTrigger} git <cmd>\` \u2014 Executes git repository commands`),
345
+ new djs.TextDisplayBuilder().setContent(`### \u{1F9F0} Utilities
346
+ - \`${matchedTrigger} <load|unload|reload> <target>\` \u2014 Manages system modules
347
+ - \`${matchedTrigger} sync\` \u2014 Forces global slash command sync
348
+ - \`${matchedTrigger} in <channel> <cmd>\` \u2014 Executes command in target channel
349
+ - \`${matchedTrigger} restart\` \u2014 Restarts the bot completely
350
+ - \`${matchedTrigger} shutdown\` \u2014 Stops the bot completely`)
351
+ );
352
+ await message.reply({ components: [container], flags: 32768, allowedMentions: { repliedUser: false } });
353
+ return;
354
+ }
355
+ if (!command) {
356
+ const mem = process.memoryUsage();
357
+ const botPing = client.ws.ping;
358
+ const djs = __require("discord.js");
359
+ const container = new djs.ContainerBuilder().setAccentColor(5397233).addTextDisplayComponents(
360
+ new djs.TextDisplayBuilder().setContent(`# \u{1F6E0}\uFE0F Developer System Dashboard
361
+ > **DNXT Framework Engine**`)
362
+ ).addSeparatorComponents(new djs.SeparatorBuilder()).addTextDisplayComponents(
363
+ new djs.TextDisplayBuilder().setContent(`### \u{1F4E1} Network Status
364
+ - **System Uptime:** <t:${Math.floor((Date.now() - client.uptime) / 1e3)}:R>
365
+ - **WebSocket Latency:** \`${botPing}ms\``),
366
+ new djs.TextDisplayBuilder().setContent(`### \u{1F4E6} Host Environment
367
+ - **Discord.js Library:** \`v${djsVersion}\`
368
+ - **Node.js Runtime:** \`${process.version}\`
369
+ - **Operating System:** \`${os.type()}\` (\`${os.cpus().length}\` thread cores, \`${(os.uptime() / 60 / 60).toFixed(2)}\` hrs uptime)`),
370
+ new djs.TextDisplayBuilder().setContent(`### \u{1F9E0} Resource Utilization
371
+ - **Physical Memory:** \`${(mem.rss / 1024 / 1024).toFixed(2)} MB\`
372
+ - **Heap Allocated:** \`${(mem.heapUsed / 1024 / 1024).toFixed(2)} MB\``)
373
+ );
374
+ await message.reply({
375
+ components: [container],
376
+ flags: 32768,
377
+ // MessageFlags.IsComponentsV2
378
+ allowedMentions: { repliedUser: false }
379
+ });
380
+ return;
381
+ }
382
+ if (command === "js" || command === "eval" || command === "py") {
383
+ let code = args.join(" ");
384
+ if (code.startsWith("```js") || code.startsWith("```py")) code = code.replace(/^```[a-z]*|```$/g, "");
385
+ else if (code.startsWith("```")) code = code.replace(/^```|```$/g, "");
386
+ if (!code) return void await message.reply("\u274C Please provide code to evaluate.");
387
+ try {
388
+ const start = process.hrtime.bigint();
389
+ const { commands, components, config } = client;
390
+ let evaled = await eval(`(async () => { ${code} })()`);
391
+ const end = process.hrtime.bigint();
392
+ const timeMs = Number(end - start) / 1e6;
393
+ if (typeof evaled !== "string") evaled = util.inspect(evaled, { depth: 1, colors: true });
394
+ await sendPaginatedText(message, `\u2705 **Evaluated in ${timeMs.toFixed(3)}ms**
395
+ `, evaled, "ansi");
396
+ } catch (err) {
397
+ await sendPaginatedText(message, `\u274C **Evaluation Error**
398
+ `, err.message, "ansi");
399
+ }
400
+ return;
401
+ }
402
+ if (command === "sh" || command === "shell" || command === "git") {
403
+ const cmd = command === "git" ? "git " + args.join(" ") : args.join(" ");
404
+ if (!cmd) return void await message.reply("\u274C Please provide a command to execute.");
405
+ try {
406
+ const start2 = process.hrtime.bigint();
407
+ let stdout = "", stderr = "", code2 = 0;
408
+ try {
409
+ const result = await execAsync(cmd);
410
+ stdout = result.stdout;
411
+ stderr = result.stderr;
412
+ } catch (err) {
413
+ stdout = err.stdout || "";
414
+ stderr = err.stderr || err.message || "";
415
+ code2 = err.code || 1;
416
+ }
417
+ const end2 = process.hrtime.bigint();
418
+ const timeMs2 = Number(end2 - start2) / 1e6;
419
+ let resultText = `$ ${cmd}
420
+ `;
421
+ if (stdout) resultText += `${stdout}
422
+ `;
423
+ if (stderr) resultText += `${stderr}
424
+ `;
425
+ resultText += `
426
+ [status] Return code ${code2}`;
427
+ await sendPaginatedText(message, `\u2705 **Executed in ${timeMs2.toFixed(3)}ms**
428
+ `, resultText, "ansi");
429
+ } catch (err) {
430
+ await sendPaginatedText(message, `\u274C **Shell Error**
431
+ `, err.message, "ansi");
432
+ }
433
+ return;
434
+ }
435
+ if (command === "load" || command === "unload" || command === "reload") {
436
+ const target = args[0]?.toLowerCase();
437
+ try {
438
+ if (target === "commands" && client["_commandsDir"]) {
439
+ if (command === "unload" || command === "reload") client.commands.clear();
440
+ if (command === "load" || command === "reload") client.commands = await loadAndDeployCommands(client["_commandsDir"], client.token, client["_clientId"], client["_guildId"]);
441
+ await message.reply(`\u2705 Successfully ${command}ed commands.`);
442
+ } else if (target === "events" && client["_eventsDir"]) {
443
+ if (command === "unload" || command === "reload") {
444
+ client.removeAllListeners();
445
+ client["attachCoreListeners"]();
446
+ }
447
+ if (command === "load" || command === "reload") await loadEvents(client, client["_eventsDir"]);
448
+ await message.reply(`\u2705 Successfully ${command}ed events.`);
449
+ } else if (target === "components" && client["_componentsDir"]) {
450
+ if (command === "unload" || command === "reload") client.components.clear();
451
+ if (command === "load" || command === "reload") client.components = await loadComponents(client["_componentsDir"]);
452
+ await message.reply(`\u2705 Successfully ${command}ed components.`);
453
+ } else if (target === "locales" && client["_localesDir"]) {
454
+ if (command === "load" || command === "reload") loadLocales(client["_localesDir"], client.config.defaultLocale);
455
+ await message.reply(`\u2705 Successfully ${command}ed locales.`);
456
+ } else if (target === "all" || !target) {
457
+ if (command === "unload" || command === "reload") {
458
+ client.removeAllListeners();
459
+ client["attachCoreListeners"]();
460
+ client.commands.clear();
461
+ client.components.clear();
462
+ }
463
+ if (command === "load" || command === "reload") {
464
+ if (client["_eventsDir"]) await loadEvents(client, client["_eventsDir"]);
465
+ if (client["_componentsDir"]) client.components = await loadComponents(client["_componentsDir"]);
466
+ if (client["_localesDir"]) loadLocales(client["_localesDir"], client.config.defaultLocale);
467
+ if (client["_commandsDir"]) client.commands = await loadAndDeployCommands(client["_commandsDir"], client.token, client["_clientId"], client["_guildId"]);
468
+ }
469
+ await message.reply(`\u2705 Successfully ${command}ed all framework modules.`);
470
+ } else {
471
+ await message.reply("\u274C Unknown target. Valid targets: `commands, events, components, locales, all`");
472
+ }
473
+ } catch (err) {
474
+ await message.reply(`\u274C **${command.toUpperCase()} Error:** ${err.message}`);
475
+ }
476
+ return;
477
+ }
478
+ if (command === "cat") {
479
+ const fs9 = await import("fs");
480
+ const path7 = await import("path");
481
+ const file = args.join(" ");
482
+ if (!file) return void await message.reply("\u274C Please provide a file to read.");
483
+ try {
484
+ const content2 = fs9.readFileSync(path7.resolve(process.cwd(), file), "utf8");
485
+ await sendPaginatedText(message, `\u{1F4C4} **${file}**
486
+ `, content2, file.split(".").pop() || "");
487
+ } catch (e) {
488
+ await message.reply(`\u274C **Error reading file:** ${e.message}`);
489
+ }
490
+ return;
491
+ }
492
+ if (command === "curl") {
493
+ const url = args[0];
494
+ if (!url) return void await message.reply("\u274C Please provide a URL.");
495
+ try {
496
+ const res = await fetch(url);
497
+ const text = await res.text();
498
+ await sendPaginatedText(message, `\u{1F310} **Fetched from \`${url}\`**
499
+ `, text, "html");
500
+ } catch (e) {
501
+ await message.reply(`\u274C **Curl Error:** ${e.message}`);
502
+ }
503
+ return;
504
+ }
505
+ if (command === "debug") {
506
+ let code = args.join(" ");
507
+ if (code.startsWith("```js") || code.startsWith("```py")) code = code.replace(/^```[a-z]*|```$/g, "");
508
+ else if (code.startsWith("```")) code = code.replace(/^```|```$/g, "");
509
+ if (!code) return void await message.reply("\u274C Please provide code to debug.");
510
+ try {
511
+ const startMem = process.memoryUsage().heapUsed;
512
+ const start = process.hrtime.bigint();
513
+ const { commands, components, config } = client;
514
+ let evaled = await eval(`(async () => { ${code} })()`);
515
+ const end = process.hrtime.bigint();
516
+ const endMem = process.memoryUsage().heapUsed;
517
+ const timeMs = Number(end - start) / 1e6;
518
+ const memDiff = (endMem - startMem) / 1024 / 1024;
519
+ if (typeof evaled !== "string") evaled = util.inspect(evaled, { depth: 1, colors: true });
520
+ await sendPaginatedText(message, `\u23F1\uFE0F **Debug Execution**
521
+ Time: \`${timeMs.toFixed(3)}ms\` | Heap Delta: \`${memDiff.toFixed(3)}MB\`
522
+ `, evaled, "ansi");
523
+ } catch (err) {
524
+ await sendPaginatedText(message, `\u274C **Debug Error**
525
+ `, err.message, "ansi");
526
+ }
527
+ return;
528
+ }
529
+ if (command === "in") {
530
+ const channelId = args.shift()?.replace(/<#|>/g, "");
531
+ const cmd = args.join(" ");
532
+ if (!channelId || !cmd) return void await message.reply(`\u274C Usage: ${matchedTrigger} in <#channel|id> <command>`);
533
+ try {
534
+ const targetChannel = await client.channels.fetch(channelId);
535
+ if (!targetChannel || !targetChannel.isTextBased()) throw new Error("Invalid Text Channel.");
536
+ const mockMessage = Object.assign(Object.create(Object.getPrototypeOf(message)), message);
537
+ Object.defineProperty(mockMessage, "client", { value: client, configurable: true });
538
+ if (message.guild) {
539
+ Object.defineProperty(mockMessage, "guild", { value: message.guild, configurable: true });
540
+ Object.defineProperty(mockMessage, "guildId", { value: message.guildId, configurable: true });
541
+ }
542
+ Object.defineProperty(mockMessage, "channel", { value: targetChannel, configurable: true });
543
+ Object.defineProperty(mockMessage, "channelId", { value: targetChannel.id, configurable: true });
544
+ Object.defineProperty(mockMessage, "content", { value: cmd, configurable: true });
545
+ client.emit("messageCreate", mockMessage);
546
+ } catch (e) {
547
+ await message.reply(`\u274C **In Error:** ${e.message}`);
548
+ }
549
+ return;
550
+ }
551
+ if (command === "sync") {
552
+ try {
553
+ await message.reply("\u{1F504} Force syncing slash commands...");
554
+ await loadAndDeployCommands(client._commandsDir, client.token, client._clientId, client._guildId);
555
+ await message.reply("\u2705 Slash commands synchronized globally/locally.");
556
+ } catch (e) {
557
+ await message.reply(`\u274C **Sync Error:** ${e.message}`);
558
+ }
559
+ return;
560
+ }
561
+ if (command === "restart") {
562
+ await message.reply("\u{1F504} Restarting framework...");
563
+ client.destroy();
564
+ const { spawn } = __require("child_process");
565
+ const child = spawn(process.argv[0], process.argv.slice(1), {
566
+ detached: true,
567
+ stdio: "ignore",
568
+ cwd: process.cwd()
569
+ });
570
+ child.unref();
571
+ process.exit(0);
572
+ return;
573
+ }
574
+ if (command === "shutdown" || command === "stop") {
575
+ await message.reply("\u{1F6D1} Shutting down framework...");
576
+ client.destroy();
577
+ process.exit(0);
578
+ return;
579
+ }
580
+ await message.reply(`\u2753 Unknown ${matchedTrigger} command. Available: \`js, sh, git, cat, curl, in, debug, reload, sync, restart, shutdown\``);
581
+ }
582
+ async function sendPaginatedText(message2, header, content2, language = "") {
583
+ const maxLength = 800;
584
+ if (content2.length <= maxLength) {
585
+ await message2.reply(buildDisplayMessage(`### ${header.replace(/\\*\\*/g, "")}
586
+ \`\`\`${language}
587
+ ${content2}
588
+ \`\`\``));
589
+ return;
590
+ }
591
+ const chunks = [];
592
+ for (let i = 0; i < content2.length; i += maxLength) {
593
+ chunks.push(content2.substring(i, i + maxLength));
594
+ }
595
+ let index = 0;
596
+ const djs = __require("discord.js");
597
+ function buildPage(idx) {
598
+ const text = `### ${header.replace(/\\*\\*/g, "")}
599
+ \`\`\`${language}
600
+ ${chunks[idx]}
601
+ \`\`\`
602
+ > *Page ${idx + 1} of ${chunks.length}*`;
603
+ const container = new djs.ContainerBuilder().setAccentColor(5397233).addTextDisplayComponents(
604
+ new djs.TextDisplayBuilder().setContent(text)
605
+ );
606
+ const row1 = new djs.ActionRowBuilder().addComponents(
607
+ new djs.ButtonBuilder().setCustomId("first").setLabel("\u226A").setStyle(2),
608
+ new djs.ButtonBuilder().setCustomId("prev").setLabel("\uFF1C").setStyle(2),
609
+ new djs.ButtonBuilder().setCustomId("goto").setLabel("\u2398").setStyle(1),
610
+ new djs.ButtonBuilder().setCustomId("next").setLabel("\uFF1E").setStyle(2),
611
+ new djs.ButtonBuilder().setCustomId("last").setLabel("\u226B").setStyle(2)
612
+ );
613
+ const row2 = new djs.ActionRowBuilder().addComponents(
614
+ new djs.ButtonBuilder().setCustomId("stop").setLabel("\u2716 Close").setStyle(4)
615
+ );
616
+ container.addActionRowComponents(row1, row2);
617
+ return { components: [container], flags: 32768 };
618
+ }
619
+ const reply = await message2.reply(buildPage(index));
620
+ const collector = reply.createMessageComponentCollector({
621
+ filter: (i) => ["first", "prev", "goto", "stop", "next", "last"].includes(i.customId) && i.user.id === message2.author.id,
622
+ time: 12e4
623
+ });
624
+ collector.on("collect", async (i) => {
625
+ if (i.customId === "first") {
626
+ index = 0;
627
+ } else if (i.customId === "prev") {
628
+ index = index > 0 ? index - 1 : index;
629
+ } else if (i.customId === "next") {
630
+ index = index < chunks.length - 1 ? index + 1 : index;
631
+ } else if (i.customId === "last") {
632
+ index = chunks.length - 1;
633
+ } else if (i.customId === "goto") {
634
+ const modal = new djs.ModalBuilder().setCustomId("goto_modal").setTitle("Go to Page");
635
+ const input = new djs.TextInputBuilder().setCustomId("page_num").setLabel(`Page Number (1-${chunks.length})`).setStyle(1).setRequired(true);
636
+ modal.addComponents(new djs.ActionRowBuilder().addComponents(input));
637
+ await i.showModal(modal);
638
+ try {
639
+ const modalSubmit = await i.awaitModalSubmit({ filter: (mi) => mi.user.id === message2.author.id && mi.customId === "goto_modal", time: 6e4 });
640
+ const targetPage = parseInt(modalSubmit.fields.getTextInputValue("page_num"), 10);
641
+ if (!isNaN(targetPage) && targetPage >= 1 && targetPage <= chunks.length) {
642
+ index = targetPage - 1;
643
+ }
644
+ await modalSubmit.update(buildPage(index));
645
+ } catch {
646
+ }
647
+ return;
648
+ } else if (i.customId === "stop") {
649
+ await reply.delete().catch(() => null);
650
+ collector.stop();
651
+ return;
652
+ }
653
+ await i.update(buildPage(index));
654
+ });
655
+ collector.on("end", () => {
656
+ reply.edit({ components: [] }).catch(() => null);
657
+ });
658
+ }
659
+
660
+ // src/client.ts
661
+ var DJSNextClient = class extends Client {
662
+ commands;
663
+ components;
664
+ cooldowns;
665
+ config = {};
666
+ t = translate;
667
+ db;
668
+ _commandsDir;
669
+ _eventsDir;
670
+ _componentsDir;
671
+ _tasksDir;
672
+ _localesDir;
673
+ _clientId;
674
+ _guildId;
675
+ _developers;
676
+ _middleware;
677
+ _prefixes;
678
+ _enableSlashCommands;
679
+ _enableTextCommands;
680
+ _enableMentionPrefix;
681
+ _enableNoPrefix;
682
+ constructor(options) {
683
+ super(options);
684
+ this.commands = new Collection3();
685
+ this.components = new Collection3();
686
+ this.cooldowns = new Collection3();
687
+ this._commandsDir = options.commandsDir ? path6.resolve(process.cwd(), options.commandsDir) : void 0;
688
+ this._eventsDir = options.eventsDir ? path6.resolve(process.cwd(), options.eventsDir) : void 0;
689
+ this._componentsDir = options.componentsDir ? path6.resolve(process.cwd(), options.componentsDir) : void 0;
690
+ this._tasksDir = options.tasksDir ? path6.resolve(process.cwd(), options.tasksDir) : void 0;
691
+ this._clientId = options.clientId;
692
+ this._guildId = options.guildId;
693
+ this._developers = options.developers || [];
694
+ this._middleware = options.middleware;
695
+ const prefs = options.prefixes || [];
696
+ this._prefixes = Array.isArray(prefs) ? prefs : [prefs];
697
+ this._prefixes = this._prefixes.filter((p) => p !== "");
698
+ this._enableSlashCommands = options.enableSlashCommands ?? true;
699
+ this._enableTextCommands = options.enableTextCommands ?? true;
700
+ this._enableMentionPrefix = options.enableMentionPrefix ?? true;
701
+ this._enableNoPrefix = options.enableNoPrefix ?? false;
702
+ if (options.db) this.db = options.db;
703
+ this.attachCoreListeners();
704
+ }
705
+ attachCoreListeners() {
706
+ this.on("interactionCreate", async (interaction) => {
707
+ if (this._middleware) {
708
+ try {
709
+ const shouldContinue = await this._middleware(interaction, this);
710
+ if (!shouldContinue) return;
711
+ } catch (error) {
712
+ console.error(`[djs-next] Middleware error:`, error);
713
+ return;
714
+ }
715
+ }
716
+ if (interaction.isChatInputCommand()) {
717
+ if (!this._enableSlashCommands) return;
718
+ let commandKey = interaction.commandName;
719
+ const group = interaction.options.getSubcommandGroup(false);
720
+ const sub = interaction.options.getSubcommand(false);
721
+ if (group) commandKey += ` ${group}`;
722
+ if (sub) commandKey += ` ${sub}`;
723
+ const command2 = this.commands.get(commandKey);
724
+ if (!command2 || !command2.execute) return;
725
+ if (!await this.handlePreconditions(command2, interaction, commandKey)) return;
726
+ try {
727
+ await command2.execute(interaction, this);
728
+ } catch (error) {
729
+ await this.handleCommandError(error, commandKey, interaction);
730
+ }
731
+ }
732
+ if (interaction.isAutocomplete()) {
733
+ let commandKey = interaction.commandName;
734
+ const group = interaction.options.getSubcommandGroup(false);
735
+ const sub = interaction.options.getSubcommand(false);
736
+ if (group) commandKey += ` ${group}`;
737
+ if (sub) commandKey += ` ${sub}`;
738
+ const command2 = this.commands.get(commandKey);
739
+ if (command2 && command2.autocomplete) {
740
+ try {
741
+ await command2.autocomplete(interaction, this);
742
+ } catch (error) {
743
+ console.error(`[djs-next] Error executing autocomplete for: "${commandKey}"`, error);
744
+ }
745
+ }
746
+ }
747
+ if (interaction.isMessageComponent() || interaction.isModalSubmit()) {
748
+ if (interaction.customId === "djs_prev" || interaction.customId === "djs_next") return;
749
+ let component = this.components.get(interaction.customId);
750
+ let params = {};
751
+ if (!component) {
752
+ for (const [key, comp] of this.components) {
753
+ if (!key.includes("[")) continue;
754
+ const escapedKey = key.replace(/[.*+?^${}()|\\-]/g, "\\$&");
755
+ const regexStr = "^" + escapedKey.replace(/\\\[([^\]]+)\\\]/g, "(?<$1>.+)") + "$";
756
+ const match = interaction.customId.match(new RegExp(regexStr));
757
+ if (match) {
758
+ component = comp;
759
+ if (match.groups) params = match.groups;
760
+ break;
761
+ }
762
+ }
763
+ }
764
+ if (component) {
765
+ if (!await this.handlePreconditions(component, interaction, interaction.customId)) return;
766
+ try {
767
+ await component.execute(interaction, this, params);
768
+ } catch (error) {
769
+ await this.handleCommandError(error, interaction.customId, interaction);
770
+ }
771
+ }
772
+ }
773
+ });
774
+ this.on("messageCreate", async (message2) => {
775
+ if (message2.author.bot) return;
776
+ if (!this._enableTextCommands) return;
777
+ if (this._middleware) {
778
+ try {
779
+ const shouldContinue = await this._middleware(message2, this);
780
+ if (!shouldContinue) return;
781
+ } catch (error) {
782
+ console.error(`[djs-next] Middleware error (Message):`, error);
783
+ return;
784
+ }
785
+ }
786
+ let content2 = message2.content.trim();
787
+ let matchedPrefix = "";
788
+ let isCommand = false;
789
+ const mentionRegex = new RegExp(`^<@!?${this.user?.id}>\\s*`);
790
+ const canUseMention = this._enableMentionPrefix === true || Array.isArray(this._enableMentionPrefix) && this._enableMentionPrefix.includes(message2.author.id);
791
+ if (canUseMention && mentionRegex.test(content2)) {
792
+ matchedPrefix = content2.match(mentionRegex)[0];
793
+ isCommand = true;
794
+ } else {
795
+ const sortedPrefs = [...this._prefixes].sort((a, b) => b.length - a.length);
796
+ for (const p of sortedPrefs) {
797
+ if (content2.startsWith(p)) {
798
+ matchedPrefix = p;
799
+ isCommand = true;
800
+ break;
801
+ }
802
+ }
803
+ const canUseNoPrefix = this._enableNoPrefix === true || Array.isArray(this._enableNoPrefix) && this._enableNoPrefix.includes(message2.author.id);
804
+ if (!isCommand && canUseNoPrefix) {
805
+ isCommand = true;
806
+ matchedPrefix = "";
807
+ }
808
+ }
809
+ if (!isCommand) return;
810
+ const args2 = content2.slice(matchedPrefix.length).trim().split(/ +/g);
811
+ const commandName = args2.shift()?.toLowerCase();
812
+ if (!commandName) return;
813
+ let command2 = this.commands.get(commandName);
814
+ if (!command2) {
815
+ command2 = this.commands.find((c) => c.aliases?.includes(commandName) || false);
816
+ }
817
+ if (!command2 || !command2.executeText) return;
818
+ if (!await this.handlePreconditions(command2, message2, commandName)) return;
819
+ try {
820
+ await command2.executeText(message2, args2, this);
821
+ } catch (error) {
822
+ await this.handleCommandError(error, commandName, message2);
823
+ }
824
+ });
825
+ }
826
+ async start(token) {
827
+ if (!token) throw new Error("[djs-next] A token must be provided to start the bot.");
828
+ this.config = await loadConfig();
829
+ this._guildId = this._guildId || this.config.devGuildId;
830
+ if (!this._commandsDir) this._commandsDir = path6.resolve(process.cwd(), this.config.directories?.commands || "src/commands");
831
+ if (!this._eventsDir) this._eventsDir = path6.resolve(process.cwd(), this.config.directories?.events || "src/events");
832
+ if (!this._componentsDir) this._componentsDir = path6.resolve(process.cwd(), this.config.directories?.components || "src/components");
833
+ if (!this._tasksDir) this._tasksDir = path6.resolve(process.cwd(), this.config.directories?.tasks || "src/tasks");
834
+ if (!this._localesDir) this._localesDir = path6.resolve(process.cwd(), this.config.directories?.locales || "src/locales");
835
+ if (fs8.existsSync(this._localesDir)) loadLocales(this._localesDir, this.config.defaultLocale);
836
+ if (!this._middleware) {
837
+ const exts = [".js", ".mjs", ".cjs", ".ts", ".mts", ".cts"];
838
+ const cwd = process.cwd();
839
+ for (const ext of exts) {
840
+ const mwPath = path6.join(cwd, `middleware${ext}`);
841
+ if (fs8.existsSync(mwPath)) {
842
+ try {
843
+ const mwModule = await import(pathToFileURL6(mwPath).href);
844
+ this._middleware = mwModule.default?.middleware || mwModule.middleware || mwModule.default || mwModule;
845
+ if (this._middleware) {
846
+ console.log(`[djs-next] Loaded global middleware.`);
847
+ break;
848
+ }
849
+ } catch (err) {
850
+ console.error(`[djs-next] Error loading middleware file ${mwPath}:`, err);
851
+ }
852
+ }
853
+ }
854
+ }
855
+ if (fs8.existsSync(this._eventsDir)) await loadEvents(this, this._eventsDir);
856
+ if (fs8.existsSync(this._componentsDir)) this.components = await loadComponents(this._componentsDir);
857
+ if (fs8.existsSync(this._tasksDir)) await loadTasks(this, this._tasksDir);
858
+ await this.login(token);
859
+ console.log(`[djs-next] Bot is ready and logged in as ${this.user?.tag}!`);
860
+ if (fs8.existsSync(this._commandsDir)) {
861
+ this._clientId = this._clientId || this.user.id;
862
+ this.commands = await loadAndDeployCommands(this._commandsDir, token, this._clientId, this._guildId);
863
+ }
864
+ }
865
+ enableDevTools(prefix = "dnxt") {
866
+ if (prefix !== "dnxt" && prefix !== "nxt") {
867
+ throw new Error(`[djs-next] Developer Tools prefix must be either 'dnxt' or 'nxt'. Received: ${prefix}`);
868
+ }
869
+ this.on("messageCreate", async (message2) => {
870
+ await handleDNXT(message2, this, prefix);
871
+ });
872
+ console.log(`[djs-next] \u{1F6E0}\uFE0F Developer Tools enabled. Use "${prefix}" in chat. Ensure MessageContent intent is enabled!`);
873
+ }
874
+ async enableHMR() {
875
+ try {
876
+ const chokidar = await import("chokidar");
877
+ console.log(`[djs-next] \u{1F504} HMR Enabled. Watching for file changes...`);
878
+ const watcher = chokidar.watch([
879
+ this._commandsDir,
880
+ this._eventsDir,
881
+ this._componentsDir,
882
+ this._localesDir
883
+ ].filter(Boolean), { ignoreInitial: true });
884
+ watcher.on("change", async (filePath) => {
885
+ console.log(`[djs-next] \u267B\uFE0F File changed: ${filePath}. Reloading...`);
886
+ this.removeAllListeners();
887
+ this.commands.clear();
888
+ this.components.clear();
889
+ this.attachCoreListeners();
890
+ if (this._eventsDir) await loadEvents(this, this._eventsDir);
891
+ if (this._componentsDir) this.components = await loadComponents(this._componentsDir);
892
+ if (this._commandsDir && this._clientId) {
893
+ this.commands = await loadAndDeployCommands(this._commandsDir, this.token, this._clientId, this._guildId);
894
+ }
895
+ if (this._localesDir) loadLocales(this._localesDir, this.config.defaultLocale);
896
+ console.log(`[djs-next] \u2705 Hot Reload complete.`);
897
+ });
898
+ } catch (e) {
899
+ console.warn(`[djs-next] chokidar not installed. HMR is disabled. Please run "npm install chokidar" to use this feature.`);
900
+ }
901
+ }
902
+ async handleCommandError(error, commandKey, context) {
903
+ console.error(`[djs-next] Error executing command/component: "${commandKey}"`, error);
904
+ const djs = __require("discord.js");
905
+ if (this.config.responses?.errorBoundary === null) {
906
+ } else {
907
+ try {
908
+ const errorContent = this.config.responses?.errorBoundary || `### \u26A0\uFE0F Execution Error
909
+ > The framework encountered a fatal error while executing \`${commandKey}\`.`;
910
+ const codeBlock = `\`\`\`js
911
+ ${String(error.stack || error.message).substring(0, 1500)}
912
+ \`\`\``;
913
+ if ("commandName" in context || "customId" in context) {
914
+ const container = new djs.ContainerBuilder().setAccentColor(15548997).addTextDisplayComponents(new djs.TextDisplayBuilder().setContent(errorContent)).addSeparatorComponents(new djs.SeparatorBuilder()).addTextDisplayComponents(new djs.TextDisplayBuilder().setContent(codeBlock));
915
+ const payload = { components: [container], flags: 32768, ephemeral: true };
916
+ const i = context;
917
+ if (i.isRepliable()) {
918
+ if (i.replied || i.deferred) await i.followUp(payload);
919
+ else await i.reply(payload);
920
+ }
921
+ } else {
922
+ const embed = new djs.EmbedBuilder().setColor(15548997).setDescription(`${errorContent}
923
+
924
+ ${codeBlock}`);
925
+ const m = context;
926
+ await m.reply({ embeds: [embed] });
927
+ }
928
+ } catch (e) {
929
+ }
930
+ }
931
+ if (this.config.errorLogChannelId) {
932
+ try {
933
+ const channel = await this.channels.fetch(this.config.errorLogChannelId);
934
+ if (channel && channel.isTextBased()) {
935
+ const userId = "user" in context ? context.user.id : context.author.id;
936
+ await channel.send(`\u{1F6A8} **Global Error Boundary Caught Exception**
937
+ **Context:** \`${commandKey}\`
938
+ **User:** <@${userId}>
939
+ \`\`\`js
940
+ ${String(error.stack || error.message).substring(0, 1900)}
941
+ \`\`\``);
942
+ }
943
+ } catch (e) {
944
+ console.error(`[djs-next] Failed to send error to log channel:`, e);
945
+ }
946
+ }
947
+ }
948
+ async handlePreconditions(command2, context, commandKey) {
949
+ const userId = "user" in context ? context.user.id : context.author.id;
950
+ const isGuild = "guild" in context && context.guild !== null;
951
+ const member = context.member;
952
+ const sendErr = async (msg) => {
953
+ if (msg === null) return;
954
+ if ("reply" in context && typeof context.reply === "function") {
955
+ try {
956
+ if ("replied" in context && context.isRepliable() && (context.replied || context.deferred)) {
957
+ await context.followUp({ content: msg, ephemeral: true });
958
+ } else {
959
+ await context.reply({ content: msg, ephemeral: true, allowedMentions: { repliedUser: false } });
960
+ }
961
+ } catch (e) {
962
+ }
963
+ }
964
+ };
965
+ if ("developerOnly" in command2 && command2.developerOnly && !this._developers.includes(userId)) {
966
+ await sendErr(this.config.responses?.developerOnly !== void 0 ? this.config.responses.developerOnly : "Only developers can use this command.");
967
+ return false;
968
+ }
969
+ if ("guildOnly" in command2 && command2.guildOnly && !isGuild) {
970
+ await sendErr(this.config.responses?.guildOnly !== void 0 ? this.config.responses.guildOnly : "This command can only be used in a server.");
971
+ return false;
972
+ }
973
+ if ("userPermissions" in command2 && command2.userPermissions && member?.permissions) {
974
+ const missing = member.permissions.missing(command2.userPermissions);
975
+ if (missing.length > 0) {
976
+ await sendErr(this.config.responses?.missingPerms !== void 0 ? this.config.responses.missingPerms === null ? null : this.config.responses.missingPerms.replace("{perms}", missing.join(", ")) : `You are missing permissions: \`${missing.join(", ")}\``);
977
+ return false;
978
+ }
979
+ }
980
+ if ("botPermissions" in command2 && command2.botPermissions && context.guild?.members.me?.permissions) {
981
+ const missing = context.guild.members.me.permissions.missing(command2.botPermissions);
982
+ if (missing.length > 0) {
983
+ await sendErr(this.config.responses?.missingPerms !== void 0 ? this.config.responses.missingPerms === null ? null : this.config.responses.missingPerms.replace("{perms}", missing.join(", ")) : `I am missing permissions to run this: \`${missing.join(", ")}\``);
984
+ return false;
985
+ }
986
+ }
987
+ let totalCooldown = "cooldown" in command2 && command2.cooldown ? command2.cooldown * 1e3 : 0;
988
+ if (command2.preconditions) {
989
+ for (const pre of command2.preconditions) {
990
+ const parts = pre.split(":");
991
+ const type = parts[0].toLowerCase();
992
+ const val = parts.slice(1).join(":");
993
+ if (type === "owneronly" || type === "developeronly") {
994
+ if (!this._developers.includes(userId)) {
995
+ await sendErr(this.config.responses?.developerOnly !== void 0 ? this.config.responses.developerOnly : "Only developers can use this command.");
996
+ return false;
997
+ }
998
+ } else if (type === "guildonly") {
999
+ if (!isGuild) {
1000
+ await sendErr(this.config.responses?.guildOnly !== void 0 ? this.config.responses.guildOnly : "This command can only be used in a server.");
1001
+ return false;
1002
+ }
1003
+ } else if (type === "requireperms") {
1004
+ const perms = val.split(",").map((p) => p.trim());
1005
+ if (member?.permissions) {
1006
+ const missing = member.permissions.missing(perms);
1007
+ if (missing.length > 0) {
1008
+ await sendErr(this.config.responses?.missingPerms !== void 0 ? this.config.responses.missingPerms === null ? null : this.config.responses.missingPerms.replace("{perms}", missing.join(", ")) : `You are missing permissions: \`${missing.join(", ")}\``);
1009
+ return false;
1010
+ }
1011
+ }
1012
+ } else if (type === "cooldown") {
1013
+ const match = val.match(/(\d+)(s|m|h)/);
1014
+ if (match) {
1015
+ let amount = parseInt(match[1]) * 1e3;
1016
+ if (match[2] === "m") amount *= 60;
1017
+ if (match[2] === "h") amount *= 3600;
1018
+ totalCooldown = Math.max(totalCooldown, amount);
1019
+ }
1020
+ }
1021
+ }
1022
+ }
1023
+ if (totalCooldown > 0) {
1024
+ const now = Date.now();
1025
+ if (this.config.cooldownAdapter) {
1026
+ const lastUsed = await this.config.cooldownAdapter.get(commandKey, userId);
1027
+ if (lastUsed) {
1028
+ const expirationTime = lastUsed + totalCooldown;
1029
+ if (now < expirationTime) {
1030
+ const timeStr = `<t:${Math.round(expirationTime / 1e3)}:R>`;
1031
+ await sendErr(this.config.responses?.cooldown !== void 0 ? this.config.responses.cooldown === null ? null : this.config.responses.cooldown.replace("{time}", timeStr) : `Please wait, you are on a cooldown. You can use it again ${timeStr}.`);
1032
+ return false;
1033
+ }
1034
+ }
1035
+ await this.config.cooldownAdapter.set(commandKey, userId, now);
1036
+ } else {
1037
+ if (!this.cooldowns.has(commandKey)) this.cooldowns.set(commandKey, new Collection3());
1038
+ const timestamps = this.cooldowns.get(commandKey);
1039
+ if (timestamps.has(userId)) {
1040
+ const expirationTime = timestamps.get(userId) + totalCooldown;
1041
+ if (now < expirationTime) {
1042
+ const timeStr = `<t:${Math.round(expirationTime / 1e3)}:R>`;
1043
+ await sendErr(this.config.responses?.cooldown !== void 0 ? this.config.responses.cooldown === null ? null : this.config.responses.cooldown.replace("{time}", timeStr) : `Please wait, you are on a cooldown. You can use it again ${timeStr}.`);
1044
+ return false;
1045
+ }
1046
+ }
1047
+ timestamps.set(userId, now);
1048
+ setTimeout(() => timestamps.delete(userId), totalCooldown);
1049
+ }
1050
+ }
1051
+ return true;
1052
+ }
1053
+ };
1054
+
1055
+ // src/utils/paginate.ts
1056
+ import {
1057
+ ActionRowBuilder,
1058
+ ButtonBuilder,
1059
+ ButtonStyle
1060
+ } from "discord.js";
1061
+ async function paginate(context, pages, time = 6e4) {
1062
+ const isMessage = "author" in context;
1063
+ if (!isMessage) {
1064
+ if (!context.deferred && !context.replied) {
1065
+ await context.deferReply();
1066
+ }
1067
+ }
1068
+ if (pages.length === 1) {
1069
+ if (isMessage) {
1070
+ return context.reply({ embeds: [pages[0]], components: [] });
1071
+ } else {
1072
+ return context.editReply({ embeds: [pages[0]], components: [] });
1073
+ }
1074
+ }
1075
+ let index = 0;
1076
+ const prevButton = new ButtonBuilder().setCustomId("djs_prev").setLabel("Previous").setStyle(ButtonStyle.Primary).setDisabled(true);
1077
+ const nextButton = new ButtonBuilder().setCustomId("djs_next").setLabel("Next").setStyle(ButtonStyle.Primary);
1078
+ const row = new ActionRowBuilder().addComponents(prevButton, nextButton);
1079
+ let message2;
1080
+ if (isMessage) {
1081
+ message2 = await context.reply({
1082
+ embeds: [pages[index]],
1083
+ components: [row]
1084
+ });
1085
+ } else {
1086
+ message2 = await context.editReply({
1087
+ embeds: [pages[index]],
1088
+ components: [row]
1089
+ });
1090
+ }
1091
+ const collector = message2.createMessageComponentCollector({
1092
+ filter: (i) => i.user.id === (isMessage ? context.author.id : context.user.id),
1093
+ time
1094
+ });
1095
+ collector.on("collect", async (i) => {
1096
+ if (i.customId === "djs_prev") {
1097
+ index = index > 0 ? index - 1 : index;
1098
+ } else if (i.customId === "djs_next") {
1099
+ index = index < pages.length - 1 ? index + 1 : index;
1100
+ }
1101
+ prevButton.setDisabled(index === 0);
1102
+ nextButton.setDisabled(index === pages.length - 1);
1103
+ await i.update({
1104
+ embeds: [pages[index]],
1105
+ components: [new ActionRowBuilder().addComponents(prevButton, nextButton)]
1106
+ });
1107
+ });
1108
+ collector.on("end", async () => {
1109
+ prevButton.setDisabled(true);
1110
+ nextButton.setDisabled(true);
1111
+ if (message2.editable) {
1112
+ await message2.edit({
1113
+ components: [new ActionRowBuilder().addComponents(prevButton, nextButton)]
1114
+ }).catch(() => {
1115
+ });
1116
+ }
1117
+ });
1118
+ }
1119
+
1120
+ // src/utils/prompts.ts
1121
+ import {
1122
+ ActionRowBuilder as ActionRowBuilder2,
1123
+ ButtonBuilder as ButtonBuilder2,
1124
+ ButtonStyle as ButtonStyle2
1125
+ } from "discord.js";
1126
+ async function confirmPrompt(context, content2, time = 3e4) {
1127
+ const isMessage = "author" in context;
1128
+ if (!isMessage) {
1129
+ if (!context.deferred && !context.replied) {
1130
+ await context.deferReply();
1131
+ }
1132
+ }
1133
+ const yesButton = new ButtonBuilder2().setCustomId("djs_prompt_yes").setLabel("Yes").setStyle(ButtonStyle2.Success);
1134
+ const noButton = new ButtonBuilder2().setCustomId("djs_prompt_no").setLabel("No").setStyle(ButtonStyle2.Danger);
1135
+ const row = new ActionRowBuilder2().addComponents(yesButton, noButton);
1136
+ const payload = { components: [row] };
1137
+ if (typeof content2 === "string") {
1138
+ payload.content = content2;
1139
+ } else {
1140
+ payload.embeds = [content2];
1141
+ }
1142
+ let message2;
1143
+ if (isMessage) {
1144
+ message2 = await context.reply(payload);
1145
+ } else {
1146
+ message2 = await context.editReply(payload);
1147
+ }
1148
+ try {
1149
+ const interaction = await message2.awaitMessageComponent({
1150
+ filter: (i) => i.user.id === (isMessage ? context.author.id : context.user.id),
1151
+ time
1152
+ });
1153
+ if (interaction.customId === "djs_prompt_yes") {
1154
+ await interaction.update({ components: [] });
1155
+ return true;
1156
+ } else {
1157
+ await interaction.update({ components: [] });
1158
+ return false;
1159
+ }
1160
+ } catch (error) {
1161
+ if (message2.editable) {
1162
+ await message2.edit({ components: [] }).catch(() => {
1163
+ });
1164
+ }
1165
+ return null;
1166
+ }
1167
+ }
1168
+
1169
+ // src/utils/PaginationBuilder.ts
1170
+ import {
1171
+ ActionRowBuilder as ActionRowBuilder3,
1172
+ ButtonBuilder as ButtonBuilder3,
1173
+ ButtonStyle as ButtonStyle3,
1174
+ CommandInteraction as CommandInteraction3,
1175
+ ComponentType
1176
+ } from "discord.js";
1177
+ var PaginationBuilder = class {
1178
+ pages = [];
1179
+ timeout = 6e4;
1180
+ constructor(pages) {
1181
+ if (pages) this.pages = pages;
1182
+ }
1183
+ addPage(embed) {
1184
+ this.pages.push(embed);
1185
+ return this;
1186
+ }
1187
+ setPages(pages) {
1188
+ this.pages = pages;
1189
+ return this;
1190
+ }
1191
+ setTimeout(ms) {
1192
+ this.timeout = ms;
1193
+ return this;
1194
+ }
1195
+ async build(target) {
1196
+ if (this.pages.length === 0) throw new Error("[djs-next] PaginationBuilder requires at least one page.");
1197
+ if (this.pages.length === 1) {
1198
+ if (target instanceof CommandInteraction3) {
1199
+ if (target.deferred || target.replied) {
1200
+ return await target.editReply({ embeds: [this.pages[0]] });
1201
+ }
1202
+ return await target.reply({ embeds: [this.pages[0]], fetchReply: true });
1203
+ } else {
1204
+ return await target.reply({ embeds: [this.pages[0]] });
1205
+ }
1206
+ }
1207
+ let currentPage = 0;
1208
+ const row = new ActionRowBuilder3().addComponents(
1209
+ new ButtonBuilder3().setCustomId("prev").setLabel("\u25C0").setStyle(ButtonStyle3.Primary).setDisabled(true),
1210
+ new ButtonBuilder3().setCustomId("page").setLabel(`1 / ${this.pages.length}`).setStyle(ButtonStyle3.Secondary).setDisabled(true),
1211
+ new ButtonBuilder3().setCustomId("next").setLabel("\u25B6").setStyle(ButtonStyle3.Primary)
1212
+ );
1213
+ let replyMsg;
1214
+ if (target instanceof CommandInteraction3) {
1215
+ if (target.deferred || target.replied) {
1216
+ replyMsg = await target.editReply({ embeds: [this.pages[0]], components: [row] });
1217
+ } else {
1218
+ replyMsg = await target.reply({ embeds: [this.pages[0]], components: [row], fetchReply: true });
1219
+ }
1220
+ } else {
1221
+ replyMsg = await target.reply({ embeds: [this.pages[0]], components: [row] });
1222
+ }
1223
+ const userId = target instanceof CommandInteraction3 ? target.user.id : target.author.id;
1224
+ const collector = replyMsg.createMessageComponentCollector({
1225
+ componentType: ComponentType.Button,
1226
+ time: this.timeout,
1227
+ filter: (i) => i.user.id === userId
1228
+ });
1229
+ collector.on("collect", async (i) => {
1230
+ if (i.customId === "prev") currentPage--;
1231
+ else if (i.customId === "next") currentPage++;
1232
+ const newRow = new ActionRowBuilder3().addComponents(
1233
+ new ButtonBuilder3().setCustomId("prev").setLabel("\u25C0").setStyle(ButtonStyle3.Primary).setDisabled(currentPage === 0),
1234
+ new ButtonBuilder3().setCustomId("page").setLabel(`${currentPage + 1} / ${this.pages.length}`).setStyle(ButtonStyle3.Secondary).setDisabled(true),
1235
+ new ButtonBuilder3().setCustomId("next").setLabel("\u25B6").setStyle(ButtonStyle3.Primary).setDisabled(currentPage === this.pages.length - 1)
1236
+ );
1237
+ await i.update({ embeds: [this.pages[currentPage]], components: [newRow] });
1238
+ });
1239
+ collector.on("end", () => {
1240
+ replyMsg.edit({ components: [] }).catch(() => null);
1241
+ });
1242
+ return replyMsg;
1243
+ }
1244
+ };
1245
+
1246
+ // src/index.ts
1247
+ export * from "discord.js";
1248
+ export {
1249
+ DJSNextClient,
1250
+ PaginationBuilder,
1251
+ confirmPrompt,
1252
+ defineConfig,
1253
+ getLocalesCache,
1254
+ loadConfig,
1255
+ loadLocales,
1256
+ paginate,
1257
+ translate
1258
+ };
1259
+ //# sourceMappingURL=index.mjs.map