@spatulox/simplediscordbot 1.0.5 → 1.0.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (28) hide show
  1. package/.env.example +1 -1
  2. package/LICENSE.md +21 -21
  3. package/README.md +44 -44
  4. package/dist/bot/BotMessage.js +54 -28
  5. package/dist/index.js +6 -2
  6. package/dist/manager/builder/SendableComponentBuilder.js +62 -0
  7. package/dist/manager/direct/UserManager.js +16 -5
  8. package/dist/manager/guild/ChannelManager/GuildMessageManager.js +12 -4
  9. package/dist/manager/guild/ChannelManager/ThreadChannelManager.js +15 -0
  10. package/dist/manager/interactions/InteractionManager.js +68 -0
  11. package/dist/manager/{handlers/builder → interactions}/ModalManager.js +2 -2
  12. package/dist/manager/interactions/SelectMenuManager.js +123 -0
  13. package/dist/manager/messages/WebhookManager.js +8 -5
  14. package/package.json +36 -41
  15. package/dist/cli/BaseCLI.js +0 -166
  16. package/dist/cli/GenerationCLI/ContextMenuGeneratorCLI.js +0 -109
  17. package/dist/cli/GenerationCLI/GenerationCLI.js +0 -25
  18. package/dist/cli/GenerationCLI/ModalGeneratorCLI.js +0 -166
  19. package/dist/cli/GenerationCLI/SlashCommandsGeneratorCLI.js +0 -221
  20. package/dist/cli/GuildListManager.js +0 -61
  21. package/dist/cli/InteractionCLI/InteractionCLI.js +0 -30
  22. package/dist/cli/InteractionCLI/InteractionCLIManager.js +0 -80
  23. package/dist/cli/MainCLI.js +0 -32
  24. package/dist/cli/type/ContextMenuConfig.js +0 -2
  25. package/dist/cli/type/InteractionType.js +0 -14
  26. package/dist/cli/type/SlashCommandConfig.js +0 -2
  27. package/dist/manager/handlers/interactions/BaseInteractionManager.js +0 -338
  28. package/dist/manager/handlers/interactions/InteractionManager.js +0 -29
package/.env.example CHANGED
@@ -1,2 +1,2 @@
1
- DISCORD_BOT_TOKEN=example
1
+ DISCORD_BOT_TOKEN=example
2
2
  DISCORD_BOT_DEV # Define this one with anything you want, the value is not important as long as the env var is defined
