js-discord-modularcommand 2.5.0 → 2.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/README.md +252 -35
- package/package.json +5 -1
package/README.md
CHANGED
|
@@ -1,69 +1,286 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Discord.js Modular Command
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[](https://www.npmjs.com/package/js-discord-modularcommand)
|
|
4
|
+
[](https://opensource.org/licenses/MIT)
|
|
4
5
|
|
|
5
|
-
|
|
6
|
+
A powerful and elegant library for creating modular, feature-rich slash commands for your [Discord.js](https://discord.js.org/) bot.
|
|
6
7
|
|
|
7
|
-
|
|
8
|
+
`js-discord-modularcommand` simplifies command management by providing a clean, chainable structure for defining commands, handling interactions, and managing localizations. Move away from boilerplate code and focus on what truly matters: your bot's logic.
|
|
8
9
|
|
|
9
|
-
##
|
|
10
|
+
## Features
|
|
10
11
|
|
|
11
|
-
|
|
12
|
+
- **Modular by Design:** Structure each command in its own file for a clean and scalable project architecture.
|
|
13
|
+
- **Effortless Localization:** Built-in support for multiple languages for command descriptions, options, and in-command responses.
|
|
14
|
+
- **Interactive Components Made Easy:** Fluent builders for creating and managing Buttons, Modals, and Select Menus with their own handlers, all within the command's context.
|
|
15
|
+
- **Chainable Configuration:** Use a fluent, chainable API to configure every aspect of your command, from descriptions and options to permissions and cooldowns.
|
|
16
|
+
- **Simplified Handlers:** The library abstracts away the complexity of handling different interaction types. You just provide the logic.
|
|
17
|
+
|
|
18
|
+
## Installation
|
|
19
|
+
|
|
20
|
+
Install the package using npm or your favorite package manager:
|
|
12
21
|
|
|
13
22
|
```sh
|
|
14
|
-
npm install js-discord-modularcommand
|
|
23
|
+
npm install js-discord-modularcommand
|
|
15
24
|
```
|
|
16
25
|
|
|
17
|
-
|
|
26
|
+
## Getting Started
|
|
27
|
+
|
|
28
|
+
The core of the library is the `ModularCommand` class. You create an instance of it for each command and chain methods to configure it.
|
|
29
|
+
|
|
30
|
+
Here is a basic example of a `ping` command:
|
|
18
31
|
|
|
19
32
|
```javascript
|
|
20
|
-
// filepath: commands/ping.js
|
|
33
|
+
// filepath: /commands/ping.js
|
|
21
34
|
const { ModularCommand, RegisterCommand } = require('js-discord-modularcommand');
|
|
22
|
-
const {
|
|
35
|
+
const { Locale } = require('discord.js');
|
|
36
|
+
|
|
37
|
+
// 1. Create a new command instance
|
|
38
|
+
const pingCommand = new ModularCommand('ping');
|
|
23
39
|
|
|
24
|
-
//
|
|
25
|
-
|
|
40
|
+
// 2. Configure the command using chainable methods
|
|
41
|
+
pingCommand.setDescription('Replies with Pong!')
|
|
26
42
|
|
|
27
|
-
// Set
|
|
28
|
-
|
|
43
|
+
// Optional: Set a 5-second cooldown
|
|
44
|
+
pingCommand.setCooldown(5)
|
|
45
|
+
|
|
46
|
+
// Optional: Add localized descriptions for the command itself
|
|
47
|
+
pingCommand.setLocalizationDescription({
|
|
48
|
+
[Locale.EnglishUS]: 'Replies with Pong!',
|
|
49
|
+
[Locale.SpanishLATAM]: '¡Responde con Pong!',
|
|
50
|
+
})
|
|
51
|
+
|
|
52
|
+
// Optional: Define response phrases for different languages
|
|
53
|
+
pingCommand.setLocalizationPhrases({
|
|
54
|
+
[Locale.EnglishUS]: {
|
|
55
|
+
'pong_reply': 'Pong! 🏓',
|
|
56
|
+
},
|
|
57
|
+
[Locale.SpanishLATAM]: {
|
|
58
|
+
'pong_reply': '¡Pong! 🏓',
|
|
59
|
+
}
|
|
60
|
+
})
|
|
29
61
|
|
|
30
|
-
//
|
|
31
|
-
|
|
32
|
-
|
|
62
|
+
// 3. Define the execution logic
|
|
63
|
+
// The 'locale' object contains the phrases for the user's language
|
|
64
|
+
pingCommand.setExecute(async ({ interaction, locale }) => {
|
|
65
|
+
await interaction.reply({
|
|
66
|
+
content: locale['pong_reply']
|
|
67
|
+
});
|
|
33
68
|
});
|
|
34
69
|
|
|
35
|
-
//
|
|
36
|
-
|
|
70
|
+
// 4. Export the command for the handler
|
|
71
|
+
module.exports = RegisterCommand(pingCommand);
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## Advanced Usage: Interactive Components
|
|
75
|
+
|
|
76
|
+
Easily add interactive components to your commands.
|
|
77
|
+
|
|
78
|
+
### Buttons
|
|
79
|
+
|
|
80
|
+
Create buttons and attach specific logic to each one.
|
|
81
|
+
|
|
82
|
+
```javascript
|
|
83
|
+
// filepath: /commands/vote.js
|
|
84
|
+
const { ModularCommand, RegisterCommand } = require('js-discord-modularcommand');
|
|
85
|
+
const { ButtonStyle, Locale, MessageFlags } = require('discord.js');
|
|
86
|
+
const { ActionRowBuilder } = require('@discordjs/builders');
|
|
87
|
+
|
|
88
|
+
const voteCommand = new ModularCommand('votecommand');
|
|
89
|
+
|
|
90
|
+
voteCommand.setDescription('Starts a simple poll.');
|
|
91
|
+
|
|
92
|
+
voteCommand.setLocalizationPhrases({
|
|
37
93
|
[Locale.EnglishUS]: {
|
|
38
|
-
|
|
94
|
+
'poll_question': 'What is your favorite color?',
|
|
95
|
+
'votecommand.yes': 'Green',
|
|
96
|
+
'votecommand.no': 'Blue',
|
|
97
|
+
'reply.yes': 'You voted for Green!',
|
|
98
|
+
'reply.no': 'You voted for Blue!',
|
|
39
99
|
},
|
|
40
100
|
[Locale.SpanishLATAM]: {
|
|
41
|
-
|
|
101
|
+
'poll_question': '¿Cuál es tu color favorito?',
|
|
102
|
+
'votecommand.yes': 'Verde',
|
|
103
|
+
'votecommand.no': 'Azul',
|
|
104
|
+
'reply.yes': '¡Has votado por el Verde!',
|
|
105
|
+
'reply.no': '¡Has votado por el Azul!',
|
|
42
106
|
}
|
|
43
107
|
});
|
|
44
108
|
|
|
45
|
-
//
|
|
46
|
-
|
|
109
|
+
// Create and handle the "Yes" button
|
|
110
|
+
const yesButton = voteCommand.addButton('yes', async ({ interaction, locale }) => {
|
|
111
|
+
await interaction.reply({
|
|
112
|
+
content: locale['reply.yes'],
|
|
113
|
+
flags: MessageFlags.Ephemeral
|
|
114
|
+
});
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
// Create and handle the "No" button
|
|
118
|
+
const noButton = voteCommand.addButton('no', async ({ interaction, locale }) => {
|
|
119
|
+
await interaction.reply({
|
|
120
|
+
content: locale['reply.no'],
|
|
121
|
+
flags: MessageFlags.Ephemeral
|
|
122
|
+
});
|
|
123
|
+
});
|
|
47
124
|
|
|
48
|
-
//
|
|
49
|
-
|
|
125
|
+
// Customize the underlying discord.js button
|
|
126
|
+
yesButton.getButton().setStyle(ButtonStyle.Success);
|
|
127
|
+
noButton.getButton().setStyle(ButtonStyle.Primary);
|
|
50
128
|
|
|
51
|
-
//
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
129
|
+
// Main command execution: sends the message with the buttons
|
|
130
|
+
voteCommand.setExecute(async ({ interaction, locale }) => {
|
|
131
|
+
const row = new ActionRowBuilder();
|
|
132
|
+
|
|
133
|
+
row.addComponents(
|
|
134
|
+
yesButton.build(locale), // .build(locale) applies the correct localization
|
|
135
|
+
noButton.build(locale)
|
|
136
|
+
);
|
|
137
|
+
|
|
138
|
+
await interaction.reply({
|
|
139
|
+
content: locale['poll_question'],
|
|
140
|
+
components: [row]
|
|
141
|
+
});
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
module.exports = RegisterCommand(voteCommand);
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
### Select Menus
|
|
148
|
+
|
|
149
|
+
Build and handle string select menus seamlessly.
|
|
150
|
+
|
|
151
|
+
```javascript
|
|
152
|
+
// filepath: /commands/starter.js
|
|
153
|
+
const { ModularCommand, RegisterCommand } = require('js-discord-modularcommand');
|
|
154
|
+
const { ActionRowBuilder } = require('@discordjs/builders');
|
|
155
|
+
const { Locale, MessageFlags } = require('discord.js');
|
|
156
|
+
|
|
157
|
+
const starterCommand = new ModularCommand('starter');
|
|
158
|
+
|
|
159
|
+
starterCommand.setDescription('Choose your starter Pokémon.')
|
|
160
|
+
|
|
161
|
+
starterCommand.setLocalizationPhrases({
|
|
162
|
+
[Locale.EnglishUS]: {
|
|
163
|
+
'select_prompt': 'Please select your starter:',
|
|
164
|
+
'menuselection.placeholder': 'Make a selection!',
|
|
165
|
+
'menuselection.bulbasaur.label': 'Bulbasaur',
|
|
166
|
+
'menuselection.bulbasaur.description': 'The Seed Pokémon.',
|
|
167
|
+
'menuselection.charmander.label': 'Charmander',
|
|
168
|
+
'menuselection.charmander.description': 'The Lizard Pokémon.',
|
|
169
|
+
'menuselection.squirtle.label': 'Squirtle',
|
|
170
|
+
'menuselection.squirtle.description': 'The Tiny Turtle Pokémon.',
|
|
171
|
+
'response': 'You chose {selection}!',
|
|
172
|
+
},
|
|
173
|
+
[Locale.SpanishLATAM]: {
|
|
174
|
+
'select_prompt': 'Por favor, elige tu inicial:',
|
|
175
|
+
'menuselection.placeholder': '¡Haz una selección!',
|
|
176
|
+
'menuselection.bulbasaur.label': 'Bulbasaur',
|
|
177
|
+
'menuselection.bulbasaur.description': 'El Pokémon Semilla.',
|
|
178
|
+
'menuselection.charmander.label': 'Charmander',
|
|
179
|
+
'menuselection.charmander.description': 'El Pokémon Lagartija.',
|
|
180
|
+
'menuselection.squirtle.label': 'Squirtle',
|
|
181
|
+
'menuselection.squirtle.description': 'El Pokémon Agua.',
|
|
182
|
+
'response': '¡Elegiste a {selection}!',
|
|
183
|
+
}
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
const starterMenu = starterCommand.addSelectMenu('menuselection');
|
|
187
|
+
|
|
188
|
+
// Value must match the key in localization phrases
|
|
189
|
+
starterMenu.addOption('bulbasaur')
|
|
190
|
+
starterMenu.addOption('charmander')
|
|
191
|
+
starterMenu.addOption('squirtle')
|
|
192
|
+
|
|
193
|
+
starterMenu.setExecute(async ({ interaction, selected, locale }) => {
|
|
194
|
+
// 'selected' directly gives you the value of the chosen option
|
|
195
|
+
const selectionLabel = locale[`menuselection.${selected}.label`];
|
|
196
|
+
await interaction.update({
|
|
197
|
+
content: locale['response'].replace('{selection}', selectionLabel),
|
|
198
|
+
components: [] // Remove menu after selection
|
|
199
|
+
});
|
|
55
200
|
});
|
|
56
201
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
202
|
+
starterCommand.setExecute(async ({ interaction, locale }) => {
|
|
203
|
+
const row = new ActionRowBuilder()
|
|
204
|
+
row.addComponents(starterMenu.build(locale));
|
|
205
|
+
|
|
206
|
+
await interaction.reply({
|
|
207
|
+
content: locale['select_prompt'],
|
|
208
|
+
components: [row],
|
|
209
|
+
flags: MessageFlags.Ephemeral
|
|
210
|
+
});
|
|
60
211
|
});
|
|
61
212
|
|
|
62
|
-
module.exports = RegisterCommand(
|
|
213
|
+
module.exports = RegisterCommand(starterCommand);
|
|
63
214
|
```
|
|
64
215
|
|
|
65
|
-
|
|
216
|
+
### Modals (Pop-up Forms)
|
|
217
|
+
|
|
218
|
+
Display pop-up forms to collect detailed user input.
|
|
219
|
+
|
|
220
|
+
```javascript
|
|
221
|
+
// filepath: /commands/feedback.js
|
|
222
|
+
const { ModularCommand, RegisterCommand } = require('js-discord-modularcommand');
|
|
223
|
+
const { TextInputStyle, Locale, MessageFlags } = require('discord.js');
|
|
224
|
+
|
|
225
|
+
const feedbackCommand = new ModularCommand('feedback');
|
|
226
|
+
|
|
227
|
+
feedbackCommand.setDescription('Submit feedback about the bot.')
|
|
228
|
+
|
|
229
|
+
feedbackCommand.setLocalizationPhrases({
|
|
230
|
+
[Locale.EnglishUS]: {
|
|
231
|
+
'form.title': 'Feedback Form',
|
|
232
|
+
'form.subject.label': 'Subject',
|
|
233
|
+
'form.subject.placeholder': 'e.g., Feature Request',
|
|
234
|
+
'form.message.label': 'Message',
|
|
235
|
+
'form.message.placeholder': 'Your detailed feedback here...',
|
|
236
|
+
'success_reply': 'Thank you for your feedback!',
|
|
237
|
+
},
|
|
238
|
+
[Locale.SpanishLATAM]: {
|
|
239
|
+
'form.title': 'Formulario de Comentarios',
|
|
240
|
+
'form.subject.label': 'Asunto',
|
|
241
|
+
'form.subject.placeholder': 'Ej: Solicitud de función',
|
|
242
|
+
'form.message.label': 'Mensaje',
|
|
243
|
+
'form.message.placeholder': 'Tus comentarios detallados aquí...',
|
|
244
|
+
'success_reply': '¡Gracias por tus comentarios!',
|
|
245
|
+
}
|
|
246
|
+
});
|
|
247
|
+
|
|
248
|
+
const feedbackModal = feedbackCommand.addModal('form');
|
|
249
|
+
|
|
250
|
+
// Define text inputs
|
|
251
|
+
const subjectInput = feedbackModal.newTextInput('subject')
|
|
252
|
+
.setStyle(TextInputStyle.Short)
|
|
253
|
+
.setRequired(true)
|
|
254
|
+
.data
|
|
255
|
+
.custom_id;
|
|
256
|
+
|
|
257
|
+
const messageInput = feedbackModal.newTextInput('message')
|
|
258
|
+
.setStyle(TextInputStyle.Paragraph)
|
|
259
|
+
.setRequired(true)
|
|
260
|
+
.data
|
|
261
|
+
.custom_id;
|
|
262
|
+
|
|
263
|
+
// This function runs when the user submits the modal
|
|
264
|
+
feedbackModal.setExecute(async ({ interaction, args, locale }) => {
|
|
265
|
+
const subject = args[subjectInput];
|
|
266
|
+
const message = args[messageInput];
|
|
267
|
+
|
|
268
|
+
// Process the data
|
|
269
|
+
console.log(`New Feedback: ${subject} - ${message}`);
|
|
270
|
+
await interaction.reply({
|
|
271
|
+
content: locale['success_reply'],
|
|
272
|
+
flags: MessageFlags.Ephemeral
|
|
273
|
+
});
|
|
274
|
+
});
|
|
275
|
+
|
|
276
|
+
// This function runs when the /feedback command is used, showing the modal
|
|
277
|
+
feedbackCommand.setExecute(async ({ interaction, locale }) => {
|
|
278
|
+
await interaction.showModal(feedbackModal.build(locale));
|
|
279
|
+
});
|
|
280
|
+
|
|
281
|
+
module.exports = RegisterCommand(feedbackCommand);
|
|
282
|
+
```
|
|
66
283
|
|
|
67
284
|
## License
|
|
68
285
|
|
|
69
|
-
This project is under the MIT License. See the
|
|
286
|
+
This project is licensed under the MIT License. See the `LICENSE` file for details.
|
package/package.json
CHANGED
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "js-discord-modularcommand",
|
|
3
|
-
"version": "2.5.
|
|
3
|
+
"version": "2.5.2",
|
|
4
4
|
"description": "",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"discord",
|
|
7
7
|
"js",
|
|
8
8
|
"node"
|
|
9
9
|
],
|
|
10
|
+
"repository": {
|
|
11
|
+
"type": "git",
|
|
12
|
+
"url": "https://github.com/vicentefelipechile/js-discord-modularcommand.git"
|
|
13
|
+
},
|
|
10
14
|
"license": "MIT",
|
|
11
15
|
"author": "vicentefelipechile",
|
|
12
16
|
"type": "commonjs",
|