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.js CHANGED
@@ -32,8 +32,6 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
32
32
  var index_exports = {};
33
33
  __export(index_exports, {
34
34
  DJSNextClient: () => DJSNextClient,
35
- PaginationBuilder: () => PaginationBuilder,
36
- confirmPrompt: () => confirmPrompt,
37
35
  defineConfig: () => defineConfig,
38
36
  getLocalesCache: () => getLocalesCache,
39
37
  loadConfig: () => loadConfig,
@@ -42,10 +40,9 @@ __export(index_exports, {
42
40
  translate: () => translate
43
41
  });
44
42
  module.exports = __toCommonJS(index_exports);
45
- var import_config = require("dotenv/config");
46
43
 
47
44
  // src/client.ts
48
- var import_discord4 = require("discord.js");
45
+ var import_discord3 = require("discord.js");
49
46
 
50
47
  // src/handlers/commandHandler.ts
51
48
  var import_discord = require("discord.js");
@@ -291,9 +288,9 @@ function loadLocales(localesDir, defaultLocale) {
291
288
  for (const file of files) {
292
289
  if (file.endsWith(".json")) {
293
290
  const lang = file.replace(".json", "");
294
- const content2 = import_fs7.default.readFileSync(import_path5.default.join(localesDir, file), "utf8");
291
+ const content = import_fs7.default.readFileSync(import_path5.default.join(localesDir, file), "utf8");
295
292
  try {
296
- localesCache[lang] = JSON.parse(content2);
293
+ localesCache[lang] = JSON.parse(content);
297
294
  } catch (e) {
298
295
  console.error(`[djs-next] Failed to parse locale file: ${file}`, e);
299
296
  }
@@ -327,92 +324,26 @@ function getLocalesCache() {
327
324
  }
328
325
 
329
326
  // src/plugins/dnxt.ts
330
- var import_discord3 = require("discord.js");
331
327
  var import_child_process = require("child_process");
332
328
  var import_util = __toESM(require("util"));
333
329
  var import_os = __toESM(require("os"));
334
330
  var execAsync = import_util.default.promisify(import_child_process.exec);
335
- function buildDisplayMessage(content2, color = 5397233) {
336
- const djs = require("discord.js");
337
- const container = new djs.ContainerBuilder().setAccentColor(color).addTextDisplayComponents(
338
- new djs.TextDisplayBuilder().setContent(content2)
339
- );
340
- return { components: [container], flags: 32768 };
341
- }
342
- async function handleDNXT(message, client, devPrefix) {
331
+ async function handleDNXT(message, client, prefix = "dnxt") {
343
332
  if (message.author.bot) return;
344
- if (!client._developers.includes(message.author.id)) return;
345
- if (client.config?.devGuildId && message.guildId !== client.config.devGuildId) return;
346
- const originalReply = message.reply.bind(message);
347
- message.reply = (async (content2) => {
348
- if (typeof content2 === "string") {
349
- return await originalReply({ ...buildDisplayMessage(content2), allowedMentions: { repliedUser: false } });
350
- }
351
- if (!content2.allowedMentions) content2.allowedMentions = { repliedUser: false };
352
- return await originalReply(content2);
353
- });
354
- const content = message.content.trim();
355
- const validTriggers = [devPrefix];
356
- const clientPrefixes = client._prefixes || [];
357
- for (const p of clientPrefixes) {
358
- if (p !== "") validTriggers.push(`${p}${devPrefix}`);
359
- }
360
- let matchedTrigger = validTriggers.find((t) => content === t || content.startsWith(`${t} `));
361
- if (!matchedTrigger) return;
362
- const args = content.slice(matchedTrigger.length).trim().split(/ +/g);
333
+ if (!client["_developers"].includes(message.author.id)) return;
334
+ if (!message.content.startsWith(prefix)) return;
335
+ const args = message.content.slice(prefix.length).trim().split(/ +/);
363
336
  const command = args.shift()?.toLowerCase();
364
- if (command === "help") {
365
- const djs = require("discord.js");
366
- const container = new djs.ContainerBuilder().setAccentColor(5397233).addTextDisplayComponents(
367
- new djs.TextDisplayBuilder().setContent(`# \u{1F4D6} DNXT Toolkit Reference
368
- > Current prefix trigger: \`${matchedTrigger}\``)
369
- ).addSeparatorComponents(new djs.SeparatorBuilder()).addTextDisplayComponents(
370
- new djs.TextDisplayBuilder().setContent(`### \u{1F4CA} Core Framework
371
- - \`${matchedTrigger}\` \u2014 Developer system dashboard
372
- - \`${matchedTrigger} help\` \u2014 Shows this reference menu`),
373
- new djs.TextDisplayBuilder().setContent(`### \u{1F4BB} Execution & Diagnostics
374
- - \`${matchedTrigger} js <code>\` \u2014 Evaluates raw JS code
375
- - \`${matchedTrigger} sh <cmd>\` \u2014 Runs terminal shell script
376
- - \`${matchedTrigger} debug <code>\` \u2014 Evaluates JS with precise memory deltas`),
377
- new djs.TextDisplayBuilder().setContent(`### \u{1F4C2} File System & Network
378
- - \`${matchedTrigger} cat <file>\` \u2014 Reads file contents
379
- - \`${matchedTrigger} curl <url>\` \u2014 Fetches remote URL data
380
- - \`${matchedTrigger} git <cmd>\` \u2014 Executes git repository commands`),
381
- new djs.TextDisplayBuilder().setContent(`### \u{1F9F0} Utilities
382
- - \`${matchedTrigger} <load|unload|reload> <target>\` \u2014 Manages system modules
383
- - \`${matchedTrigger} sync\` \u2014 Forces global slash command sync
384
- - \`${matchedTrigger} in <channel> <cmd>\` \u2014 Executes command in target channel
385
- - \`${matchedTrigger} restart\` \u2014 Restarts the bot completely
386
- - \`${matchedTrigger} shutdown\` \u2014 Stops the bot completely`)
387
- );
388
- await message.reply({ components: [container], flags: 32768, allowedMentions: { repliedUser: false } });
389
- return;
390
- }
391
337
  if (!command) {
392
338
  const mem = process.memoryUsage();
339
+ const discordJsVersion = require("discord.js/package.json").version;
393
340
  const botPing = client.ws.ping;
394
- const djs = require("discord.js");
395
- const container = new djs.ContainerBuilder().setAccentColor(5397233).addTextDisplayComponents(
396
- new djs.TextDisplayBuilder().setContent(`# \u{1F6E0}\uFE0F Developer System Dashboard
397
- > **DNXT Framework Engine**`)
398
- ).addSeparatorComponents(new djs.SeparatorBuilder()).addTextDisplayComponents(
399
- new djs.TextDisplayBuilder().setContent(`### \u{1F4E1} Network Status
400
- - **System Uptime:** <t:${Math.floor((Date.now() - client.uptime) / 1e3)}:R>
401
- - **WebSocket Latency:** \`${botPing}ms\``),
402
- new djs.TextDisplayBuilder().setContent(`### \u{1F4E6} Host Environment
403
- - **Discord.js Library:** \`v${import_discord3.version}\`
404
- - **Node.js Runtime:** \`${process.version}\`
405
- - **Operating System:** \`${import_os.default.type()}\` (\`${import_os.default.cpus().length}\` thread cores, \`${(import_os.default.uptime() / 60 / 60).toFixed(2)}\` hrs uptime)`),
406
- new djs.TextDisplayBuilder().setContent(`### \u{1F9E0} Resource Utilization
407
- - **Physical Memory:** \`${(mem.rss / 1024 / 1024).toFixed(2)} MB\`
408
- - **Heap Allocated:** \`${(mem.heapUsed / 1024 / 1024).toFixed(2)} MB\``)
409
- );
410
- await message.reply({
411
- components: [container],
412
- flags: 32768,
413
- // MessageFlags.IsComponentsV2
414
- allowedMentions: { repliedUser: false }
415
- });
341
+ const text = `Module was loaded <t:${Math.floor((Date.now() - client.uptime) / 1e3)}:R>.
342
+ DNXT framework plugin, discord.js \`${discordJsVersion}\`, \`Node.js ${process.version}\` on \`${import_os.default.type()}\`.
343
+ Latencies: \`${botPing}ms\` websocket ping.
344
+ Memory: \`${(mem.rss / 1024 / 1024).toFixed(2)} MB\` physical, \`${(mem.heapUsed / 1024 / 1024).toFixed(2)} MB\` heap.
345
+ System: \`${import_os.default.cpus().length}\` thread(s), \`${(import_os.default.uptime() / 60 / 60).toFixed(2)}\` hrs system uptime.`;
346
+ await message.reply(text);
416
347
  return;
417
348
  }
418
349
  if (command === "js" || command === "eval" || command === "py") {
@@ -426,12 +357,12 @@ async function handleDNXT(message, client, devPrefix) {
426
357
  let evaled = await eval(`(async () => { ${code} })()`);
427
358
  const end = process.hrtime.bigint();
428
359
  const timeMs = Number(end - start) / 1e6;
429
- if (typeof evaled !== "string") evaled = import_util.default.inspect(evaled, { depth: 1, colors: true });
360
+ if (typeof evaled !== "string") evaled = import_util.default.inspect(evaled, { depth: 1 });
430
361
  await sendPaginatedText(message, `\u2705 **Evaluated in ${timeMs.toFixed(3)}ms**
431
- `, evaled, "ansi");
362
+ `, evaled, "js");
432
363
  } catch (err) {
433
364
  await sendPaginatedText(message, `\u274C **Evaluation Error**
434
- `, err.message, "ansi");
365
+ `, err.message, "js");
435
366
  }
436
367
  return;
437
368
  }
@@ -440,74 +371,52 @@ async function handleDNXT(message, client, devPrefix) {
440
371
  if (!cmd) return void await message.reply("\u274C Please provide a command to execute.");
441
372
  try {
442
373
  const start2 = process.hrtime.bigint();
443
- let stdout = "", stderr = "", code2 = 0;
444
- try {
445
- const result = await execAsync(cmd);
446
- stdout = result.stdout;
447
- stderr = result.stderr;
448
- } catch (err) {
449
- stdout = err.stdout || "";
450
- stderr = err.stderr || err.message || "";
451
- code2 = err.code || 1;
452
- }
374
+ const { stdout, stderr } = await execAsync(cmd);
453
375
  const end2 = process.hrtime.bigint();
454
376
  const timeMs2 = Number(end2 - start2) / 1e6;
455
- let resultText = `$ ${cmd}
456
- `;
457
- if (stdout) resultText += `${stdout}
458
- `;
459
- if (stderr) resultText += `${stderr}
460
- `;
461
- resultText += `
462
- [status] Return code ${code2}`;
377
+ const result = stdout || stderr || "No output.";
463
378
  await sendPaginatedText(message, `\u2705 **Executed in ${timeMs2.toFixed(3)}ms**
464
- `, resultText, "ansi");
379
+ `, result, "sh");
465
380
  } catch (err) {
466
381
  await sendPaginatedText(message, `\u274C **Shell Error**
467
- `, err.message, "ansi");
382
+ `, err.message, "sh");
468
383
  }
469
384
  return;
470
385
  }
471
- if (command === "load" || command === "unload" || command === "reload") {
386
+ if (command === "reload" || command === "load") {
472
387
  const target = args[0]?.toLowerCase();
473
388
  try {
474
389
  if (target === "commands" && client["_commandsDir"]) {
475
- if (command === "unload" || command === "reload") client.commands.clear();
476
- if (command === "load" || command === "reload") client.commands = await loadAndDeployCommands(client["_commandsDir"], client.token, client["_clientId"], client["_guildId"]);
477
- await message.reply(`\u2705 Successfully ${command}ed commands.`);
390
+ client.commands.clear();
391
+ client.commands = await loadAndDeployCommands(client["_commandsDir"], client.token, client["_clientId"], client["_guildId"]);
392
+ await message.reply("\u2705 Reloaded commands.");
478
393
  } else if (target === "events" && client["_eventsDir"]) {
479
- if (command === "unload" || command === "reload") {
480
- client.removeAllListeners();
481
- client["attachCoreListeners"]();
482
- }
483
- if (command === "load" || command === "reload") await loadEvents(client, client["_eventsDir"]);
484
- await message.reply(`\u2705 Successfully ${command}ed events.`);
394
+ client.removeAllListeners();
395
+ client["attachCoreListeners"]();
396
+ await loadEvents(client, client["_eventsDir"]);
397
+ await message.reply("\u2705 Reloaded events.");
485
398
  } else if (target === "components" && client["_componentsDir"]) {
486
- if (command === "unload" || command === "reload") client.components.clear();
487
- if (command === "load" || command === "reload") client.components = await loadComponents(client["_componentsDir"]);
488
- await message.reply(`\u2705 Successfully ${command}ed components.`);
399
+ client.components.clear();
400
+ client.components = await loadComponents(client["_componentsDir"]);
401
+ await message.reply("\u2705 Reloaded components.");
489
402
  } else if (target === "locales" && client["_localesDir"]) {
490
- if (command === "load" || command === "reload") loadLocales(client["_localesDir"], client.config.defaultLocale);
491
- await message.reply(`\u2705 Successfully ${command}ed locales.`);
403
+ loadLocales(client["_localesDir"], client.config.defaultLocale);
404
+ await message.reply("\u2705 Reloaded locales.");
492
405
  } else if (target === "all" || !target) {
493
- if (command === "unload" || command === "reload") {
494
- client.removeAllListeners();
495
- client["attachCoreListeners"]();
496
- client.commands.clear();
497
- client.components.clear();
498
- }
499
- if (command === "load" || command === "reload") {
500
- if (client["_eventsDir"]) await loadEvents(client, client["_eventsDir"]);
501
- if (client["_componentsDir"]) client.components = await loadComponents(client["_componentsDir"]);
502
- if (client["_localesDir"]) loadLocales(client["_localesDir"], client.config.defaultLocale);
503
- if (client["_commandsDir"]) client.commands = await loadAndDeployCommands(client["_commandsDir"], client.token, client["_clientId"], client["_guildId"]);
504
- }
505
- await message.reply(`\u2705 Successfully ${command}ed all framework modules.`);
406
+ client.removeAllListeners();
407
+ client["attachCoreListeners"]();
408
+ client.commands.clear();
409
+ client.components.clear();
410
+ if (client["_eventsDir"]) await loadEvents(client, client["_eventsDir"]);
411
+ if (client["_componentsDir"]) client.components = await loadComponents(client["_componentsDir"]);
412
+ if (client["_localesDir"]) loadLocales(client["_localesDir"], client.config.defaultLocale);
413
+ if (client["_commandsDir"]) client.commands = await loadAndDeployCommands(client["_commandsDir"], client.token, client["_clientId"], client["_guildId"]);
414
+ await message.reply("\u2705 Reloaded all framework modules.");
506
415
  } else {
507
416
  await message.reply("\u274C Unknown target. Valid targets: `commands, events, components, locales, all`");
508
417
  }
509
418
  } catch (err) {
510
- await message.reply(`\u274C **${command.toUpperCase()} Error:** ${err.message}`);
419
+ await message.reply(`\u274C **Reload Error:** ${err.message}`);
511
420
  }
512
421
  return;
513
422
  }
@@ -517,14 +426,49 @@ async function handleDNXT(message, client, devPrefix) {
517
426
  const file = args.join(" ");
518
427
  if (!file) return void await message.reply("\u274C Please provide a file to read.");
519
428
  try {
520
- const content2 = fs9.readFileSync(path7.resolve(process.cwd(), file), "utf8");
429
+ const content = fs9.readFileSync(path7.resolve(process.cwd(), file), "utf8");
521
430
  await sendPaginatedText(message, `\u{1F4C4} **${file}**
522
- `, content2, file.split(".").pop() || "");
431
+ `, content, file.split(".").pop() || "");
523
432
  } catch (e) {
524
433
  await message.reply(`\u274C **Error reading file:** ${e.message}`);
525
434
  }
526
435
  return;
527
436
  }
437
+ if (command === "su" || command === "sudo") {
438
+ const targetUserId = args.shift();
439
+ const cmd = args.join(" ");
440
+ if (!targetUserId || !cmd) return void await message.reply(`\u274C Usage: ${prefix} su <user_id> <command>`);
441
+ try {
442
+ const targetUser = await client.users.fetch(targetUserId.replace(/<@!?|>/g, ""));
443
+ if (!targetUser) throw new Error("User not found.");
444
+ const mockMessage = Object.assign(Object.create(Object.getPrototypeOf(message)), message);
445
+ mockMessage.author = targetUser;
446
+ if (message.guild) {
447
+ mockMessage.member = await message.guild.members.fetch(targetUser.id).catch(() => null);
448
+ }
449
+ mockMessage.content = cmd;
450
+ client.emit("messageCreate", mockMessage);
451
+ await message.reply(`\u2705 Invoked \`${cmd}\` as **${targetUser.tag}**.`);
452
+ } catch (e) {
453
+ await message.reply(`\u274C **Sudo Error:** ${e.message}`);
454
+ }
455
+ return;
456
+ }
457
+ if (command === "source" || command === "src") {
458
+ const target = args.join(" ");
459
+ if (!target) return void await message.reply("\u274C Please provide a command name.");
460
+ const cmdData = client.commands.get(target);
461
+ if (!cmdData || !cmdData.filepath) return void await message.reply("\u274C Command not found or has no associated filepath.");
462
+ try {
463
+ const fs9 = await import("fs");
464
+ const content = fs9.readFileSync(cmdData.filepath, "utf8");
465
+ await sendPaginatedText(message, `\u{1F4C4} **Source of \`${target}\`**
466
+ `, content, cmdData.filepath.split(".").pop() || "");
467
+ } catch (e) {
468
+ await message.reply(`\u274C **Error reading source:** ${e.message}`);
469
+ }
470
+ return;
471
+ }
528
472
  if (command === "curl") {
529
473
  const url = args[0];
530
474
  if (!url) return void await message.reply("\u274C Please provide a URL.");
@@ -552,38 +496,64 @@ async function handleDNXT(message, client, devPrefix) {
552
496
  const endMem = process.memoryUsage().heapUsed;
553
497
  const timeMs = Number(end - start) / 1e6;
554
498
  const memDiff = (endMem - startMem) / 1024 / 1024;
555
- if (typeof evaled !== "string") evaled = import_util.default.inspect(evaled, { depth: 1, colors: true });
499
+ if (typeof evaled !== "string") evaled = import_util.default.inspect(evaled, { depth: 1 });
556
500
  await sendPaginatedText(message, `\u23F1\uFE0F **Debug Execution**
557
501
  Time: \`${timeMs.toFixed(3)}ms\` | Heap Delta: \`${memDiff.toFixed(3)}MB\`
558
- `, evaled, "ansi");
502
+ `, evaled, "js");
559
503
  } catch (err) {
560
504
  await sendPaginatedText(message, `\u274C **Debug Error**
561
- `, err.message, "ansi");
505
+ `, err.message, "js");
562
506
  }
563
507
  return;
564
508
  }
565
509
  if (command === "in") {
566
510
  const channelId = args.shift()?.replace(/<#|>/g, "");
567
511
  const cmd = args.join(" ");
568
- if (!channelId || !cmd) return void await message.reply(`\u274C Usage: ${matchedTrigger} in <#channel|id> <command>`);
512
+ if (!channelId || !cmd) return void await message.reply(`\u274C Usage: ${prefix} in <channel> <command>`);
569
513
  try {
570
514
  const targetChannel = await client.channels.fetch(channelId);
571
515
  if (!targetChannel || !targetChannel.isTextBased()) throw new Error("Invalid Text Channel.");
572
516
  const mockMessage = Object.assign(Object.create(Object.getPrototypeOf(message)), message);
573
- Object.defineProperty(mockMessage, "client", { value: client, configurable: true });
574
- if (message.guild) {
575
- Object.defineProperty(mockMessage, "guild", { value: message.guild, configurable: true });
576
- Object.defineProperty(mockMessage, "guildId", { value: message.guildId, configurable: true });
577
- }
578
- Object.defineProperty(mockMessage, "channel", { value: targetChannel, configurable: true });
579
- Object.defineProperty(mockMessage, "channelId", { value: targetChannel.id, configurable: true });
580
- Object.defineProperty(mockMessage, "content", { value: cmd, configurable: true });
517
+ mockMessage.channel = targetChannel;
518
+ mockMessage.channelId = targetChannel.id;
519
+ mockMessage.content = cmd;
581
520
  client.emit("messageCreate", mockMessage);
521
+ await message.reply(`\u2705 Redirected execution to <#${targetChannel.id}>.`);
582
522
  } catch (e) {
583
523
  await message.reply(`\u274C **In Error:** ${e.message}`);
584
524
  }
585
525
  return;
586
526
  }
527
+ if (command === "tasks") {
528
+ const tasks = client._activeTasks;
529
+ if (!tasks || tasks.size === 0) return void await message.reply("No active background tasks running.");
530
+ let text = `\u2699\uFE0F **Active Background Tasks (${tasks.size})**
531
+ `;
532
+ for (const [name] of tasks.entries()) {
533
+ text += `- \`${name.split("/").pop()}\`
534
+ `;
535
+ }
536
+ await sendPaginatedText(message, "", text, "");
537
+ return;
538
+ }
539
+ if (command === "cancel") {
540
+ const target = args.join(" ");
541
+ if (!target) return void await message.reply(`\u274C Usage: ${prefix} cancel <task_name>`);
542
+ const tasks = client._activeTasks;
543
+ if (!tasks) return void await message.reply("No active tasks to cancel.");
544
+ let found = false;
545
+ for (const [name, intervalId] of tasks.entries()) {
546
+ if (name.includes(target)) {
547
+ clearInterval(intervalId);
548
+ tasks.delete(name);
549
+ found = true;
550
+ await message.reply(`\u2705 Cancelled background task: \`${name.split("/").pop()}\``);
551
+ break;
552
+ }
553
+ }
554
+ if (!found) await message.reply("\u274C Task not found.");
555
+ return;
556
+ }
587
557
  if (command === "sync") {
588
558
  try {
589
559
  await message.reply("\u{1F504} Force syncing slash commands...");
@@ -594,107 +564,85 @@ Time: \`${timeMs.toFixed(3)}ms\` | Heap Delta: \`${memDiff.toFixed(3)}MB\`
594
564
  }
595
565
  return;
596
566
  }
597
- if (command === "restart") {
598
- await message.reply("\u{1F504} Restarting framework...");
599
- client.destroy();
600
- const { spawn } = require("child_process");
601
- const child = spawn(process.argv[0], process.argv.slice(1), {
602
- detached: true,
603
- stdio: "ignore",
604
- cwd: process.cwd()
605
- });
606
- child.unref();
607
- process.exit(0);
567
+ if (command === "sql") {
568
+ const query = args.join(" ");
569
+ if (!query) return void await message.reply(`\u274C Usage: ${prefix} sql <query>`);
570
+ try {
571
+ let res;
572
+ if (client.db && typeof client.db.$queryRawUnsafe === "function") {
573
+ res = await client.db.$queryRawUnsafe(query);
574
+ } else if (client.db && typeof client.db.query === "function") {
575
+ res = await client.db.query(query);
576
+ } else {
577
+ return void await message.reply("\u274C Your configured `client.db` does not expose a recognized raw SQL execution method (`$queryRawUnsafe` or `query`).");
578
+ }
579
+ const inspect = import_util.default.inspect(res, { depth: 2 });
580
+ await sendPaginatedText(message, `\u{1F5C4}\uFE0F **SQL Query**
581
+ `, inspect, "js");
582
+ } catch (e) {
583
+ await message.reply(`\u274C **SQL Error:** ${e.message}`);
584
+ }
608
585
  return;
609
586
  }
610
- if (command === "shutdown" || command === "stop") {
611
- await message.reply("\u{1F6D1} Shutting down framework...");
612
- client.destroy();
613
- process.exit(0);
587
+ if (command === "vc" || command === "voice") {
588
+ if (!message.guild) return void await message.reply("\u274C This command must be used in a server.");
589
+ const me = message.guild.members.me;
590
+ if (!me?.voice?.channel) return void await message.reply("\u274C Bot is not currently in a voice channel.");
591
+ const text = `\u{1F399}\uFE0F **Voice Debugger**
592
+ Channel: <#${me.voice.channel.id}> (\`${me.voice.channel.id}\`)
593
+ Muted: ${me.voice.mute} | Deafened: ${me.voice.deaf}
594
+ Session ID: \`${me.voice.sessionId || "None"}\``;
595
+ await message.reply(text);
614
596
  return;
615
597
  }
616
- await message.reply(`\u2753 Unknown ${matchedTrigger} command. Available: \`js, sh, git, cat, curl, in, debug, reload, sync, restart, shutdown\``);
598
+ await message.reply(`\u2753 Unknown ${prefix} command. Available: \`js, sh, git, cat, curl, su, in, source, debug, reload, tasks, cancel, sync, sql, vc\``);
617
599
  }
618
- async function sendPaginatedText(message2, header, content2, language = "") {
619
- const maxLength = 800;
620
- if (content2.length <= maxLength) {
621
- await message2.reply(buildDisplayMessage(`### ${header.replace(/\\*\\*/g, "")}
622
- \`\`\`${language}
623
- ${content2}
624
- \`\`\``));
600
+ async function sendPaginatedText(message2, header, content, language = "") {
601
+ const maxLength = 1900;
602
+ if (content.length <= maxLength) {
603
+ await message2.reply(`${header}\`\`\`${language}
604
+ ${content}
605
+ \`\`\``);
625
606
  return;
626
607
  }
627
608
  const chunks = [];
628
- for (let i = 0; i < content2.length; i += maxLength) {
629
- chunks.push(content2.substring(i, i + maxLength));
609
+ for (let i = 0; i < content.length; i += maxLength) {
610
+ chunks.push(content.substring(i, i + maxLength));
630
611
  }
631
612
  let index = 0;
632
- const djs = require("discord.js");
633
- function buildPage(idx) {
634
- const text = `### ${header.replace(/\\*\\*/g, "")}
635
- \`\`\`${language}
636
- ${chunks[idx]}
613
+ const reply = await message2.reply(`${header}\`\`\`${language}
614
+ ${chunks[index]}
637
615
  \`\`\`
638
- > *Page ${idx + 1} of ${chunks.length}*`;
639
- const container = new djs.ContainerBuilder().setAccentColor(5397233).addTextDisplayComponents(
640
- new djs.TextDisplayBuilder().setContent(text)
641
- );
642
- const row1 = new djs.ActionRowBuilder().addComponents(
643
- new djs.ButtonBuilder().setCustomId("first").setLabel("\u226A").setStyle(2),
644
- new djs.ButtonBuilder().setCustomId("prev").setLabel("\uFF1C").setStyle(2),
645
- new djs.ButtonBuilder().setCustomId("goto").setLabel("\u2398").setStyle(1),
646
- new djs.ButtonBuilder().setCustomId("next").setLabel("\uFF1E").setStyle(2),
647
- new djs.ButtonBuilder().setCustomId("last").setLabel("\u226B").setStyle(2)
648
- );
649
- const row2 = new djs.ActionRowBuilder().addComponents(
650
- new djs.ButtonBuilder().setCustomId("stop").setLabel("\u2716 Close").setStyle(4)
651
- );
652
- container.addActionRowComponents(row1, row2);
653
- return { components: [container], flags: 32768 };
654
- }
655
- const reply = await message2.reply(buildPage(index));
656
- const collector = reply.createMessageComponentCollector({
657
- filter: (i) => ["first", "prev", "goto", "stop", "next", "last"].includes(i.customId) && i.user.id === message2.author.id,
616
+ *Page 1 of ${chunks.length}*`);
617
+ await reply.react("\u25C0\uFE0F");
618
+ await reply.react("\u25B6\uFE0F");
619
+ await reply.react("\u23F9\uFE0F");
620
+ const collector = reply.createReactionCollector({
621
+ filter: (reaction, user) => ["\u25C0\uFE0F", "\u25B6\uFE0F", "\u23F9\uFE0F"].includes(reaction.emoji.name) && user.id === message2.author.id,
658
622
  time: 12e4
659
623
  });
660
- collector.on("collect", async (i) => {
661
- if (i.customId === "first") {
662
- index = 0;
663
- } else if (i.customId === "prev") {
624
+ collector.on("collect", async (reaction, user) => {
625
+ await reaction.users.remove(user.id).catch(() => null);
626
+ if (reaction.emoji.name === "\u25C0\uFE0F") {
664
627
  index = index > 0 ? index - 1 : index;
665
- } else if (i.customId === "next") {
628
+ } else if (reaction.emoji.name === "\u25B6\uFE0F") {
666
629
  index = index < chunks.length - 1 ? index + 1 : index;
667
- } else if (i.customId === "last") {
668
- index = chunks.length - 1;
669
- } else if (i.customId === "goto") {
670
- const modal = new djs.ModalBuilder().setCustomId("goto_modal").setTitle("Go to Page");
671
- const input = new djs.TextInputBuilder().setCustomId("page_num").setLabel(`Page Number (1-${chunks.length})`).setStyle(1).setRequired(true);
672
- modal.addComponents(new djs.ActionRowBuilder().addComponents(input));
673
- await i.showModal(modal);
674
- try {
675
- const modalSubmit = await i.awaitModalSubmit({ filter: (mi) => mi.user.id === message2.author.id && mi.customId === "goto_modal", time: 6e4 });
676
- const targetPage = parseInt(modalSubmit.fields.getTextInputValue("page_num"), 10);
677
- if (!isNaN(targetPage) && targetPage >= 1 && targetPage <= chunks.length) {
678
- index = targetPage - 1;
679
- }
680
- await modalSubmit.update(buildPage(index));
681
- } catch {
682
- }
683
- return;
684
- } else if (i.customId === "stop") {
685
- await reply.delete().catch(() => null);
630
+ } else if (reaction.emoji.name === "\u23F9\uFE0F") {
686
631
  collector.stop();
687
632
  return;
688
633
  }
689
- await i.update(buildPage(index));
634
+ await reply.edit(`${header}\`\`\`${language}
635
+ ${chunks[index]}
636
+ \`\`\`
637
+ *Page ${index + 1} of ${chunks.length}*`);
690
638
  });
691
639
  collector.on("end", () => {
692
- reply.edit({ components: [] }).catch(() => null);
640
+ reply.reactions.removeAll().catch(() => null);
693
641
  });
694
642
  }
695
643
 
696
644
  // src/client.ts
697
- var DJSNextClient = class extends import_discord4.Client {
645
+ var DJSNextClient = class extends import_discord3.Client {
698
646
  commands;
699
647
  components;
700
648
  cooldowns;
@@ -711,15 +659,12 @@ var DJSNextClient = class extends import_discord4.Client {
711
659
  _developers;
712
660
  _middleware;
713
661
  _prefixes;
714
- _enableSlashCommands;
715
- _enableTextCommands;
716
662
  _enableMentionPrefix;
717
- _enableNoPrefix;
718
663
  constructor(options) {
719
664
  super(options);
720
- this.commands = new import_discord4.Collection();
721
- this.components = new import_discord4.Collection();
722
- this.cooldowns = new import_discord4.Collection();
665
+ this.commands = new import_discord3.Collection();
666
+ this.components = new import_discord3.Collection();
667
+ this.cooldowns = new import_discord3.Collection();
723
668
  this._commandsDir = options.commandsDir ? import_path6.default.resolve(process.cwd(), options.commandsDir) : void 0;
724
669
  this._eventsDir = options.eventsDir ? import_path6.default.resolve(process.cwd(), options.eventsDir) : void 0;
725
670
  this._componentsDir = options.componentsDir ? import_path6.default.resolve(process.cwd(), options.componentsDir) : void 0;
@@ -730,12 +675,7 @@ var DJSNextClient = class extends import_discord4.Client {
730
675
  this._middleware = options.middleware;
731
676
  const prefs = options.prefixes || [];
732
677
  this._prefixes = Array.isArray(prefs) ? prefs : [prefs];
733
- this._prefixes = this._prefixes.filter((p) => p !== "");
734
- this._enableSlashCommands = options.enableSlashCommands ?? true;
735
- this._enableTextCommands = options.enableTextCommands ?? true;
736
678
  this._enableMentionPrefix = options.enableMentionPrefix ?? true;
737
- this._enableNoPrefix = options.enableNoPrefix ?? false;
738
- if (options.db) this.db = options.db;
739
679
  this.attachCoreListeners();
740
680
  }
741
681
  attachCoreListeners() {
@@ -750,7 +690,6 @@ var DJSNextClient = class extends import_discord4.Client {
750
690
  }
751
691
  }
752
692
  if (interaction.isChatInputCommand()) {
753
- if (!this._enableSlashCommands) return;
754
693
  let commandKey = interaction.commandName;
755
694
  const group = interaction.options.getSubcommandGroup(false);
756
695
  const sub = interaction.options.getSubcommand(false);
@@ -758,11 +697,48 @@ var DJSNextClient = class extends import_discord4.Client {
758
697
  if (sub) commandKey += ` ${sub}`;
759
698
  const command2 = this.commands.get(commandKey);
760
699
  if (!command2 || !command2.execute) return;
761
- if (!await this.handlePreconditions(command2, interaction, commandKey)) return;
700
+ if (command2.developerOnly && !this._developers.includes(interaction.user.id)) {
701
+ return interaction.reply({ content: "Only developers can use this command.", ephemeral: true });
702
+ }
703
+ if (command2.guildOnly && !interaction.inGuild()) {
704
+ return interaction.reply({ content: "This command can only be used in a server.", ephemeral: true });
705
+ }
706
+ if (command2.userPermissions && interaction.memberPermissions) {
707
+ const missing = interaction.memberPermissions.missing(command2.userPermissions);
708
+ if (missing.length > 0) {
709
+ return interaction.reply({ content: `You are missing permissions: \`${missing.join(", ")}\``, ephemeral: true });
710
+ }
711
+ }
712
+ if (command2.botPermissions && interaction.guild?.members.me?.permissions) {
713
+ const missing = interaction.guild.members.me.permissions.missing(command2.botPermissions);
714
+ if (missing.length > 0) {
715
+ return interaction.reply({ content: `I am missing permissions to run this: \`${missing.join(", ")}\``, ephemeral: true });
716
+ }
717
+ }
718
+ if (command2.cooldown) {
719
+ if (!this.cooldowns.has(commandKey)) this.cooldowns.set(commandKey, new import_discord3.Collection());
720
+ const now = Date.now();
721
+ const timestamps = this.cooldowns.get(commandKey);
722
+ const cooldownAmount = command2.cooldown * 1e3;
723
+ if (timestamps.has(interaction.user.id)) {
724
+ const expirationTime = timestamps.get(interaction.user.id) + cooldownAmount;
725
+ if (now < expirationTime) {
726
+ return interaction.reply({
727
+ content: `Please wait, you are on a cooldown. You can use it again <t:${Math.round(expirationTime / 1e3)}:R>.`,
728
+ ephemeral: true
729
+ });
730
+ }
731
+ }
732
+ timestamps.set(interaction.user.id, now);
733
+ setTimeout(() => timestamps.delete(interaction.user.id), cooldownAmount);
734
+ }
762
735
  try {
763
736
  await command2.execute(interaction, this);
764
737
  } catch (error) {
765
- await this.handleCommandError(error, commandKey, interaction);
738
+ console.error(`[djs-next] Error executing command: "${commandKey}"`, error);
739
+ const msg = { content: "We ran into an internal error executing this command. The developers have been notified.", ephemeral: true };
740
+ if (interaction.replied || interaction.deferred) await interaction.followUp(msg).catch(() => null);
741
+ else await interaction.reply(msg).catch(() => null);
766
742
  }
767
743
  }
768
744
  if (interaction.isAutocomplete()) {
@@ -798,18 +774,19 @@ var DJSNextClient = class extends import_discord4.Client {
798
774
  }
799
775
  }
800
776
  if (component) {
801
- if (!await this.handlePreconditions(component, interaction, interaction.customId)) return;
802
777
  try {
803
778
  await component.execute(interaction, this, params);
804
779
  } catch (error) {
805
- await this.handleCommandError(error, interaction.customId, interaction);
780
+ console.error(`[djs-next] Error executing component: "${interaction.customId}"`, error);
781
+ const msg = { content: "We ran into an internal error executing this component.", ephemeral: true };
782
+ if (interaction.replied || interaction.deferred) await interaction.followUp(msg).catch(() => null);
783
+ else await interaction.reply(msg).catch(() => null);
806
784
  }
807
785
  }
808
786
  }
809
787
  });
810
788
  this.on("messageCreate", async (message2) => {
811
789
  if (message2.author.bot) return;
812
- if (!this._enableTextCommands) return;
813
790
  if (this._middleware) {
814
791
  try {
815
792
  const shouldContinue = await this._middleware(message2, this);
@@ -819,31 +796,28 @@ var DJSNextClient = class extends import_discord4.Client {
819
796
  return;
820
797
  }
821
798
  }
822
- let content2 = message2.content.trim();
799
+ let content = message2.content.trim();
823
800
  let matchedPrefix = "";
824
801
  let isCommand = false;
825
802
  const mentionRegex = new RegExp(`^<@!?${this.user?.id}>\\s*`);
826
- const canUseMention = this._enableMentionPrefix === true || Array.isArray(this._enableMentionPrefix) && this._enableMentionPrefix.includes(message2.author.id);
827
- if (canUseMention && mentionRegex.test(content2)) {
828
- matchedPrefix = content2.match(mentionRegex)[0];
803
+ if (this._enableMentionPrefix && mentionRegex.test(content)) {
804
+ matchedPrefix = content.match(mentionRegex)[0];
829
805
  isCommand = true;
830
806
  } else {
831
807
  const sortedPrefs = [...this._prefixes].sort((a, b) => b.length - a.length);
808
+ if (sortedPrefs.includes("")) {
809
+ isCommand = true;
810
+ }
832
811
  for (const p of sortedPrefs) {
833
- if (content2.startsWith(p)) {
812
+ if (p !== "" && content.startsWith(p)) {
834
813
  matchedPrefix = p;
835
814
  isCommand = true;
836
815
  break;
837
816
  }
838
817
  }
839
- const canUseNoPrefix = this._enableNoPrefix === true || Array.isArray(this._enableNoPrefix) && this._enableNoPrefix.includes(message2.author.id);
840
- if (!isCommand && canUseNoPrefix) {
841
- isCommand = true;
842
- matchedPrefix = "";
843
- }
844
818
  }
845
819
  if (!isCommand) return;
846
- const args2 = content2.slice(matchedPrefix.length).trim().split(/ +/g);
820
+ const args2 = content.slice(matchedPrefix.length).trim().split(/ +/g);
847
821
  const commandName = args2.shift()?.toLowerCase();
848
822
  if (!commandName) return;
849
823
  let command2 = this.commands.get(commandName);
@@ -851,11 +825,35 @@ var DJSNextClient = class extends import_discord4.Client {
851
825
  command2 = this.commands.find((c) => c.aliases?.includes(commandName) || false);
852
826
  }
853
827
  if (!command2 || !command2.executeText) return;
854
- if (!await this.handlePreconditions(command2, message2, commandName)) return;
828
+ if (command2.developerOnly && !this._developers.includes(message2.author.id)) return;
829
+ if (command2.guildOnly && !message2.guild) return;
830
+ if (command2.userPermissions && message2.member?.permissions) {
831
+ const missing = message2.member.permissions.missing(command2.userPermissions);
832
+ if (missing.length > 0) return;
833
+ }
834
+ if (command2.botPermissions && message2.guild?.members.me?.permissions) {
835
+ const missing = message2.guild.members.me.permissions.missing(command2.botPermissions);
836
+ if (missing.length > 0) return;
837
+ }
838
+ if (command2.cooldown) {
839
+ if (!this.cooldowns.has(commandName)) this.cooldowns.set(commandName, new import_discord3.Collection());
840
+ const now = Date.now();
841
+ const timestamps = this.cooldowns.get(commandName);
842
+ const cooldownAmount = command2.cooldown * 1e3;
843
+ if (timestamps.has(message2.author.id)) {
844
+ const expirationTime = timestamps.get(message2.author.id) + cooldownAmount;
845
+ if (now < expirationTime) {
846
+ return void await message2.reply(`Please wait, you are on a cooldown. You can use it again <t:${Math.round(expirationTime / 1e3)}:R>.`);
847
+ }
848
+ }
849
+ timestamps.set(message2.author.id, now);
850
+ setTimeout(() => timestamps.delete(message2.author.id), cooldownAmount);
851
+ }
855
852
  try {
856
853
  await command2.executeText(message2, args2, this);
857
854
  } catch (error) {
858
- await this.handleCommandError(error, commandName, message2);
855
+ console.error(`[djs-next] Error executing text command: "${commandName}"`, error);
856
+ await message2.reply("We ran into an internal error executing this command.").catch(() => null);
859
857
  }
860
858
  });
861
859
  }
@@ -863,12 +861,12 @@ var DJSNextClient = class extends import_discord4.Client {
863
861
  if (!token) throw new Error("[djs-next] A token must be provided to start the bot.");
864
862
  this.config = await loadConfig();
865
863
  this._guildId = this._guildId || this.config.devGuildId;
866
- if (!this._commandsDir) this._commandsDir = import_path6.default.resolve(process.cwd(), this.config.directories?.commands || "src/commands");
867
- if (!this._eventsDir) this._eventsDir = import_path6.default.resolve(process.cwd(), this.config.directories?.events || "src/events");
868
- if (!this._componentsDir) this._componentsDir = import_path6.default.resolve(process.cwd(), this.config.directories?.components || "src/components");
869
- if (!this._tasksDir) this._tasksDir = import_path6.default.resolve(process.cwd(), this.config.directories?.tasks || "src/tasks");
870
- if (!this._localesDir) this._localesDir = import_path6.default.resolve(process.cwd(), this.config.directories?.locales || "src/locales");
871
- if (import_fs8.default.existsSync(this._localesDir)) loadLocales(this._localesDir, this.config.defaultLocale);
864
+ if (!this._commandsDir && this.config.directories?.commands) this._commandsDir = import_path6.default.resolve(process.cwd(), this.config.directories.commands);
865
+ if (!this._eventsDir && this.config.directories?.events) this._eventsDir = import_path6.default.resolve(process.cwd(), this.config.directories.events);
866
+ if (!this._componentsDir && this.config.directories?.components) this._componentsDir = import_path6.default.resolve(process.cwd(), this.config.directories.components);
867
+ if (!this._tasksDir && this.config.directories?.tasks) this._tasksDir = import_path6.default.resolve(process.cwd(), this.config.directories.tasks);
868
+ if (!this._localesDir && this.config.directories?.locales) this._localesDir = import_path6.default.resolve(process.cwd(), this.config.directories.locales);
869
+ if (this._localesDir) loadLocales(this._localesDir, this.config.defaultLocale);
872
870
  if (!this._middleware) {
873
871
  const exts = [".js", ".mjs", ".cjs", ".ts", ".mts", ".cts"];
874
872
  const cwd = process.cwd();
@@ -888,24 +886,24 @@ var DJSNextClient = class extends import_discord4.Client {
888
886
  }
889
887
  }
890
888
  }
891
- if (import_fs8.default.existsSync(this._eventsDir)) await loadEvents(this, this._eventsDir);
892
- if (import_fs8.default.existsSync(this._componentsDir)) this.components = await loadComponents(this._componentsDir);
893
- if (import_fs8.default.existsSync(this._tasksDir)) await loadTasks(this, this._tasksDir);
894
- await this.login(token);
895
- console.log(`[djs-next] Bot is ready and logged in as ${this.user?.tag}!`);
896
- if (import_fs8.default.existsSync(this._commandsDir)) {
897
- this._clientId = this._clientId || this.user.id;
889
+ if (this._eventsDir) await loadEvents(this, this._eventsDir);
890
+ if (this._componentsDir) this.components = await loadComponents(this._componentsDir);
891
+ if (this._tasksDir) await loadTasks(this, this._tasksDir);
892
+ if (this._commandsDir) {
893
+ if (!this._clientId) throw new Error("[djs-next] You must provide a clientId to deploy commands.");
898
894
  this.commands = await loadAndDeployCommands(this._commandsDir, token, this._clientId, this._guildId);
899
895
  }
896
+ await this.login(token);
897
+ console.log(`[djs-next] Bot is ready and logged in as ${this.user?.tag}!`);
900
898
  }
901
- enableDevTools(prefix = "dnxt") {
902
- if (prefix !== "dnxt" && prefix !== "nxt") {
903
- throw new Error(`[djs-next] Developer Tools prefix must be either 'dnxt' or 'nxt'. Received: ${prefix}`);
899
+ enableDevTools(prefix2 = "dnxt") {
900
+ if (prefix2 !== "dnxt" && prefix2 !== "nxt") {
901
+ throw new Error(`[djs-next] Developer Tools prefix must be either 'dnxt' or 'nxt'. Received: ${prefix2}`);
904
902
  }
905
903
  this.on("messageCreate", async (message2) => {
906
- await handleDNXT(message2, this, prefix);
904
+ await handleDNXT(message2, this, prefix2);
907
905
  });
908
- console.log(`[djs-next] \u{1F6E0}\uFE0F Developer Tools enabled. Use "${prefix}" in chat. Ensure MessageContent intent is enabled!`);
906
+ console.log(`[djs-next] \u{1F6E0}\uFE0F Developer Tools enabled. Use "${prefix2}" in chat. Ensure MessageContent intent is enabled!`);
909
907
  }
910
908
  async enableHMR() {
911
909
  try {
@@ -935,193 +933,27 @@ var DJSNextClient = class extends import_discord4.Client {
935
933
  console.warn(`[djs-next] chokidar not installed. HMR is disabled. Please run "npm install chokidar" to use this feature.`);
936
934
  }
937
935
  }
938
- async handleCommandError(error, commandKey, context) {
939
- console.error(`[djs-next] Error executing command/component: "${commandKey}"`, error);
940
- const djs = require("discord.js");
941
- if (this.config.responses?.errorBoundary === null) {
942
- } else {
943
- try {
944
- const errorContent = this.config.responses?.errorBoundary || `### \u26A0\uFE0F Execution Error
945
- > The framework encountered a fatal error while executing \`${commandKey}\`.`;
946
- const codeBlock = `\`\`\`js
947
- ${String(error.stack || error.message).substring(0, 1500)}
948
- \`\`\``;
949
- if ("commandName" in context || "customId" in context) {
950
- const container = new djs.ContainerBuilder().setAccentColor(15548997).addTextDisplayComponents(new djs.TextDisplayBuilder().setContent(errorContent)).addSeparatorComponents(new djs.SeparatorBuilder()).addTextDisplayComponents(new djs.TextDisplayBuilder().setContent(codeBlock));
951
- const payload = { components: [container], flags: 32768, ephemeral: true };
952
- const i = context;
953
- if (i.isRepliable()) {
954
- if (i.replied || i.deferred) await i.followUp(payload);
955
- else await i.reply(payload);
956
- }
957
- } else {
958
- const embed = new djs.EmbedBuilder().setColor(15548997).setDescription(`${errorContent}
959
-
960
- ${codeBlock}`);
961
- const m = context;
962
- await m.reply({ embeds: [embed] });
963
- }
964
- } catch (e) {
965
- }
966
- }
967
- if (this.config.errorLogChannelId) {
968
- try {
969
- const channel = await this.channels.fetch(this.config.errorLogChannelId);
970
- if (channel && channel.isTextBased()) {
971
- const userId = "user" in context ? context.user.id : context.author.id;
972
- await channel.send(`\u{1F6A8} **Global Error Boundary Caught Exception**
973
- **Context:** \`${commandKey}\`
974
- **User:** <@${userId}>
975
- \`\`\`js
976
- ${String(error.stack || error.message).substring(0, 1900)}
977
- \`\`\``);
978
- }
979
- } catch (e) {
980
- console.error(`[djs-next] Failed to send error to log channel:`, e);
981
- }
982
- }
983
- }
984
- async handlePreconditions(command2, context, commandKey) {
985
- const userId = "user" in context ? context.user.id : context.author.id;
986
- const isGuild = "guild" in context && context.guild !== null;
987
- const member = context.member;
988
- const sendErr = async (msg) => {
989
- if (msg === null) return;
990
- if ("reply" in context && typeof context.reply === "function") {
991
- try {
992
- if ("replied" in context && context.isRepliable() && (context.replied || context.deferred)) {
993
- await context.followUp({ content: msg, ephemeral: true });
994
- } else {
995
- await context.reply({ content: msg, ephemeral: true, allowedMentions: { repliedUser: false } });
996
- }
997
- } catch (e) {
998
- }
999
- }
1000
- };
1001
- if ("developerOnly" in command2 && command2.developerOnly && !this._developers.includes(userId)) {
1002
- await sendErr(this.config.responses?.developerOnly !== void 0 ? this.config.responses.developerOnly : "Only developers can use this command.");
1003
- return false;
1004
- }
1005
- if ("guildOnly" in command2 && command2.guildOnly && !isGuild) {
1006
- await sendErr(this.config.responses?.guildOnly !== void 0 ? this.config.responses.guildOnly : "This command can only be used in a server.");
1007
- return false;
1008
- }
1009
- if ("userPermissions" in command2 && command2.userPermissions && member?.permissions) {
1010
- const missing = member.permissions.missing(command2.userPermissions);
1011
- if (missing.length > 0) {
1012
- 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(", ")}\``);
1013
- return false;
1014
- }
1015
- }
1016
- if ("botPermissions" in command2 && command2.botPermissions && context.guild?.members.me?.permissions) {
1017
- const missing = context.guild.members.me.permissions.missing(command2.botPermissions);
1018
- if (missing.length > 0) {
1019
- 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(", ")}\``);
1020
- return false;
1021
- }
1022
- }
1023
- let totalCooldown = "cooldown" in command2 && command2.cooldown ? command2.cooldown * 1e3 : 0;
1024
- if (command2.preconditions) {
1025
- for (const pre of command2.preconditions) {
1026
- const parts = pre.split(":");
1027
- const type = parts[0].toLowerCase();
1028
- const val = parts.slice(1).join(":");
1029
- if (type === "owneronly" || type === "developeronly") {
1030
- if (!this._developers.includes(userId)) {
1031
- await sendErr(this.config.responses?.developerOnly !== void 0 ? this.config.responses.developerOnly : "Only developers can use this command.");
1032
- return false;
1033
- }
1034
- } else if (type === "guildonly") {
1035
- if (!isGuild) {
1036
- await sendErr(this.config.responses?.guildOnly !== void 0 ? this.config.responses.guildOnly : "This command can only be used in a server.");
1037
- return false;
1038
- }
1039
- } else if (type === "requireperms") {
1040
- const perms = val.split(",").map((p) => p.trim());
1041
- if (member?.permissions) {
1042
- const missing = member.permissions.missing(perms);
1043
- if (missing.length > 0) {
1044
- 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(", ")}\``);
1045
- return false;
1046
- }
1047
- }
1048
- } else if (type === "cooldown") {
1049
- const match = val.match(/(\d+)(s|m|h)/);
1050
- if (match) {
1051
- let amount = parseInt(match[1]) * 1e3;
1052
- if (match[2] === "m") amount *= 60;
1053
- if (match[2] === "h") amount *= 3600;
1054
- totalCooldown = Math.max(totalCooldown, amount);
1055
- }
1056
- }
1057
- }
1058
- }
1059
- if (totalCooldown > 0) {
1060
- const now = Date.now();
1061
- if (this.config.cooldownAdapter) {
1062
- const lastUsed = await this.config.cooldownAdapter.get(commandKey, userId);
1063
- if (lastUsed) {
1064
- const expirationTime = lastUsed + totalCooldown;
1065
- if (now < expirationTime) {
1066
- const timeStr = `<t:${Math.round(expirationTime / 1e3)}:R>`;
1067
- 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}.`);
1068
- return false;
1069
- }
1070
- }
1071
- await this.config.cooldownAdapter.set(commandKey, userId, now);
1072
- } else {
1073
- if (!this.cooldowns.has(commandKey)) this.cooldowns.set(commandKey, new import_discord4.Collection());
1074
- const timestamps = this.cooldowns.get(commandKey);
1075
- if (timestamps.has(userId)) {
1076
- const expirationTime = timestamps.get(userId) + totalCooldown;
1077
- if (now < expirationTime) {
1078
- const timeStr = `<t:${Math.round(expirationTime / 1e3)}:R>`;
1079
- 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}.`);
1080
- return false;
1081
- }
1082
- }
1083
- timestamps.set(userId, now);
1084
- setTimeout(() => timestamps.delete(userId), totalCooldown);
1085
- }
1086
- }
1087
- return true;
1088
- }
1089
936
  };
1090
937
 
1091
938
  // src/utils/paginate.ts
1092
- var import_discord5 = require("discord.js");
1093
- async function paginate(context, pages, time = 6e4) {
1094
- const isMessage = "author" in context;
1095
- if (!isMessage) {
1096
- if (!context.deferred && !context.replied) {
1097
- await context.deferReply();
1098
- }
939
+ var import_discord4 = require("discord.js");
940
+ async function paginate(interaction, pages, time = 6e4) {
941
+ if (!interaction.deferred && !interaction.replied) {
942
+ await interaction.deferReply();
1099
943
  }
1100
944
  if (pages.length === 1) {
1101
- if (isMessage) {
1102
- return context.reply({ embeds: [pages[0]], components: [] });
1103
- } else {
1104
- return context.editReply({ embeds: [pages[0]], components: [] });
1105
- }
945
+ return interaction.editReply({ embeds: [pages[0]], components: [] });
1106
946
  }
1107
947
  let index = 0;
1108
- const prevButton = new import_discord5.ButtonBuilder().setCustomId("djs_prev").setLabel("Previous").setStyle(import_discord5.ButtonStyle.Primary).setDisabled(true);
1109
- const nextButton = new import_discord5.ButtonBuilder().setCustomId("djs_next").setLabel("Next").setStyle(import_discord5.ButtonStyle.Primary);
1110
- const row = new import_discord5.ActionRowBuilder().addComponents(prevButton, nextButton);
1111
- let message2;
1112
- if (isMessage) {
1113
- message2 = await context.reply({
1114
- embeds: [pages[index]],
1115
- components: [row]
1116
- });
1117
- } else {
1118
- message2 = await context.editReply({
1119
- embeds: [pages[index]],
1120
- components: [row]
1121
- });
1122
- }
948
+ const prevButton = new import_discord4.ButtonBuilder().setCustomId("djs_prev").setLabel("Previous").setStyle(import_discord4.ButtonStyle.Primary).setDisabled(true);
949
+ const nextButton = new import_discord4.ButtonBuilder().setCustomId("djs_next").setLabel("Next").setStyle(import_discord4.ButtonStyle.Primary);
950
+ const row = new import_discord4.ActionRowBuilder().addComponents(prevButton, nextButton);
951
+ const message2 = await interaction.editReply({
952
+ embeds: [pages[index]],
953
+ components: [row]
954
+ });
1123
955
  const collector = message2.createMessageComponentCollector({
1124
- filter: (i) => i.user.id === (isMessage ? context.author.id : context.user.id),
956
+ filter: (i) => i.user.id === interaction.user.id,
1125
957
  time
1126
958
  });
1127
959
  collector.on("collect", async (i) => {
@@ -1134,144 +966,24 @@ async function paginate(context, pages, time = 6e4) {
1134
966
  nextButton.setDisabled(index === pages.length - 1);
1135
967
  await i.update({
1136
968
  embeds: [pages[index]],
1137
- components: [new import_discord5.ActionRowBuilder().addComponents(prevButton, nextButton)]
969
+ components: [new import_discord4.ActionRowBuilder().addComponents(prevButton, nextButton)]
1138
970
  });
1139
971
  });
1140
972
  collector.on("end", async () => {
1141
973
  prevButton.setDisabled(true);
1142
974
  nextButton.setDisabled(true);
1143
- if (message2.editable) {
1144
- await message2.edit({
1145
- components: [new import_discord5.ActionRowBuilder().addComponents(prevButton, nextButton)]
1146
- }).catch(() => {
1147
- });
1148
- }
1149
- });
1150
- }
1151
-
1152
- // src/utils/prompts.ts
1153
- var import_discord6 = require("discord.js");
1154
- async function confirmPrompt(context, content2, time = 3e4) {
1155
- const isMessage = "author" in context;
1156
- if (!isMessage) {
1157
- if (!context.deferred && !context.replied) {
1158
- await context.deferReply();
1159
- }
1160
- }
1161
- const yesButton = new import_discord6.ButtonBuilder().setCustomId("djs_prompt_yes").setLabel("Yes").setStyle(import_discord6.ButtonStyle.Success);
1162
- const noButton = new import_discord6.ButtonBuilder().setCustomId("djs_prompt_no").setLabel("No").setStyle(import_discord6.ButtonStyle.Danger);
1163
- const row = new import_discord6.ActionRowBuilder().addComponents(yesButton, noButton);
1164
- const payload = { components: [row] };
1165
- if (typeof content2 === "string") {
1166
- payload.content = content2;
1167
- } else {
1168
- payload.embeds = [content2];
1169
- }
1170
- let message2;
1171
- if (isMessage) {
1172
- message2 = await context.reply(payload);
1173
- } else {
1174
- message2 = await context.editReply(payload);
1175
- }
1176
- try {
1177
- const interaction = await message2.awaitMessageComponent({
1178
- filter: (i) => i.user.id === (isMessage ? context.author.id : context.user.id),
1179
- time
975
+ await interaction.editReply({
976
+ components: [new import_discord4.ActionRowBuilder().addComponents(prevButton, nextButton)]
977
+ }).catch(() => {
1180
978
  });
1181
- if (interaction.customId === "djs_prompt_yes") {
1182
- await interaction.update({ components: [] });
1183
- return true;
1184
- } else {
1185
- await interaction.update({ components: [] });
1186
- return false;
1187
- }
1188
- } catch (error) {
1189
- if (message2.editable) {
1190
- await message2.edit({ components: [] }).catch(() => {
1191
- });
1192
- }
1193
- return null;
1194
- }
979
+ });
1195
980
  }
1196
981
 
1197
- // src/utils/PaginationBuilder.ts
1198
- var import_discord7 = require("discord.js");
1199
- var PaginationBuilder = class {
1200
- pages = [];
1201
- timeout = 6e4;
1202
- constructor(pages) {
1203
- if (pages) this.pages = pages;
1204
- }
1205
- addPage(embed) {
1206
- this.pages.push(embed);
1207
- return this;
1208
- }
1209
- setPages(pages) {
1210
- this.pages = pages;
1211
- return this;
1212
- }
1213
- setTimeout(ms) {
1214
- this.timeout = ms;
1215
- return this;
1216
- }
1217
- async build(target) {
1218
- if (this.pages.length === 0) throw new Error("[djs-next] PaginationBuilder requires at least one page.");
1219
- if (this.pages.length === 1) {
1220
- if (target instanceof import_discord7.CommandInteraction) {
1221
- if (target.deferred || target.replied) {
1222
- return await target.editReply({ embeds: [this.pages[0]] });
1223
- }
1224
- return await target.reply({ embeds: [this.pages[0]], fetchReply: true });
1225
- } else {
1226
- return await target.reply({ embeds: [this.pages[0]] });
1227
- }
1228
- }
1229
- let currentPage = 0;
1230
- const row = new import_discord7.ActionRowBuilder().addComponents(
1231
- new import_discord7.ButtonBuilder().setCustomId("prev").setLabel("\u25C0").setStyle(import_discord7.ButtonStyle.Primary).setDisabled(true),
1232
- new import_discord7.ButtonBuilder().setCustomId("page").setLabel(`1 / ${this.pages.length}`).setStyle(import_discord7.ButtonStyle.Secondary).setDisabled(true),
1233
- new import_discord7.ButtonBuilder().setCustomId("next").setLabel("\u25B6").setStyle(import_discord7.ButtonStyle.Primary)
1234
- );
1235
- let replyMsg;
1236
- if (target instanceof import_discord7.CommandInteraction) {
1237
- if (target.deferred || target.replied) {
1238
- replyMsg = await target.editReply({ embeds: [this.pages[0]], components: [row] });
1239
- } else {
1240
- replyMsg = await target.reply({ embeds: [this.pages[0]], components: [row], fetchReply: true });
1241
- }
1242
- } else {
1243
- replyMsg = await target.reply({ embeds: [this.pages[0]], components: [row] });
1244
- }
1245
- const userId = target instanceof import_discord7.CommandInteraction ? target.user.id : target.author.id;
1246
- const collector = replyMsg.createMessageComponentCollector({
1247
- componentType: import_discord7.ComponentType.Button,
1248
- time: this.timeout,
1249
- filter: (i) => i.user.id === userId
1250
- });
1251
- collector.on("collect", async (i) => {
1252
- if (i.customId === "prev") currentPage--;
1253
- else if (i.customId === "next") currentPage++;
1254
- const newRow = new import_discord7.ActionRowBuilder().addComponents(
1255
- new import_discord7.ButtonBuilder().setCustomId("prev").setLabel("\u25C0").setStyle(import_discord7.ButtonStyle.Primary).setDisabled(currentPage === 0),
1256
- new import_discord7.ButtonBuilder().setCustomId("page").setLabel(`${currentPage + 1} / ${this.pages.length}`).setStyle(import_discord7.ButtonStyle.Secondary).setDisabled(true),
1257
- new import_discord7.ButtonBuilder().setCustomId("next").setLabel("\u25B6").setStyle(import_discord7.ButtonStyle.Primary).setDisabled(currentPage === this.pages.length - 1)
1258
- );
1259
- await i.update({ embeds: [this.pages[currentPage]], components: [newRow] });
1260
- });
1261
- collector.on("end", () => {
1262
- replyMsg.edit({ components: [] }).catch(() => null);
1263
- });
1264
- return replyMsg;
1265
- }
1266
- };
1267
-
1268
982
  // src/index.ts
1269
983
  __reExport(index_exports, require("discord.js"), module.exports);
1270
984
  // Annotate the CommonJS export names for ESM import in node:
1271
985
  0 && (module.exports = {
1272
986
  DJSNextClient,
1273
- PaginationBuilder,
1274
- confirmPrompt,
1275
987
  defineConfig,
1276
988
  getLocalesCache,
1277
989
  loadConfig,