package/LICENSE.md CHANGED
@@ -1,21 +1,21 @@
1
- MIT License
2
-
3
- Copyright (c) 2025 Spatulox
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Spatulox
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,45 +1,45 @@
1
-
2
- # Simple Discord Bot ![badge-status](https://img.shields.io/badge/status-active-brightgreen)
3
-
4
- [![npm version](https://img.shields.io/npm/v/@spatulox/simplediscordbot.svg)](https://npmjs.com/package/@spatulox/simplediscordbot)
5
- [![downloads](https://img.shields.io/npm/dm/@spatulox/simplediscordbot.svg)](https://npmjs.com/package/@spatulox/simplediscordbot)
6
- [![license](https://img.shields.io/npm/l/@spatulox/simplediscordbot.svg)](LICENSE)
7
-
8
- **Framework Discord.js TypeScript ultra-simple**
9
-
10
- ## Installation
11
- ```bash
12
- npm i @spatulox/simplediscordbot
13
- ```
14
-
15
- > **TypeScript Discord.js framework** - Simple, powerful, framework-ready. Built for developers who want clean bot architecture.
16
-
17
- ## Quick Start
18
-
19
- ```typescript
20
- import {Bot, BotConfig, EmbedColor, Time} from "@spatulox/simplediscordbot";
21
- import {Client, Events, GatewayIntentBits} from "discord.js";
22
-
23
- const client = new Client({
24
- intents: [GatewayIntentBits.Guilds, GatewayIntentBits.GuildMessages]
25
- });
26
-
27
- const config: BotConfig = {
28
- defaultEmbedColor: EmbedColor.blue,
29
- botName: "Simple Discord Bot",
30
- log: {
31
- logChannelId: "YOUR_LOG_CHANNEL_ID",
32
- errorChannelId: "YOUR_ERROR_CHANNEL_ID",
33
- info: { console: true, discord: true },
34
- error: { console: true, discord: true },
35
- warn: { console: true, discord: true },
36
- debug: { console: true, discord: false }
37
- }
38
- };
39
-
40
- const bot = new Bot(client, config);
41
-
42
- bot.client.on(Events.ClientReady, async () => {
43
- Bot.setRandomActivity(randomActivityList, Time.minute.MIN_10.toMilliseconds());
44
- console.log("Bot ready! ✨");
1
+
2
+ # Simple Discord Bot ![badge-status](https://img.shields.io/badge/status-active-brightgreen)
3
+
4
+ [![npm version](https://img.shields.io/npm/v/@spatulox/simplediscordbot.svg)](https://npmjs.com/package/@spatulox/simplediscordbot)
5
+ [![downloads](https://img.shields.io/npm/dm/@spatulox/simplediscordbot.svg)](https://npmjs.com/package/@spatulox/simplediscordbot)
6
+ [![license](https://img.shields.io/npm/l/@spatulox/simplediscordbot.svg)](LICENSE)
7
+
8
+ **Framework Discord.js TypeScript ultra-simple**
9
+
10
+ ## Installation
11
+ ```bash
12
+ npm i @spatulox/simplediscordbot
13
+ ```
14
+
15
+ > **TypeScript Discord.js framework** - Simple, powerful, framework-ready. Built for developers who want clean bot architecture.
16
+
17
+ ## Quick Start
18
+
19
+ ```typescript
20
+ import {Bot, BotConfig, EmbedColor, Time} from "@spatulox/simplediscordbot";
21
+ import {Client, Events, GatewayIntentBits} from "discord.js";
22
+
23
+ const client = new Client({
24
+ intents: [GatewayIntentBits.Guilds, GatewayIntentBits.GuildMessages]
25
+ });
26
+
27
+ const config: BotConfig = {
28
+ defaultEmbedColor: EmbedColor.blue,
29
+ botName: "Simple Discord Bot",
30
+ log: {
31
+ logChannelId: "YOUR_LOG_CHANNEL_ID",
32
+ errorChannelId: "YOUR_ERROR_CHANNEL_ID",
33
+ info: { console: true, discord: true },
34
+ error: { console: true, discord: true },
35
+ warn: { console: true, discord: true },
36
+ debug: { console: true, discord: false }
37
+ }
38
+ };
39
+
40
+ const bot = new Bot(client, config);
41
+
42
+ bot.client.on(Events.ClientReady, async () => {
43
+ Bot.setRandomActivity(randomActivityList, Time.minute.MIN_10.toMilliseconds());
44
+ console.log("Bot ready! ✨");
45
45
  });
@@ -5,36 +5,54 @@ const discord_js_1 = require("discord.js");
5
5
  const Log_1 = require("../utils/Log");
6
6
  const Bot_1 = require("./Bot");
7
7
  const EmbedManager_1 = require("../manager/messages/EmbedManager");
8
+ const SendableComponentBuilder_1 = require("../manager/builder/SendableComponentBuilder");
8
9
  class BotMessage {
9
- /**
10
- * Send message to any text-based channel
11
- */
12
- async send(channel, content) {
13
- if (!channel) {
14
- Log_1.Log.warn('Cannot send message: invalid channel');
15
- return false;
16
- }
17
- if (typeof channel == "string") {
18
- channel = Bot_1.Bot.client.channels.cache.get(channel);
19
- }
10
+ async send(channel, content, component) {
20
11
  try {
21
- if (content instanceof discord_js_1.EmbedBuilder) {
22
- const msg = await channel.send({ embeds: [content] });
23
- Log_1.Log.info(`Embed sent to ${channel.id}`);
24
- return msg;
12
+ if (!channel) {
13
+ Log_1.Log.warn('Cannot send message: invalid channel');
14
+ return false;
15
+ }
16
+ if (typeof channel === "string") {
17
+ const fetchedChannel = Bot_1.Bot.client.channels.cache.get(channel);
18
+ if (!fetchedChannel?.isTextBased()) {
19
+ Log_1.Log.warn(`Invalid channel ID: ${channel}`);
20
+ return false;
21
+ }
22
+ channel = fetchedChannel;
23
+ }
24
+ let messageCreate;
25
+ if (typeof content !== "string" && !component) {
26
+ messageCreate = content;
25
27
  }
26
28
  else {
27
- const msg = await channel.send(content);
28
- Log_1.Log.info(`Message sent to ${channel.id}: ${content.slice(0, 50)}...`);
29
- return msg;
29
+ content = content;
30
+ if (content && component) {
31
+ messageCreate = SendableComponentBuilder_1.SendableComponentBuilder.buildMessage(content, component);
32
+ }
33
+ else if (content) {
34
+ messageCreate = SendableComponentBuilder_1.SendableComponentBuilder.buildMessage(content);
35
+ }
36
+ else if (component) {
37
+ messageCreate = SendableComponentBuilder_1.SendableComponentBuilder.buildMessage(component);
38
+ }
39
+ else {
40
+ throw new Error("content and component cannot be null at the same time");
41
+ }
42
+ }
43
+ try {
44
+ return await channel.send(messageCreate);
45
+ }
46
+ catch (e) {
47
+ throw e;
30
48
  }
31
49
  }
32
- catch (error) {
33
- Log_1.Log.error(`Failed to send message to ${channel.id}: ${error}`);
50
+ catch (e) {
51
+ Log_1.Log.error(`Failed to send message : ${e}`);
34
52
  return false;
35
53
  }
36
54
  }
37
- async sendDM(user, content) {
55
+ async sendDM(user, content, component) {
38
56
  try {
39
57
  let targetUser;
40
58
  if (user instanceof discord_js_1.User || user instanceof discord_js_1.GuildMember) {
@@ -43,12 +61,20 @@ class BotMessage {
43
61
  else {
44
62
  targetUser = await Bot_1.Bot.client.users.fetch(user);
45
63
  }
46
- if (content instanceof discord_js_1.EmbedBuilder) {
47
- return await targetUser.send({ embeds: [content] });
64
+ let messageCreate;
65
+ if (content && component) {
66
+ messageCreate = SendableComponentBuilder_1.SendableComponentBuilder.buildMessage(content, component);
67
+ }
68
+ else if (content) {
69
+ messageCreate = SendableComponentBuilder_1.SendableComponentBuilder.buildMessage(content);
70
+ }
71
+ else if (component) {
72
+ messageCreate = SendableComponentBuilder_1.SendableComponentBuilder.buildMessage(component);
48
73
  }
49
74
  else {
50
- return await targetUser.send(content);
75
+ throw new Error("content and component cannot be null at the same time");
51
76
  }
77
+ return await targetUser.send(messageCreate);
52
78
  }
53
79
  catch (error) {
54
80
  Log_1.Log.error(`Failed to send message to ${user}: ${error}`);
@@ -61,9 +87,9 @@ class BotMessage {
61
87
  success(channel, message) {
62
88
  const embed = EmbedManager_1.EmbedManager.success(message);
63
89
  if (channel instanceof discord_js_1.User || channel instanceof discord_js_1.GuildMember) {
64
- return this.sendDM(channel, embed);
90
+ return this.sendDM(channel, message, embed);
65
91
  }
66
- return this.send(channel, embed);
92
+ return this.send(channel, message, embed);
67
93
  }
68
94
  /**
69
95
  * Quick error message
@@ -71,9 +97,9 @@ class BotMessage {
71
97
  error(channel, message) {
72
98
  const embed = EmbedManager_1.EmbedManager.error(message);
73
99
  if (channel instanceof discord_js_1.User || channel instanceof discord_js_1.GuildMember) {
74
- return this.sendDM(channel, embed);
100
+ return this.sendDM(channel, message, embed);
75
101
  }
76
- return this.send(channel, embed);
102
+ return this.send(channel, message, embed);
77
103
  }
78
104
  }
79
105
  exports.BotMessage = BotMessage;
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.DiscordRegex = exports.SimpleMutex = exports.Log = exports.Time = exports.ModalManager = exports.UserManager = exports.GuildManager = exports.ReactionManager = exports.WebhookManager = exports.EmbedColor = exports.EmbedManager = exports.FileManager = exports.BotEnv = exports.Bot = void 0;
3
+ exports.DiscordRegex = exports.SimpleMutex = exports.Log = exports.Time = exports.InteractionManager = exports.SelectMenuManager = exports.ModalManager = exports.UserManager = exports.GuildManager = exports.ReactionManager = exports.WebhookManager = exports.EmbedColor = exports.EmbedManager = exports.FileManager = exports.BotEnv = exports.Bot = void 0;
4
4
  var Bot_1 = require("./bot/Bot");
5
5
  Object.defineProperty(exports, "Bot", { enumerable: true, get: function () { return Bot_1.Bot; } });
6
6
  var BotEnv_1 = require("./bot/BotEnv");
@@ -20,8 +20,12 @@ Object.defineProperty(exports, "GuildManager", { enumerable: true, get: function
20
20
  var UserManager_1 = require("./manager/direct/UserManager");
21
21
  Object.defineProperty(exports, "UserManager", { enumerable: true, get: function () { return UserManager_1.UserManager; } });
22
22
  // Handlers
23
- var ModalManager_1 = require("./manager/handlers/builder/ModalManager");
23
+ var ModalManager_1 = require("./manager/interactions/ModalManager");
24
24
  Object.defineProperty(exports, "ModalManager", { enumerable: true, get: function () { return ModalManager_1.ModalManager; } });
25
+ var SelectMenuManager_1 = require("./manager/interactions/SelectMenuManager");
26
+ Object.defineProperty(exports, "SelectMenuManager", { enumerable: true, get: function () { return SelectMenuManager_1.SelectMenuManager; } });
27
+ var InteractionManager_1 = require("./manager/interactions/InteractionManager");
28
+ Object.defineProperty(exports, "InteractionManager", { enumerable: true, get: function () { return InteractionManager_1.InteractionManager; } });
25
29
  // Utils
26
30
  var UnitTime_1 = require("./utils/times/UnitTime");
27
31
  Object.defineProperty(exports, "Time", { enumerable: true, get: function () { return UnitTime_1.Time; } });
@@ -0,0 +1,62 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SendableComponentBuilder = void 0;
4
+ const discord_js_1 = require("discord.js");
5
+ class SendableComponentBuilder {
6
+ static isSendableComponent(thing) {
7
+ return thing instanceof discord_js_1.EmbedBuilder || thing instanceof discord_js_1.ActionRowBuilder;
8
+ }
9
+ static build(base, content, components) {
10
+ if (content) {
11
+ base.content = content;
12
+ }
13
+ const comps = Array.isArray(components) ? components : [components].filter(Boolean);
14
+ for (const comp of comps) {
15
+ if (comp instanceof discord_js_1.EmbedBuilder) {
16
+ base.embeds = base.embeds || [];
17
+ base.embeds.push(comp);
18
+ }
19
+ if (comp instanceof discord_js_1.ActionRowBuilder) {
20
+ base.components = base.components || [];
21
+ base.components.push(comp);
22
+ }
23
+ }
24
+ return base;
25
+ }
26
+ static buildInteraction(contentOrComponent, component, ephemeral = false) {
27
+ let base = {};
28
+ // Case 1
29
+ if (typeof contentOrComponent === 'string' && !component) {
30
+ base = this.build(base, contentOrComponent);
31
+ }
32
+ // Case 2
33
+ if (typeof contentOrComponent !== 'string' && !component) {
34
+ base = this.build(base, null, contentOrComponent);
35
+ }
36
+ // Cas 3: content and component not null
37
+ if (contentOrComponent && typeof contentOrComponent === 'string' && component) {
38
+ base = this.build(base, contentOrComponent, component);
39
+ }
40
+ if (ephemeral) {
41
+ base.flags = [discord_js_1.MessageFlags.Ephemeral];
42
+ }
43
+ return base;
44
+ }
45
+ static buildMessage(contentOrComponent, component) {
46
+ let base = {};
47
+ // Case 1
48
+ if (typeof contentOrComponent === 'string' && !component) {
49
+ return this.build(base, contentOrComponent);
50
+ }
51
+ // Case 2
52
+ if (typeof contentOrComponent !== 'string' && !component) {
53
+ return this.build(base, null, contentOrComponent);
54
+ }
55
+ // Case 3
56
+ if (typeof contentOrComponent == 'string' && component) {
57
+ return this.build(base, contentOrComponent, component);
58
+ }
59
+ throw new Error("At least content or component need to be defined to build a message");
60
+ }
61
+ }
62
+ exports.SendableComponentBuilder = SendableComponentBuilder;
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.UserManager = void 0;
4
4
  const Bot_1 = require("../../bot/Bot");
5
5
  const Log_1 = require("../../utils/Log");
6
+ const SendableComponentBuilder_1 = require("../builder/SendableComponentBuilder");
6
7
  class UserManager {
7
8
  /**
8
9
  * Find a member
@@ -50,7 +51,7 @@ class UserManager {
50
51
  /**
51
52
  * Impl
52
53
  */
53
- static async send(user_id_or_user, content_or_options) {
54
+ static async send(user_id_or_user, content_or_component_or_options, component) {
54
55
  try {
55
56
  let user;
56
57
  if (typeof user_id_or_user === 'string') {
@@ -60,11 +61,21 @@ class UserManager {
60
61
  user = user_id_or_user;
61
62
  }
62
63
  const dmChannel = await user.createDM();
63
- const payload = typeof content_or_options === 'string'
64
- ? { content: content_or_options }
65
- : content_or_options;
64
+ let payload;
65
+ if (component && typeof content_or_component_or_options == "string") { // component + content
66
+ payload = SendableComponentBuilder_1.SendableComponentBuilder.buildMessage(content_or_component_or_options, component);
67
+ }
68
+ else if (typeof content_or_component_or_options === 'string') { // content only
69
+ payload = SendableComponentBuilder_1.SendableComponentBuilder.buildMessage(content_or_component_or_options);
70
+ }
71
+ else if (SendableComponentBuilder_1.SendableComponentBuilder.isSendableComponent(content_or_component_or_options)) { // component only
72
+ payload = SendableComponentBuilder_1.SendableComponentBuilder.buildMessage(content_or_component_or_options);
73
+ }
74
+ else { // MessageCreationOptionOnly
75
+ payload = content_or_component_or_options;
76
+ }
66
77
  const message = await dmChannel.send(payload);
67
- Log_1.Log.info(`Sent DM to ${user.id} (${user.username}): "${(payload.content || 'Embed').substring(0, 50)}..."`);
78
+ Log_1.Log.info(`Sent DM to ${user.id} (${user.username}): "${(payload.content || 'Embed/Component').substring(0, 50)}..."`);
68
79
  return message;
69
80
  }
70
81
  catch (error) {
@@ -3,20 +3,28 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.GuildMessageManager = void 0;
4
4
  const GuildTextChannelManager_1 = require("./GuildTextChannelManager");
5
5
  const Log_1 = require("../../../utils/Log");
6
+ const SendableComponentBuilder_1 = require("../../builder/SendableComponentBuilder");
6
7
  class GuildMessageManager {
7
8
  /**
8
9
  * Impl
9
10
  */
10
- static async send(channelId, content_or_options) {
11
+ static async send(channelId, content_or_component_or_options) {
11
12
  try {
12
13
  const channel = await GuildTextChannelManager_1.GuildTextChannelManager.find(channelId);
13
14
  if (!channel) {
14
15
  Log_1.Log.error(`Channel ${channelId} not found in guild`);
15
16
  return null;
16
17
  }
17
- const payload = typeof content_or_options === 'string'
18
- ? { content: content_or_options }
19
- : content_or_options;
18
+ let payload;
19
+ if (typeof content_or_component_or_options === 'string') {
20
+ payload = SendableComponentBuilder_1.SendableComponentBuilder.buildMessage(content_or_component_or_options);
21
+ }
22
+ else if (SendableComponentBuilder_1.SendableComponentBuilder.isSendableComponent(content_or_component_or_options) || Array.isArray(content_or_component_or_options)) {
23
+ payload = SendableComponentBuilder_1.SendableComponentBuilder.buildMessage(content_or_component_or_options);
24
+ }
25
+ else {
26
+ payload = content_or_component_or_options;
27
+ }
20
28
  return await channel.send(payload);
21
29
  }
22
30
  catch (error) {
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.ThreadChannelManager = void 0;
4
4
  const GuildChannelManager_1 = require("./GuildChannelManager");
5
5
  const GuildTextChannelManager_1 = require("./GuildTextChannelManager");
6
+ const SendableComponentBuilder_1 = require("../../builder/SendableComponentBuilder");
6
7
  class ThreadChannelManager {
7
8
  static async findInGuild(guildId, channelId) {
8
9
  const channel = await GuildChannelManager_1.GuildChannelManager.findInGuild(guildId, channelId);
@@ -30,5 +31,19 @@ class ThreadChannelManager {
30
31
  throw new Error('Message channel not found');
31
32
  return await message.startThread(options);
32
33
  }
34
+ /**
35
+ * Impl
36
+ */
37
+ static async send(channelId, content_or_component_or_options) {
38
+ if (typeof content_or_component_or_options == 'string') {
39
+ return await GuildTextChannelManager_1.GuildTextChannelManager.message.send(channelId, content_or_component_or_options);
40
+ }
41
+ else if (SendableComponentBuilder_1.SendableComponentBuilder.isSendableComponent(content_or_component_or_options) || Array.isArray(content_or_component_or_options)) {
42
+ return await GuildTextChannelManager_1.GuildTextChannelManager.message.send(channelId, content_or_component_or_options);
43
+ }
44
+ else {
45
+ return await GuildTextChannelManager_1.GuildTextChannelManager.message.send(channelId, content_or_component_or_options);
46
+ }
47
+ }
33
48
  }
34
49
  exports.ThreadChannelManager = ThreadChannelManager;
@@ -0,0 +1,68 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.InteractionManager = void 0;
4
+ const SendableComponentBuilder_1 = require("../builder/SendableComponentBuilder");
5
+ class InteractionManager {
6
+ /**
7
+ * InteractionReplyOptions && InteractionUpdateOptions
8
+ * The two have "content", "embeds" & "flags" field, so an internal cast is ok, unless discord/discordjs deprecate it
9
+ */
10
+ static buildReplyOptions(content, component, ephemeral) {
11
+ return this._buildOptions(content, component, ephemeral);
12
+ }
13
+ static buildUpdateOptions(content, component) {
14
+ return this._buildOptions(content, component, false);
15
+ }
16
+ static _buildOptions(content, component, ephemeral) {
17
+ return SendableComponentBuilder_1.SendableComponentBuilder.buildInteraction(content, component, ephemeral);
18
+ }
19
+ static async send(interaction, content, component, ephemeral = false) {
20
+ if (!interaction.isRepliable())
21
+ return false;
22
+ const options = this.buildReplyOptions(content, component, ephemeral);
23
+ if (!interaction.deferred && !interaction.replied) {
24
+ return await interaction.reply(options);
25
+ }
26
+ else {
27
+ return await interaction.followUp(options);
28
+ }
29
+ }
30
+ static async reply(interaction, content, component, ephemeral = false) {
31
+ return await this.send(interaction, content, component, ephemeral);
32
+ }
33
+ static async followUp(interaction, content, component, ephemeral = false) {
34
+ return await this.send(interaction, content, component, ephemeral);
35
+ }
36
+ static async defer(interaction) {
37
+ if (!interaction.isRepliable())
38
+ return;
39
+ if (interaction.isChatInputCommand() || interaction.isContextMenuCommand()) {
40
+ if (!interaction.deferred && !interaction.replied) {
41
+ await interaction.deferReply();
42
+ }
43
+ return;
44
+ }
45
+ if (interaction.isButton() ||
46
+ interaction.isAnySelectMenu() ||
47
+ interaction.isModalSubmit()) {
48
+ if (!interaction.deferred && !interaction.replied) {
49
+ await interaction.deferUpdate();
50
+ }
51
+ }
52
+ }
53
+ static async update(interaction, content, component) {
54
+ if (!interaction.isRepliable())
55
+ return;
56
+ const options = this.buildUpdateOptions(content, component);
57
+ // MessageComponent → update()
58
+ if (interaction.isMessageComponent()) {
59
+ await interaction.update(options);
60
+ return;
61
+ }
62
+ // Slash commands → editReply()
63
+ if (interaction.deferred || interaction.replied) {
64
+ await interaction.editReply(options);
65
+ }
66
+ }
67
+ }
68
+ exports.InteractionManager = InteractionManager;
@@ -2,8 +2,8 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.ModalManager = void 0;
4
4
  const discord_js_1 = require("discord.js");
5
- const FolderName_1 = require("../../../type/FolderName");
6
- const FileManager_1 = require("../../FileManager");
5
+ const FolderName_1 = require("../../type/FolderName");
6
+ const FileManager_1 = require("../FileManager");
7
7
  class ModalManager {
8
8
  /**
9
9
  * Load modal from JSON file and return ModalBuilder
@@ -0,0 +1,123 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SelectMenuManager = void 0;
4
+ const discord_js_1 = require("discord.js");
5
+ class SelectMenuManager {
6
+ /**
7
+ * Creates base StringSelectMenu - SIMPLE API !
8
+ */
9
+ static create(customId, placeholder = "Select an option...") {
10
+ return new discord_js_1.StringSelectMenuBuilder()
11
+ .setCustomId(customId)
12
+ .setPlaceholder(placeholder)
13
+ .setMinValues(1)
14
+ .setMaxValues(1);
15
+ }
16
+ /**
17
+ * Quick StringSelectMenu
18
+ */
19
+ static simple(customId, options, placeholder = "Choose an option") {
20
+ const menu = this.create(customId, placeholder);
21
+ menu.addOptions(options.map(opt => {
22
+ return this.option(opt);
23
+ }));
24
+ return menu;
25
+ }
26
+ /**
27
+ * Pagination menu
28
+ */
29
+ static paginated(customId, options, pageSize = 25) {
30
+ const row = new discord_js_1.ActionRowBuilder();
31
+ for (let i = 0; i < options.length; i += pageSize) {
32
+ const pageOptions = options.slice(i, i + pageSize);
33
+ const menu = new discord_js_1.StringSelectMenuBuilder()
34
+ .setCustomId(`${customId}_page_${Math.floor(i / pageSize)}`)
35
+ .setPlaceholder(`Page ${Math.floor(i / pageSize) + 1}`)
36
+ .addOptions(pageOptions.map(opt => {
37
+ return this.option(opt);
38
+ }));
39
+ row.addComponents(menu);
40
+ }
41
+ return row;
42
+ }
43
+ /**
44
+ * User Select Menu (Components V2)
45
+ */
46
+ static users(customId, placeholder = "Select users...") {
47
+ return new discord_js_1.UserSelectMenuBuilder()
48
+ .setCustomId(customId)
49
+ .setPlaceholder(placeholder)
50
+ .setMinValues(1)
51
+ .setMaxValues(25);
52
+ }
53
+ /**
54
+ * Role Select Menu (Components V2)
55
+ */
56
+ static roles(customId, placeholder = "Select roles...") {
57
+ return new discord_js_1.RoleSelectMenuBuilder()
58
+ .setCustomId(customId)
59
+ .setPlaceholder(placeholder)
60
+ .setMinValues(1)
61
+ .setMaxValues(25);
62
+ }
63
+ /**
64
+ * Mentionable Select Menu (Components V2)
65
+ */
66
+ static mentionables(customId, placeholder = "Select users/roles...") {
67
+ return new discord_js_1.MentionableSelectMenuBuilder()
68
+ .setCustomId(customId)
69
+ .setPlaceholder(placeholder)
70
+ .setMinValues(1)
71
+ .setMaxValues(25);
72
+ }
73
+ /**
74
+ * Channel Select Menu (Components V2)
75
+ */
76
+ static channels(customId, placeholder = "Select channels...", channelTypes = []) {
77
+ return new discord_js_1.ChannelSelectMenuBuilder()
78
+ .setCustomId(customId)
79
+ .setPlaceholder(placeholder)
80
+ .setMinValues(1)
81
+ .setMaxValues(25)
82
+ .setChannelTypes(...channelTypes);
83
+ }
84
+ static option(option) {
85
+ if (Array.isArray(option)) {
86
+ return option.map((opt) => this._createOption(opt));
87
+ }
88
+ return this._createOption(option);
89
+ }
90
+ static _createOption(option) {
91
+ const builder = new discord_js_1.StringSelectMenuOptionBuilder()
92
+ .setLabel(option.label)
93
+ .setValue(option.value);
94
+ option.description && builder.setDescription(option.description);
95
+ option.emoji && builder.setEmoji(option.emoji);
96
+ return builder;
97
+ }
98
+ /**
99
+ * Fluent API pour personnaliser
100
+ */
101
+ static placeholder(menu, placeholder) {
102
+ return menu.setPlaceholder(placeholder);
103
+ }
104
+ static minMax(menu, min, max) {
105
+ return menu.setMinValues(min).setMaxValues(Math.min(max, 25));
106
+ }
107
+ static disabled(menu, disabled) {
108
+ return menu.setDisabled(disabled);
109
+ }
110
+ /**
111
+ * ActionRow
112
+ */
113
+ static row(component) {
114
+ return new discord_js_1.ActionRowBuilder().addComponents(component);
115
+ }
116
+ /**
117
+ * Rows multiples (5 max)
118
+ */
119
+ static rows(...components) {
120
+ return components.slice(0, 5).map(component => this.row(component));
121
+ }
122
+ }
123
+ exports.SelectMenuManager = SelectMenuManager;