djs-next 0.0.1 → 1.0.0-dev.2

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 CHANGED
@@ -5,9 +5,6 @@ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require
5
5
  throw Error('Dynamic require of "' + x + '" is not supported');
6
6
  });
7
7
 
8
- // src/index.ts
9
- import "dotenv/config";
10
-
11
8
  // src/client.ts
12
9
  import { Client, Collection as Collection3 } from "discord.js";
13
10
 
@@ -255,9 +252,9 @@ function loadLocales(localesDir, defaultLocale) {
255
252
  for (const file of files) {
256
253
  if (file.endsWith(".json")) {
257
254
  const lang = file.replace(".json", "");
258
- const content2 = fs7.readFileSync(path5.join(localesDir, file), "utf8");
255
+ const content = fs7.readFileSync(path5.join(localesDir, file), "utf8");
259
256
  try {
260
- localesCache[lang] = JSON.parse(content2);
257
+ localesCache[lang] = JSON.parse(content);
261
258
  } catch (e) {
262
259
  console.error(`[djs-next] Failed to parse locale file: ${file}`, e);
263
260
  }
@@ -291,92 +288,26 @@ function getLocalesCache() {
291
288
  }
292
289
 
293
290
  // src/plugins/dnxt.ts
294
- import { version as djsVersion } from "discord.js";
295
291
  import { exec } from "child_process";
296
292
  import util from "util";
297
293
  import os from "os";
298
294
  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) {
295
+ async function handleDNXT(message, client, prefix = "dnxt") {
307
296
  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);
297
+ if (!client["_developers"].includes(message.author.id)) return;
298
+ if (!message.content.startsWith(prefix)) return;
299
+ const args = message.content.slice(prefix.length).trim().split(/ +/);
327
300
  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
301
  if (!command) {
356
302
  const mem = process.memoryUsage();
303
+ const discordJsVersion = __require("discord.js/package.json").version;
357
304
  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
- });
305
+ const text = `Module was loaded <t:${Math.floor((Date.now() - client.uptime) / 1e3)}:R>.
306
+ DNXT framework plugin, discord.js \`${discordJsVersion}\`, \`Node.js ${process.version}\` on \`${os.type()}\`.
307
+ Latencies: \`${botPing}ms\` websocket ping.
308
+ Memory: \`${(mem.rss / 1024 / 1024).toFixed(2)} MB\` physical, \`${(mem.heapUsed / 1024 / 1024).toFixed(2)} MB\` heap.
309
+ System: \`${os.cpus().length}\` thread(s), \`${(os.uptime() / 60 / 60).toFixed(2)}\` hrs system uptime.`;
310
+ await message.reply(text);
380
311
  return;
381
312
  }
382
313
  if (command === "js" || command === "eval" || command === "py") {
@@ -390,12 +321,12 @@ async function handleDNXT(message, client, devPrefix) {
390
321
  let evaled = await eval(`(async () => { ${code} })()`);
391
322
  const end = process.hrtime.bigint();
392
323
  const timeMs = Number(end - start) / 1e6;
393
- if (typeof evaled !== "string") evaled = util.inspect(evaled, { depth: 1, colors: true });
324
+ if (typeof evaled !== "string") evaled = util.inspect(evaled, { depth: 1 });
394
325
  await sendPaginatedText(message, `\u2705 **Evaluated in ${timeMs.toFixed(3)}ms**
395
- `, evaled, "ansi");
326
+ `, evaled, "js");
396
327
  } catch (err) {
397
328
  await sendPaginatedText(message, `\u274C **Evaluation Error**
398
- `, err.message, "ansi");
329
+ `, err.message, "js");
399
330
  }
400
331
  return;
401
332
  }
@@ -404,74 +335,52 @@ async function handleDNXT(message, client, devPrefix) {
404
335
  if (!cmd) return void await message.reply("\u274C Please provide a command to execute.");
405
336
  try {
406
337
  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
- }
338
+ const { stdout, stderr } = await execAsync(cmd);
417
339
  const end2 = process.hrtime.bigint();
418
340
  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}`;
341
+ const result = stdout || stderr || "No output.";
427
342
  await sendPaginatedText(message, `\u2705 **Executed in ${timeMs2.toFixed(3)}ms**
