@spatulox/simplediscordbot 1.5.0 → 1.5.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.
package/dist/index.js CHANGED
@@ -32,6 +32,8 @@ var index_exports = {};
32
32
  __export(index_exports, {
33
33
  Bot: () => Bot,
34
34
  BotEnv: () => BotEnv,
35
+ ButtonManager: () => ButtonManager,
36
+ ComponentManager: () => ComponentManager,
35
37
  DiscordRegex: () => DiscordRegex,
36
38
  EmbedColor: () => EmbedColor,
37
39
  EmbedManager: () => EmbedManager,
@@ -468,6 +470,7 @@ var BotLog = _BotLog;
468
470
  // src/manager/messages/EmbedManager.ts
469
471
  var import_discord2 = require("discord.js");
470
472
  var EmbedColor = /* @__PURE__ */ ((EmbedColor3) => {
473
+ EmbedColor3["transparent"] = "transparent";
471
474
  EmbedColor3[EmbedColor3["error"] = 8912917] = "error";
472
475
  EmbedColor3[EmbedColor3["success"] = 65280] = "success";
473
476
  EmbedColor3[EmbedColor3["black"] = 0] = "black";
@@ -508,7 +511,6 @@ var EmbedColor = /* @__PURE__ */ ((EmbedColor3) => {
508
511
  })(EmbedColor || {});
509
512
  var EmbedManager = class {
510
513
  static get BOT_ICON() {
511
- if (Bot.config.botIconUrl) return Bot.config.botIconUrl;
512
514
  return Bot.client?.user?.displayAvatarURL({ forceStatic: false, size: 128 }) || "";
513
515
  }
514
516
  static get DEFAULT_COLOR() {
@@ -518,7 +520,11 @@ var EmbedManager = class {
518
520
  * Creates base embed - SAME SIMPLE API !
519
521
  */
520
522
  static create(color = null) {
521
- const embed = new import_discord2.EmbedBuilder().setColor(color ?? this.DEFAULT_COLOR).setTimestamp(/* @__PURE__ */ new Date());
523
+ const embed = new import_discord2.EmbedBuilder().setTimestamp(/* @__PURE__ */ new Date());
524
+ const colorC = color ?? this.DEFAULT_COLOR;
525
+ if (colorC !== "transparent" /* transparent */) {
526
+ embed.setColor(colorC);
527
+ }
522
528
  if (Bot.config.botName) {
523
529
  const footer = {
524
530
  text: Bot.config.botName
@@ -549,7 +555,7 @@ var EmbedManager = class {
549
555
  return this.create(25600 /* minecraft */).setTitle("Success").setDescription(description);
550
556
  }
551
557
  /**
552
- * Creates a simply description embed
558
+ * Creates a simple description embed
553
559
  */
554
560
  static description(description) {
555
561
  return this.create().setDescription(description).setFooter(null).setTimestamp(null);
@@ -578,24 +584,6 @@ var EmbedManager = class {
578
584
  });
579
585
  return embed;
580
586
  }
581
- /**
582
- * Fluent API shortcuts
583
- */
584
- static title(embed, title) {
585
- return embed.setTitle(title);
586
- }
587
- static desc(embed, description) {
588
- return embed.setDescription(description);
589
- }
590
- static thumb(embed, url) {
591
- return embed.setThumbnail(url);
592
- }
593
- static image(embed, url) {
594
- return embed.setImage(url);
595
- }
596
- static footer(embed, text) {
597
- return embed.setFooter({ text, iconURL: this.BOT_ICON });
598
- }
599
587
  /**
600
588
  * Transform embed into objet for interaction.reply()
601
589
  */
@@ -2327,7 +2315,7 @@ var ModalManager = class {
2327
2315
  builder.setStyle(import_discord15.TextInputStyle.Short).setMaxLength(10);
2328
2316
  break;
2329
2317
  case 3 /* DATE */:
2330
- builder.setStyle(import_discord15.TextInputStyle.Short).setMaxLength(10);
2318
+ builder.setStyle(import_discord15.TextInputStyle.Short).setMaxLength(10).setPlaceholder("YYYY-MM-DD / DD-MM-YYYY or YYYY/MM/DD / DD/MM/YYYY");
2331
2319
  break;
2332
2320
  case 4 /* PHONE */:
2333
2321
  builder.setStyle(import_discord15.TextInputStyle.Short).setMaxLength(20);
@@ -2336,14 +2324,14 @@ var ModalManager = class {
2336
2324
  return new import_discord15.LabelBuilder().setLabel(opt.label).setTextInputComponent(builder);
2337
2325
  }
2338
2326
  /**
2339
- * Simple modal with ONE field - DIRECT ModalBuilder return !
2340
- */
2327
+ * Simple modal with ONE field - DIRECT ModalBuilder return !
2328
+ */
2341
2329
  static simple(customId, modalTitle, field) {
2342
2330
  const modal = this.create(modalTitle ?? Bot.config?.botName ?? "Bot", customId);
2343
2331
  const opt = {
2344
2332
  ...field,
2345
2333
  customId: `${customId}_input`,
2346
- placeholder: field.placeholder ?? `Enter ${field.label.toLowerCase()}`
2334
+ placeholder: "placeholder" in field && field.placeholder ? field.placeholder : `Enter ${field.label.toLowerCase()}`
2347
2335
  };
2348
2336
  modal.addLabelComponents(this._createField(opt));
2349
2337
  return modal;
@@ -2375,7 +2363,7 @@ var ModalManager = class {
2375
2363
  * Date modal preset
2376
2364
  */
2377
2365
  static date(customId, modalTitle = "Select Date", inputLabel = "Date") {
2378
- return this.simple(`${customId}_date`, modalTitle, { label: inputLabel, type: 3 /* DATE */, placeholder: "YYYY-MM-DD or DD/MM/YYYY" });
2366
+ return this.simple(`${customId}_date`, modalTitle, { label: inputLabel, type: 3 /* DATE */ });
2379
2367
  }
2380
2368
  /**
2381
2369
  * Number modal preset
@@ -2409,40 +2397,39 @@ var ModalManager = class {
2409
2397
  const num = parseInt(value);
2410
2398
  return isNaN(num) ? null : num;
2411
2399
  }
2412
- static parsePhone(value) {
2413
- const clean = value.replace(/[\s\-\(\)]/g, "");
2414
- if (/^(06|07|09)\d{8}$/.test(clean) || /^(\+33|0033)?[6-9]\d{8}$/.test(clean)) {
2415
- if (clean.startsWith("06") || clean.startsWith("07") || clean.startsWith("09")) {
2416
- return "+33" + clean.slice(2);
2417
- }
2418
- return clean.startsWith("0033") ? "+33" + clean.slice(4) : clean;
2419
- }
2420
- return null;
2421
- }
2400
+ /**
2401
+ * yyyy-mm-dd / dd-mm-yyyy / dd/mm/yyyy / yyyy/mm/dd
2402
+ * American format is not supported lol
2403
+ * @param value
2404
+ */
2422
2405
  static parseDate(value) {
2423
- if (/^\d{4}-\d{2}-\d{2}$/.test(value)) {
2406
+ if (/^\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01])$/.test(value)) {
2424
2407
  const [year, month, day] = value.split("-").map(Number);
2425
2408
  const date = new Date(year, month - 1, day);
2426
2409
  return isNaN(date.getTime()) ? null : date;
2427
2410
  }
2428
- if (/^\d{2}\/\d{2}\/\d{4}$/.test(value)) {
2411
+ if (/^(0[1-9]|[12]\d|3[01])-(0[1-9]|1[0-2])-\d{4}$/.test(value)) {
2412
+ const [day, month, year] = value.split("-").map(Number);
2413
+ const date = new Date(year, month - 1, day);
2414
+ return isNaN(date.getTime()) ? null : date;
2415
+ }
2416
+ if (/^(0[1-9]|[12]\d|3[01])\/(0[1-9]|1[0-2])\/\d{4}$/.test(value)) {
2429
2417
  const [day, month, year] = value.split("/").map(Number);
2430
2418
  const date = new Date(year, month - 1, day);
2431
2419
  return isNaN(date.getTime()) ? null : date;
2432
2420
  }
2421
+ if (/^\d{4}\/(0[1-9]|1[0-2])\/(0[1-9]|[12]\d|3[01])$/.test(value)) {
2422
+ const [year, month, day] = value.split("/").map(Number);
2423
+ const date = new Date(year, month - 1, day);
2424
+ return isNaN(date.getTime()) ? null : date;
2425
+ }
2433
2426
  return null;
2434
2427
  }
2435
- /**
2436
- * Transform modal to interaction.showModal() format
2437
- */
2438
- static toInteraction(modal) {
2439
- return modal;
2440
- }
2441
2428
  };
2442
2429
 
2443
2430
  // src/manager/interactions/SelectMenuManager.ts
2444
2431
  var import_discord16 = require("discord.js");
2445
- var SelectMenuManager = class {
2432
+ var SelectMenuManager = class _SelectMenuManager {
2446
2433
  /**
2447
2434
  * Creates base StringSelectMenu - SIMPLE API !
2448
2435
  */
@@ -2465,15 +2452,13 @@ var SelectMenuManager = class {
2465
2452
  * Pagination menu
2466
2453
  */
2467
2454
  static paginated(customId, options, pageSize = 25) {
2468
- const row = new import_discord16.ActionRowBuilder();
2455
+ const rows = [];
2469
2456
  for (let i = 0; i < options.length; i += pageSize) {
2470
2457
  const pageOptions = options.slice(i, i + pageSize);
2471
- const menu = new import_discord16.StringSelectMenuBuilder().setCustomId(`${customId}_page_${Math.floor(i / pageSize)}`).setPlaceholder(`Page ${Math.floor(i / pageSize) + 1}`).addOptions(pageOptions.map((opt) => {
2472
- return this.option(opt);
2473
- }));
2474
- row.addComponents(menu);
2458
+ const menu = new import_discord16.StringSelectMenuBuilder().setCustomId(`${customId}_page_${Math.floor(i / pageSize)}`).setPlaceholder(`Page ${Math.floor(i / pageSize) + 1}`).addOptions(pageOptions.map((opt) => this.option(opt)));
2459
+ rows.push(_SelectMenuManager.row(menu));
2475
2460
  }
2476
- return row;
2461
+ return rows.slice(0, 5);
2477
2462
  }
2478
2463
  /**
2479
2464
  * User Select Menu (Components V2)
@@ -2537,6 +2522,266 @@ var SelectMenuManager = class {
2537
2522
  (component) => this.row(component)
2538
2523
  );
2539
2524
  }
2525
+ static toMessage(menus) {
2526
+ return {
2527
+ components: this._createRowsToReturn(menus)
2528
+ };
2529
+ }
2530
+ static toInteraction(menus, ephemeral = false) {
2531
+ return {
2532
+ components: this._createRowsToReturn(menus),
2533
+ flags: ephemeral ? [import_discord16.MessageFlags.Ephemeral] : []
2534
+ };
2535
+ }
2536
+ static _createRowsToReturn(menus) {
2537
+ if (Array.isArray(menus)) {
2538
+ return menus.map(
2539
+ (menu) => menu instanceof import_discord16.ActionRowBuilder ? menu : _SelectMenuManager.row(menu)
2540
+ );
2541
+ }
2542
+ return menus instanceof import_discord16.ActionRowBuilder ? [menus] : [_SelectMenuManager.row(menus)];
2543
+ }
2544
+ };
2545
+
2546
+ // src/manager/messages/ComponentManager.ts
2547
+ var import_discord17 = require("discord.js");
2548
+ var ComponentManager = class {
2549
+ static get DEFAULT_COLOR() {
2550
+ return Bot.config?.defaultEmbedColor || 6064856 /* default */;
2551
+ }
2552
+ /**
2553
+ * Creates base ComponentV2
2554
+ */
2555
+ static create(option) {
2556
+ const container = new import_discord17.ContainerBuilder();
2557
+ const colorC = option?.color ?? this.DEFAULT_COLOR;
2558
+ if (colorC !== "transparent" /* transparent */) {
2559
+ container.setAccentColor(colorC);
2560
+ }
2561
+ if (option?.title || option?.thumbnailUrl) {
2562
+ if (option?.thumbnailUrl) {
2563
+ const headerSection = new import_discord17.SectionBuilder().addTextDisplayComponents(
2564
+ new import_discord17.TextDisplayBuilder().setContent(
2565
+ option?.title ? "## " + option.title : "\u200B"
2566
+ )
2567
+ ).setThumbnailAccessory(
2568
+ new import_discord17.ThumbnailBuilder().setURL(option.thumbnailUrl)
2569
+ );
2570
+ container.addSectionComponents(headerSection);
2571
+ } else {
2572
+ container.addTextDisplayComponents(
2573
+ new import_discord17.TextDisplayBuilder().setContent("## " + option.title)
2574
+ );
2575
+ }
2576
+ container.addSeparatorComponents(this.separator());
2577
+ }
2578
+ return container;
2579
+ }
2580
+ /**
2581
+ * Creates simple ComponentV2 with just description
2582
+ */
2583
+ static simple(description, color = null) {
2584
+ return this.create({ color }).addTextDisplayComponents(new import_discord17.TextDisplayBuilder().setContent(description)).addSeparatorComponents(this.separator());
2585
+ }
2586
+ /**
2587
+ * Creates success ComponentV2
2588
+ */
2589
+ static success(description) {
2590
+ return this.create({ title: "Success", color: 65280 /* success */ }).addTextDisplayComponents(new import_discord17.TextDisplayBuilder().setContent(description)).addSeparatorComponents(this.separator());
2591
+ }
2592
+ /**
2593
+ * Creates debug ComponentV2
2594
+ */
2595
+ static debug(description) {
2596
+ return this.create({ title: "Debug", color: 25600 /* minecraft */ }).addTextDisplayComponents(
2597
+ new import_discord17.TextDisplayBuilder().setContent(description)
2598
+ ).addSeparatorComponents(this.separator());
2599
+ }
2600
+ /**
2601
+ * Creates error ComponentV2
2602
+ */
2603
+ static error(description) {
2604
+ return this.create({ title: "Something went wrong", color: 8912917 /* error */ }).addTextDisplayComponents(
2605
+ new import_discord17.TextDisplayBuilder().setContent(description)
2606
+ ).addSeparatorComponents(this.separator());
2607
+ }
2608
+ static separator(spacing = import_discord17.SeparatorSpacingSize.Small) {
2609
+ return new import_discord17.SeparatorBuilder().setDivider(true).setSpacing(spacing);
2610
+ }
2611
+ /**
2612
+ * Quick field adder
2613
+ */
2614
+ static field(container, field) {
2615
+ if ("button" in field || "thumbnailUrl" in field) {
2616
+ const section = new import_discord17.SectionBuilder().addTextDisplayComponents(
2617
+ new import_discord17.TextDisplayBuilder().setContent(`**${field.name}**`),
2618
+ new import_discord17.TextDisplayBuilder().setContent(field.value)
2619
+ );
2620
+ if ("button" in field) {
2621
+ section.setButtonAccessory(field.button);
2622
+ } else if ("thumbnailUrl" in field) {
2623
+ section.setThumbnailAccessory(new import_discord17.ThumbnailBuilder().setURL(field.thumbnailUrl));
2624
+ }
2625
+ container.addSectionComponents(section);
2626
+ } else {
2627
+ container.addTextDisplayComponents(
2628
+ new import_discord17.TextDisplayBuilder().setContent(`**${field.name}**`),
2629
+ new import_discord17.TextDisplayBuilder().setContent(field.value)
2630
+ );
2631
+ }
2632
+ container.addSeparatorComponents(this.separator());
2633
+ return container;
2634
+ }
2635
+ /*static field(container: ContainerBuilder, field: ComponentManagerField): ContainerBuilder {
2636
+ const section = new SectionBuilder()
2637
+ .addTextDisplayComponents(
2638
+ new TextDisplayBuilder().setContent(`**${field.name}**`),
2639
+ new TextDisplayBuilder().setContent(field.value)
2640
+ );
2641
+
2642
+ if (field.thumbnailUrl) {
2643
+ section.setThumbnailAccessory(
2644
+ new ThumbnailBuilder().setURL(field.thumbnailUrl)
2645
+ );
2646
+ }
2647
+
2648
+ if (field.button && field.button.length > 0) {
2649
+ section.setButtonAccessory(field.button[0]!);
2650
+ }
2651
+
2652
+ container.addSectionComponents(section);
2653
+ container.addSeparatorComponents(this.separator());
2654
+ return container;
2655
+ }*/
2656
+ /**
2657
+ * Multiple fields
2658
+ */
2659
+ static fields(container, fields) {
2660
+ fields.forEach((f) => {
2661
+ this.field(container, f);
2662
+ });
2663
+ return container;
2664
+ }
2665
+ /**
2666
+ * Add a media gallery (links)
2667
+ */
2668
+ static mediaGallery(container, medias) {
2669
+ const gallery = new import_discord17.MediaGalleryBuilder();
2670
+ medias.forEach((med) => {
2671
+ gallery.addItems(new import_discord17.MediaGalleryItemBuilder().setURL(med.url).setSpoiler(med.spoiler ?? false));
2672
+ });
2673
+ container.addMediaGalleryComponents(gallery);
2674
+ return container;
2675
+ }
2676
+ static selectMenu(container, selectMenu) {
2677
+ const menus = Array.isArray(selectMenu) ? selectMenu : [selectMenu];
2678
+ menus.forEach((menu) => {
2679
+ const row = SelectMenuManager.row(menu);
2680
+ container.addActionRowComponents(row);
2681
+ });
2682
+ return container;
2683
+ }
2684
+ static file(container, file) {
2685
+ const files = [];
2686
+ const fileArray = Array.isArray(file) ? file : [file];
2687
+ fileArray.forEach((f) => {
2688
+ const attachment = new import_discord17.AttachmentBuilder(f.buffer, {
2689
+ name: f.name
2690
+ });
2691
+ files.push(attachment);
2692
+ container.addFileComponents(
2693
+ new import_discord17.FileBuilder().setURL(`attachment://${f.name}`).setSpoiler(f.spoiler ?? false)
2694
+ );
2695
+ container.addSeparatorComponents(this.separator());
2696
+ });
2697
+ return { container, files };
2698
+ }
2699
+ static footer(container) {
2700
+ container.addTextDisplayComponents(
2701
+ new import_discord17.TextDisplayBuilder().setContent(`-# **${Bot.config?.botName || "Bot"} \xB7 <t:${Math.floor(Date.now() / 1e3)}:d> <t:${Math.floor(Date.now() / 1e3)}:t>**`)
2702
+ );
2703
+ return container;
2704
+ }
2705
+ /**
2706
+ * Transform ComponentV2 into object for channel.send()
2707
+ * @param container The container to send
2708
+ * @param file Only if you have files to attach
2709
+ * @param footer Sometimes you don't want to have the Bot name neither the timestamp...
2710
+ */
2711
+ static toMessage(container, file = null, footer = true) {
2712
+ if (footer) {
2713
+ this.footer(container);
2714
+ }
2715
+ if (file) {
2716
+ return {
2717
+ components: [container],
2718
+ files: Array.isArray(file) ? file : [file],
2719
+ flags: [import_discord17.MessageFlags.IsComponentsV2]
2720
+ };
2721
+ }
2722
+ return {
2723
+ components: [container],
2724
+ flags: [import_discord17.MessageFlags.IsComponentsV2]
2725
+ };
2726
+ }
2727
+ };
2728
+
2729
+ // src/manager/interactions/ButtonManager.ts
2730
+ var import_discord18 = require("discord.js");
2731
+ var ButtonManager = class _ButtonManager {
2732
+ static _create(options) {
2733
+ const btn = new import_discord18.ButtonBuilder().setCustomId(options.customId).setLabel(options.label ?? "Button").setStyle(options.style).setDisabled(options.disabled ?? false);
2734
+ if (options.emoji) {
2735
+ btn.setEmoji(options.emoji);
2736
+ }
2737
+ return btn;
2738
+ }
2739
+ static primary(options) {
2740
+ return this._create({ ...options, style: import_discord18.ButtonStyle.Primary });
2741
+ }
2742
+ static success(options) {
2743
+ return this._create({ ...options, style: import_discord18.ButtonStyle.Success });
2744
+ }
2745
+ static secondary(options) {
2746
+ return this._create({ ...options, style: import_discord18.ButtonStyle.Secondary });
2747
+ }
2748
+ static danger(options) {
2749
+ return this._create({ ...options, style: import_discord18.ButtonStyle.Danger });
2750
+ }
2751
+ static link(options) {
2752
+ const btn = new import_discord18.ButtonBuilder().setLabel(options.label).setStyle(import_discord18.ButtonStyle.Link).setURL(options.url);
2753
+ if (options.emoji) btn.setEmoji(options.emoji);
2754
+ return btn;
2755
+ }
2756
+ static confirm(customId) {
2757
+ return this.success({ customId, label: "Confirm" });
2758
+ }
2759
+ static cancel(customId) {
2760
+ return this.danger({ customId, label: "Cancel" });
2761
+ }
2762
+ static row(but) {
2763
+ const buttons = Array.isArray(but) ? but.slice(0, 5) : [but];
2764
+ return new import_discord18.ActionRowBuilder().addComponents(buttons);
2765
+ }
2766
+ static toMessage(button) {
2767
+ return {
2768
+ components: this._createRowsToReturn(button)
2769
+ };
2770
+ }
2771
+ static toInteraction(button, ephemeral = false) {
2772
+ return {
2773
+ components: this._createRowsToReturn(button),
2774
+ flags: ephemeral ? [import_discord18.MessageFlags.Ephemeral] : []
2775
+ };
2776
+ }
2777
+ static _createRowsToReturn(button) {
2778
+ if (Array.isArray(button)) {
2779
+ return button.map(
2780
+ (btn) => btn instanceof import_discord18.ActionRowBuilder ? btn : _ButtonManager.row(btn)
2781
+ );
2782
+ }
2783
+ return button instanceof import_discord18.ActionRowBuilder ? [button] : [_ButtonManager.row(button)];
2784
+ }
2540
2785
  };
2541
2786
 
2542
2787
  // src/utils/SimpleMutex.ts
@@ -2580,7 +2825,7 @@ var SimpleMutex = class {
2580
2825
  // package.json
2581
2826
  var package_default = {
2582
2827
  name: "@spatulox/simplediscordbot",
2583
- version: "1.1.1",
2828
+ version: "1.5.1",
2584
2829
  author: "Spatulox",
2585
2830
  description: "Simple discord bot framework to set up a bot under 30 secondes",
2586
2831
  exports: {
@@ -2590,26 +2835,25 @@ var package_default = {
2590
2835
  },
2591
2836
  types: "./dist/index.d.ts",
2592
2837
  scripts: {
2593
- build: "rm -r dist/ && tsup",
2838
+ "type-check": "tsc --noEmit",
2839
+ build: "npm run type-check && rm -rf ./dist/ && tsup",
2840
+ dev: "npm run type-check && tsx watch src/test/index.ts",
2594
2841
  patch: "npm run build && npm version patch",
2595
2842
  minor: "npm run build && npm version minor",
2596
2843
  major: "npm run build && npm version major",
2597
2844
  "pub:patch": "npm run patch && npm publish --access public",
2598
2845
  "pub:minor": "npm run minor && npm publish --access public",
2599
- "pub:major": "npm run major && npm publish --access public",
2600
- "test-pack": "npm run patch && npm publish --access public",
2601
- dev: "nodemon --exec tsx src/test/index.ts"
2846
+ "pub:major": "npm run major && npm publish --access public"
2602
2847
  },
2603
2848
  license: "MIT",
2604
2849
  dependencies: {
2605
- "@spatulox/discord-interaction-manager": "^1.0.21",
2850
+ "@spatulox/discord-interaction-manager": "^1.0.22",
2606
2851
  "discord.js": "^14.25.1"
2607
2852
  },
2608
2853
  devDependencies: {
2609
2854
  "@types/node": "^22.14.0",
2610
2855
  "@types/node-schedule": "^2.1.7",
2611
2856
  dotenv: "^17.2.4",
2612
- nodemon: "^3.1.9",
2613
2857
  tsup: "^8.5.1",
2614
2858
  tsx: "^4.20.3",
2615
2859
  typescript: "^5.9.3"
@@ -2640,6 +2884,8 @@ var SimpleDiscordBotInfo = {
2640
2884
  0 && (module.exports = {
2641
2885
  Bot,
2642
2886
  BotEnv,
2887
+ ButtonManager,
2888
+ ComponentManager,
2643
2889
  DiscordRegex,
2644
2890
  EmbedColor,
2645
2891
  EmbedManager,