428
- `, resultText, "ansi");
343
+ `, result, "sh");
429
344
  } catch (err) {
430
345
  await sendPaginatedText(message, `\u274C **Shell Error**
431
- `, err.message, "ansi");
346
+ `, err.message, "sh");
432
347
  }
433
348
  return;
434
349
  }
435
- if (command === "load" || command === "unload" || command === "reload") {
350
+ if (command === "reload" || command === "load") {
436
351
  const target = args[0]?.toLowerCase();
437
352
  try {
438
353
  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.`);
354
+ client.commands.clear();
355
+ client.commands = await loadAndDeployCommands(client["_commandsDir"], client.token, client["_clientId"], client["_guildId"]);
356
+ await message.reply("\u2705 Reloaded commands.");
442
357
  } 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.`);
358
+ client.removeAllListeners();
359
+ client["attachCoreListeners"]();
360
+ await loadEvents(client, client["_eventsDir"]);
361
+ await message.reply("\u2705 Reloaded events.");
449
362
  } 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.`);
363
+ client.components.clear();
364
+ client.components = await loadComponents(client["_componentsDir"]);
365
+ await message.reply("\u2705 Reloaded components.");
453
366
  } 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.`);
367
+ loadLocales(client["_localesDir"], client.config.defaultLocale);
368
+ await message.reply("\u2705 Reloaded locales.");
456
369
  } 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.`);
370
+ client.removeAllListeners();
371
+ client["attachCoreListeners"]();
372
+ client.commands.clear();
373
+ client.components.clear();
374
+ if (client["_eventsDir"]) await loadEvents(client, client["_eventsDir"]);
375
+ if (client["_componentsDir"]) client.components = await loadComponents(client["_componentsDir"]);
376
+ if (client["_localesDir"]) loadLocales(client["_localesDir"], client.config.defaultLocale);
377
+ if (client["_commandsDir"]) client.commands = await loadAndDeployCommands(client["_commandsDir"], client.token, client["_clientId"], client["_guildId"]);
378
+ await message.reply("\u2705 Reloaded all framework modules.");
470
379
  } else {
471
380
  await message.reply("\u274C Unknown target. Valid targets: `commands, events, components, locales, all`");
472
381
  }
473
382
  } catch (err) {
474
- await message.reply(`\u274C **${command.toUpperCase()} Error:** ${err.message}`);
383
+ await message.reply(`\u274C **Reload Error:** ${err.message}`);
475
384
  }
476
385
  return;
477
386
  }
@@ -481,14 +390,49 @@ async function handleDNXT(message, client, devPrefix) {
481
390
  const file = args.join(" ");
482
391
  if (!file) return void await message.reply("\u274C Please provide a file to read.");
483
392
  try {
484
- const content2 = fs9.readFileSync(path7.resolve(process.cwd(), file), "utf8");
393
+ const content = fs9.readFileSync(path7.resolve(process.cwd(), file), "utf8");
485
394
  await sendPaginatedText(message, `\u{1F4C4} **${file}**
486
- `, content2, file.split(".").pop() || "");
395
+ `, content, file.split(".").pop() || "");
487
396
  } catch (e) {
488
397
  await message.reply(`\u274C **Error reading file:** ${e.message}`);
489
398
  }
490
399
  return;
491
400
  }
401
+ if (command === "su" || command === "sudo") {
402
+ const targetUserId = args.shift();
403
+ const cmd = args.join(" ");
404
+ if (!targetUserId || !cmd) return void await message.reply(`\u274C Usage: ${prefix} su <user_id> <command>`);
405
+ try {
406
+ const targetUser = await client.users.fetch(targetUserId.replace(/<@!?|>/g, ""));
407
+ if (!targetUser) throw new Error("User not found.");
408
+ const mockMessage = Object.assign(Object.create(Object.getPrototypeOf(message)), message);
409
+ mockMessage.author = targetUser;
410
+ if (message.guild) {
411
+ mockMessage.member = await message.guild.members.fetch(targetUser.id).catch(() => null);
412
+ }
413
+ mockMessage.content = cmd;
414
+ client.emit("messageCreate", mockMessage);
415
+ await message.reply(`\u2705 Invoked \`${cmd}\` as **${targetUser.tag}**.`);
416
+ } catch (e) {
417
+ await message.reply(`\u274C **Sudo Error:** ${e.message}`);
418
+ }
419
+ return;
420
+ }
421
+ if (command === "source" || command === "src") {
422
+ const target = args.join(" ");
423
+ if (!target) return void await message.reply("\u274C Please provide a command name.");
424
+ const cmdData = client.commands.get(target);
425
+ if (!cmdData || !cmdData.filepath) return void await message.reply("\u274C Command not found or has no associated filepath.");
426
+ try {
427
+ const fs9 = await import("fs");
428
+ const content = fs9.readFileSync(cmdData.filepath, "utf8");
429
+ await sendPaginatedText(message, `\u{1F4C4} **Source of \`${target}\`**
430
+ `, content, cmdData.filepath.split(".").pop() || "");
431
+ } catch (e) {
432
+ await message.reply(`\u274C **Error reading source:** ${e.message}`);
433
+ }
434
+ return;
435
+ }
492
436
  if (command === "curl") {
493
437
  const url = args[0];
494
438
  if (!url) return void await message.reply("\u274C Please provide a URL.");
@@ -516,38 +460,64 @@ async function handleDNXT(message, client, devPrefix) {
516
460
  const endMem = process.memoryUsage().heapUsed;
517
461
  const timeMs = Number(end - start) / 1e6;
518
462
  const memDiff = (endMem - startMem) / 1024 / 1024;
519
- if (typeof evaled !== "string") evaled = util.inspect(evaled, { depth: 1, colors: true });
463
+ if (typeof evaled !== "string") evaled = util.inspect(evaled, { depth: 1 });
520
464
  await sendPaginatedText(message, `\u23F1\uFE0F **Debug Execution**
521
465
  Time: \`${timeMs.toFixed(3)}ms\` | Heap Delta: \`${memDiff.toFixed(3)}MB\`
522
- `, evaled, "ansi");
466
+ `, evaled, "js");
523
467
  } catch (err) {
524
468
  await sendPaginatedText(message, `\u274C **Debug Error**
525
- `, err.message, "ansi");
469
+ `, err.message, "js");
526
470
  }
527
471
  return;
528
472
  }
529
473
  if (command === "in") {
530
474
  const channelId = args.shift()?.replace(/<#|>/g, "");
531
475
  const cmd = args.join(" ");
532
- if (!channelId || !cmd) return void await message.reply(`\u274C Usage: ${matchedTrigger} in <#channel|id> <command>`);
476
+ if (!channelId || !cmd) return void await message.reply(`\u274C Usage: ${prefix} in <channel> <command>`);
533
477
  try {
534
478
  const targetChannel = await client.channels.fetch(channelId);
535
479
  if (!targetChannel || !targetChannel.isTextBased()) throw new Error("Invalid Text Channel.");
536
480
  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 });
481
+ mockMessage.channel = targetChannel;
482
+ mockMessage.channelId = targetChannel.id;
483
+ mockMessage.content = cmd;
545
484
  client.emit("messageCreate", mockMessage);
485
+ await message.reply(`\u2705 Redirected execution to <#${targetChannel.id}>.`);
546
486
  } catch (e) {
547
487
  await message.reply(`\u274C **In Error:** ${e.message}`);
548
488
  }
549
489
  return;
550
490
  }
491
+ if (command === "tasks") {
492
+ const tasks = client._activeTasks;
493
+ if (!tasks || tasks.size === 0) return void await message.reply("No active background tasks running.");
494
+ let text = `\u2699\uFE0F **Active Background Tasks (${tasks.size})**
495
+ `;
496
+ for (const [name] of tasks.entries()) {
497
+ text += `- \`${name.split("/").pop()}\`
498
+ `;
499
+ }
500
+ await sendPaginatedText(message, "", text, "");
501
+ return;
502
+ }
503
+ if (command === "cancel") {
504
+ const target = args.join(" ");
505
+ if (!target) return void await message.reply(`\u274C Usage: ${prefix} cancel <task_name>`);
506
+ const tasks = client._activeTasks;
507
+ if (!tasks) return void await message.reply("No active tasks to cancel.");
508
+ let found = false;
509
+ for (const [name, intervalId] of tasks.entries()) {
510
+ if (name.includes(target)) {
511
+ clearInterval(intervalId);
512
+ tasks.delete(name);
513
+ found = true;
514
+ await message.reply(`\u2705 Cancelled background task: \`${name.split("/").pop()}\``);
515
+ break;
516
+ }
517
+ }
518
+ if (!found) await message.reply("\u274C Task not found.");
519
+ return;
520
+ }
551
521
  if (command === "sync") {
552
522
  try {
553
523
  await message.reply("\u{1F504} Force syncing slash commands...");
@@ -558,102 +528,80 @@ Time: \`${timeMs.toFixed(3)}ms\` | Heap Delta: \`${memDiff.toFixed(3)}MB\`
558
528
  }
559
529
  return;
560
530
  }
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);
531
+ if (command === "sql") {
532
+ const query = args.join(" ");
533
+ if (!query) return void await message.reply(`\u274C Usage: ${prefix} sql <query>`);
534
+ try {
535
+ let res;
536
+ if (client.db && typeof client.db.$queryRawUnsafe === "function") {
537
+ res = await client.db.$queryRawUnsafe(query);
538
+ } else if (client.db && typeof client.db.query === "function") {
539
+ res = await client.db.query(query);
540
+ } else {
541
+ return void await message.reply("\u274C Your configured `client.db` does not expose a recognized raw SQL execution method (`$queryRawUnsafe` or `query`).");
542
+ }
543
+ const inspect = util.inspect(res, { depth: 2 });
544
+ await sendPaginatedText(message, `\u{1F5C4}\uFE0F **SQL Query**
545
+ `, inspect, "js");
546
+ } catch (e) {
547
+ await message.reply(`\u274C **SQL Error:** ${e.message}`);
548
+ }
572
549
  return;
573
550
  }
574
- if (command === "shutdown" || command === "stop") {
575
- await message.reply("\u{1F6D1} Shutting down framework...");
576
- client.destroy();
577
- process.exit(0);
551
+ if (command === "vc" || command === "voice") {
552
+ if (!message.guild) return void await message.reply("\u274C This command must be used in a server.");
553
+ const me = message.guild.members.me;
554
+ if (!me?.voice?.channel) return void await message.reply("\u274C Bot is not currently in a voice channel.");
555
+ const text = `\u{1F399}\uFE0F **Voice Debugger**
556
+ Channel: <#${me.voice.channel.id}> (\`${me.voice.channel.id}\`)
557
+ Muted: ${me.voice.mute} | Deafened: ${me.voice.deaf}
558
+ Session ID: \`${me.voice.sessionId || "None"}\``;
559
+ await message.reply(text);
578
560
  return;
579
561
  }
580
- await message.reply(`\u2753 Unknown ${matchedTrigger} command. Available: \`js, sh, git, cat, curl, in, debug, reload, sync, restart, shutdown\``);
562
+ await message.reply(`\u2753 Unknown ${prefix} command. Available: \`js, sh, git, cat, curl, su, in, source, debug, reload, tasks, cancel, sync, sql, vc\``);
581
563
  }
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
- \`\`\``));
564
+ async function sendPaginatedText(message2, header, content, language = "") {
565
+ const maxLength = 1900;
566
+ if (content.length <= maxLength) {
567
+ await message2.reply(`${header}\`\`\`${language}
568
+ ${content}
569
+ \`\`\``);
589
570
  return;
590
571
  }
591
572
  const chunks = [];
592
- for (let i = 0; i < content2.length; i += maxLength) {
593
- chunks.push(content2.substring(i, i + maxLength));
573
+ for (let i = 0; i < content.length; i += maxLength) {
574
+ chunks.push(content.substring(i, i + maxLength));
594
575
  }
595
576
  let index = 0;
596
- const djs = __require("discord.js");
597
- function buildPage(idx) {
598
- const text = `### ${header.replace(/\\*\\*/g, "")}
599
- \`\`\`${language}
600
- ${chunks[idx]}
577
+ const reply = await message2.reply(`${header}\`\`\`${language}
578
+ ${chunks[index]}
601
579
  \`\`\`
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,
580
+ *Page 1 of ${chunks.length}*`);
581
+ await reply.react("\u25C0\uFE0F");
582
+ await reply.react("\u25B6\uFE0F");
583
+ await reply.react("\u23F9\uFE0F");
584
+ const collector = reply.createReactionCollector({
585
+ filter: (reaction, user) => ["\u25C0\uFE0F", "\u25B6\uFE0F", "\u23F9\uFE0F"].includes(reaction.emoji.name) && user.id === message2.author.id,
622
586
  time: 12e4
623
587
  });
624
- collector.on("collect", async (i) => {
625
- if (i.customId === "first") {
626
- index = 0;
627
- } else if (i.customId === "prev") {
588
+ collector.on("collect", async (reaction, user) => {
589
+ await reaction.users.remove(user.id).catch(() => null);
590
+ if (reaction.emoji.name === "\u25C0\uFE0F") {
628
591
  index = index > 0 ? index - 1 : index;
629
- } else if (i.customId === "next") {
592
+ } else if (reaction.emoji.name === "\u25B6\uFE0F") {
630
593
  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);
594
+ } else if (reaction.emoji.name === "\u23F9\uFE0F") {
650
595
  collector.stop();
651
596
  return;
652
597
  }
653
- await i.update(buildPage(index));
598
+ await reply.edit(`${header}\`\`\`${language}
599
+ ${chunks[index]}
600
+ \`\`\`
601
+ *Page ${index + 1} of ${chunks.length}*`);
654
602
  });
655
603
  collector.on("end", () => {
656
- reply.edit({ components: [] }).catch(() => null);
604
+ reply.reactions.removeAll().catch(() => null);
657
605
  });
658
606
  }
659
607
 
@@ -675,10 +623,7 @@ var DJSNextClient = class extends Client {
675
623
  _developers;
676
624
  _middleware;
677
625
  _prefixes;
678
- _enableSlashCommands;
679
- _enableTextCommands;
680
626
  _enableMentionPrefix;
681
- _enableNoPrefix;
682
627
  constructor(options) {
683
628
  super(options);
684
629
  this.commands = new Collection3();
@@ -694,12 +639,7 @@ var DJSNextClient = class extends Client {
694
639
  this._middleware = options.middleware;
695
640
  const prefs = options.prefixes || [];
696
641
  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
642
  this._enableMentionPrefix = options.enableMentionPrefix ?? true;
701
- this._enableNoPrefix = options.enableNoPrefix ?? false;
702
- if (options.db) this.db = options.db;
703
643
  this.attachCoreListeners();
704
644
  }
705
645
  attachCoreListeners() {
@@ -714,7 +654,6 @@ var DJSNextClient = class extends Client {
714
654
  }
715
655
  }
716
656
  if (interaction.isChatInputCommand()) {
717
- if (!this._enableSlashCommands) return;
718
657
  let commandKey = interaction.commandName;
719
658
  const group = interaction.options.getSubcommandGroup(false);
720
659
  const sub = interaction.options.getSubcommand(false);
@@ -722,11 +661,48 @@ var DJSNextClient = class extends Client {
722
661
  if (sub) commandKey += ` ${sub}`;
723
662
  const command2 = this.commands.get(commandKey);
724
663
  if (!command2 || !command2.execute) return;
725
- if (!await this.handlePreconditions(command2, interaction, commandKey)) return;
664
+ if (command2.developerOnly && !this._developers.includes(interaction.user.id)) {
665
+ return interaction.reply({ content: "Only developers can use this command.", ephemeral: true });
666
+ }
667
+ if (command2.guildOnly && !interaction.inGuild()) {
668
+ return interaction.reply({ content: "This command can only be used in a server.", ephemeral: true });
669
+ }
670
+ if (command2.userPermissions && interaction.memberPermissions) {
671
+ const missing = interaction.memberPermissions.missing(command2.userPermissions);
672
+ if (missing.length > 0) {
673
+ return interaction.reply({ content: `You are missing permissions: \`${missing.join(", ")}\``, ephemeral: true });
674
+ }
675
+ }
676
+ if (command2.botPermissions && interaction.guild?.members.me?.permissions) {
677
+ const missing = interaction.guild.members.me.permissions.missing(command2.botPermissions);
678
+ if (missing.length > 0) {
679
+ return interaction.reply({ content: `I am missing permissions to run this: \`${missing.join(", ")}\``, ephemeral: true });
680
+ }
681
+ }
682
+ if (command2.cooldown) {
683
+ if (!this.cooldowns.has(commandKey)) this.cooldowns.set(commandKey, new Collection3());
684
+ const now = Date.now();
685
+ const timestamps = this.cooldowns.get(commandKey);
686
+ const cooldownAmount = command2.cooldown * 1e3;
687
+ if (timestamps.has(interaction.user.id)) {
688
+ const expirationTime = timestamps.get(interaction.user.id) + cooldownAmount;
689
+ if (now < expirationTime) {
690
+ return interaction.reply({
691
+ content: `Please wait, you are on a cooldown. You can use it again <t:${Math.round(expirationTime / 1e3)}:R>.`,
692
+ ephemeral: true
693
+ });
694
+ }
695
+ }
696
+ timestamps.set(interaction.user.id, now);
697
+ setTimeout(() => timestamps.delete(interaction.user.id), cooldownAmount);
698
+ }
726
699
  try {
727
700
  await command2.execute(interaction, this);
728
701
  } catch (error) {
729
- await this.handleCommandError(error, commandKey, interaction);
702
+ console.error(`[djs-next] Error executing command: "${commandKey}"`, error);
703
+ const msg = { content: "We ran into an internal error executing this command. The developers have been notified.", ephemeral: true };
704
+ if (interaction.replied || interaction.deferred) await interaction.followUp(msg).catch(() => null);
705
+ else await interaction.reply(msg).catch(() => null);
730
706
  }
731
707
  }
732
708
  if (interaction.isAutocomplete()) {
@@ -762,18 +738,19 @@ var DJSNextClient = class extends Client {
762
738
  }
763
739
  }
764
740
  if (component) {
765
- if (!await this.handlePreconditions(component, interaction, interaction.customId)) return;
766
741
  try {
767
742
  await component.execute(interaction, this, params);
768
743
  } catch (error) {
769
- await this.handleCommandError(error, interaction.customId, interaction);
744
+ console.error(`[djs-next] Error executing component: "${interaction.customId}"`, error);
745
+ const msg = { content: "We ran into an internal error executing this component.", ephemeral: true };
746
+ if (interaction.replied || interaction.deferred) await interaction.followUp(msg).catch(() => null);
747
+ else await interaction.reply(msg).catch(() => null);
770
748
  }
771
749
  }
772
750
  }
773
751
  });
774
752
  this.on("messageCreate", async (message2) => {
775
753
  if (message2.author.bot) return;
776
- if (!this._enableTextCommands) return;
777
754
  if (this._middleware) {
778
755
  try {
779
756
  const shouldContinue = await this._middleware(message2, this);
@@ -783,31 +760,28 @@ var DJSNextClient = class extends Client {
783
760
  return;
784
761
  }
785
762
  }
786
- let content2 = message2.content.trim();
763
+ let content = message2.content.trim();
787
764
  let matchedPrefix = "";
788
765
  let isCommand = false;
789
766
  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];
767
+ if (this._enableMentionPrefix && mentionRegex.test(content)) {
768
+ matchedPrefix = content.match(mentionRegex)[0];
793
769
  isCommand = true;
794
770
  } else {
795
771
  const sortedPrefs = [...this._prefixes].sort((a, b) => b.length - a.length);
772
+ if (sortedPrefs.includes("")) {
773
+ isCommand = true;
774
+ }
796
775
  for (const p of sortedPrefs) {
797
- if (content2.startsWith(p)) {
776
+ if (p !== "" && content.startsWith(p)) {
798
777
  matchedPrefix = p;
799
778
  isCommand = true;
800
779
  break;
801
780
  }
802
781
  }
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
782
  }
809
783
  if (!isCommand) return;
810
- const args2 = content2.slice(matchedPrefix.length).trim().split(/ +/g);
784
+ const args2 = content.slice(matchedPrefix.length).trim().split(/ +/g);
811
785
  const commandName = args2.shift()?.toLowerCase();
812
786
  if (!commandName) return;
813
787
  let command2 = this.commands.get(commandName);
@@ -815,11 +789,35 @@ var DJSNextClient = class extends Client {
815
789
  command2 = this.commands.find((c) => c.aliases?.includes(commandName) || false);
816
790
  }
817
791
  if (!command2 || !command2.executeText) return;
818
- if (!await this.handlePreconditions(command2, message2, commandName)) return;
792
+ if (command2.developerOnly && !this._developers.includes(message2.author.id)) return;
793
+ if (command2.guildOnly && !message2.guild) return;
794
+ if (command2.userPermissions && message2.member?.permissions) {
795
+ const missing = message2.member.permissions.missing(command2.userPermissions);
796
+ if (missing.length > 0) return;
797
+ }
798
+ if (command2.botPermissions && message2.guild?.members.me?.permissions) {
799
+ const missing = message2.guild.members.me.permissions.missing(command2.botPermissions);
800
+ if (missing.length > 0) return;
801
+ }
802
+ if (command2.cooldown) {
803
+ if (!this.cooldowns.has(commandName)) this.cooldowns.set(commandName, new Collection3());
804
+ const now = Date.now();
805
+ const timestamps = this.cooldowns.get(commandName);
806
+ const cooldownAmount = command2.cooldown * 1e3;
807
+ if (timestamps.has(message2.author.id)) {
808
+ const expirationTime = timestamps.get(message2.author.id) + cooldownAmount;
809
+ if (now < expirationTime) {
810
+ return void await message2.reply(`Please wait, you are on a cooldown. You can use it again <t:${Math.round(expirationTime / 1e3)}:R>.`);
811
+ }
812
+ }
813
+ timestamps.set(message2.author.id, now);
814
+ setTimeout(() => timestamps.delete(message2.author.id), cooldownAmount);
815
+ }
819
816
  try {
820
817
  await command2.executeText(message2, args2, this);
821
818
  } catch (error) {
822
- await this.handleCommandError(error, commandName, message2);
819
+ console.error(`[djs-next] Error executing text command: "${commandName}"`, error);
820
+ await message2.reply("We ran into an internal error executing this command.").catch(() => null);
823
821
  }
824
822
  });
825
823
  }
@@ -827,12 +825,12 @@ var DJSNextClient = class extends Client {
827
825
  if (!token) throw new Error("[djs-next] A token must be provided to start the bot.");
828
826
  this.config = await loadConfig();
829
827
  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);
828
+ if (!this._commandsDir && this.config.directories?.commands) this._commandsDir = path6.resolve(process.cwd(), this.config.directories.commands);
829
+ if (!this._eventsDir && this.config.directories?.events) this._eventsDir = path6.resolve(process.cwd(), this.config.directories.events);
830
+ if (!this._componentsDir && this.config.directories?.components) this._componentsDir = path6.resolve(process.cwd(), this.config.directories.components);
831
+ if (!this._tasksDir && this.config.directories?.tasks) this._tasksDir = path6.resolve(process.cwd(), this.config.directories.tasks);
832
+ if (!this._localesDir && this.config.directories?.locales) this._localesDir = path6.resolve(process.cwd(), this.config.directories.locales);
833
+ if (this._localesDir) loadLocales(this._localesDir, this.config.defaultLocale);
836
834
  if (!this._middleware) {
837
835
  const exts = [".js", ".mjs", ".cjs", ".ts", ".mts", ".cts"];
838
836
  const cwd = process.cwd();
@@ -852,24 +850,24 @@ var DJSNextClient = class extends Client {
852
850
  }
853
851
  }
854
852
  }
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;
853
+ if (this._eventsDir) await loadEvents(this, this._eventsDir);
854
+ if (this._componentsDir) this.components = await loadComponents(this._componentsDir);
855
+ if (this._tasksDir) await loadTasks(this, this._tasksDir);
856
+ if (this._commandsDir) {
857
+ if (!this._clientId) throw new Error("[djs-next] You must provide a clientId to deploy commands.");
862
858
  this.commands = await loadAndDeployCommands(this._commandsDir, token, this._clientId, this._guildId);
863
859
  }
860
+ await this.login(token);
861
+ console.log(`[djs-next] Bot is ready and logged in as ${this.user?.tag}!`);
864
862
  }
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}`);
863
+ enableDevTools(prefix2 = "dnxt") {
864
+ if (prefix2 !== "dnxt" && prefix2 !== "nxt") {
865
+ throw new Error(`[djs-next] Developer Tools prefix must be either 'dnxt' or 'nxt'. Received: ${prefix2}`);
868
866
  }
869
867
  this.on("messageCreate", async (message2) => {
870
- await handleDNXT(message2, this, prefix);
868
+ await handleDNXT(message2, this, prefix2);
871
869
  });
872
- console.log(`[djs-next] \u{1F6E0}\uFE0F Developer Tools enabled. Use "${prefix}" in chat. Ensure MessageContent intent is enabled!`);
870
+ console.log(`[djs-next] \u{1F6E0}\uFE0F Developer Tools enabled. Use "${prefix2}" in chat. Ensure MessageContent intent is enabled!`);
873
871
  }
874
872
  async enableHMR() {
875
873
  try {
@@ -899,157 +897,6 @@ var DJSNextClient = class extends Client {
899
897
  console.warn(`[djs-next] chokidar not installed. HMR is disabled. Please run "npm install chokidar" to use this feature.`);
900
898
  }
901
899
  }
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
900
  };
1054
901
 
1055
902
  // src/utils/paginate.ts
@@ -1058,38 +905,23 @@ import {
1058
905
  ButtonBuilder,
1059
906
  ButtonStyle
1060
907
  } 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
- }
908
+ async function paginate(interaction, pages, time = 6e4) {
909
+ if (!interaction.deferred && !interaction.replied) {
910
+ await interaction.deferReply();
1067
911
  }
1068
912
  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
- }
913
+ return interaction.editReply({ embeds: [pages[0]], components: [] });
1074
914
  }
1075
915
  let index = 0;
1076
916
  const prevButton = new ButtonBuilder().setCustomId("djs_prev").setLabel("Previous").setStyle(ButtonStyle.Primary).setDisabled(true);
1077
917
  const nextButton = new ButtonBuilder().setCustomId("djs_next").setLabel("Next").setStyle(ButtonStyle.Primary);
1078
918
  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
- }
919
+ const message2 = await interaction.editReply({
920
+ embeds: [pages[index]],
921
+ components: [row]
922
+ });
1091
923
  const collector = message2.createMessageComponentCollector({
1092
- filter: (i) => i.user.id === (isMessage ? context.author.id : context.user.id),
924
+ filter: (i) => i.user.id === interaction.user.id,
1093
925
  time
1094
926
  });
1095
927
  collector.on("collect", async (i) => {
@@ -1108,147 +940,17 @@ async function paginate(context, pages, time = 6e4) {
1108
940
  collector.on("end", async () => {
1109
941
  prevButton.setDisabled(true);
1110
942
  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
943
+ await interaction.editReply({
944
+ components: [new ActionRowBuilder().addComponents(prevButton, nextButton)]
945
+ }).catch(() => {
1152
946
  });
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
- }
947
+ });
1167
948
  }
1168
949
 
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
950
  // src/index.ts
1247
951
  export * from "discord.js";
1248
952
  export {
1249
953
  DJSNextClient,
1250
- PaginationBuilder,
1251
- confirmPrompt,
1252
954
  defineConfig,
1253
955
  getLocalesCache,
1254
956
  loadConfig,