chub-dev 0.1.0 → 0.1.2-beta.0

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 (139) hide show
  1. package/README.md +55 -0
  2. package/bin/chub-mcp +2 -0
  3. package/dist/airtable/docs/database/javascript/DOC.md +1437 -0
  4. package/dist/airtable/docs/database/python/DOC.md +1735 -0
  5. package/dist/amplitude/docs/analytics/javascript/DOC.md +1282 -0
  6. package/dist/amplitude/docs/analytics/python/DOC.md +1199 -0
  7. package/dist/anthropic/docs/claude-api/javascript/DOC.md +503 -0
  8. package/dist/anthropic/docs/claude-api/python/DOC.md +389 -0
  9. package/dist/asana/docs/tasks/DOC.md +1396 -0
  10. package/dist/assemblyai/docs/transcription/DOC.md +1043 -0
  11. package/dist/atlassian/docs/confluence/javascript/DOC.md +1347 -0
  12. package/dist/atlassian/docs/confluence/python/DOC.md +1604 -0
  13. package/dist/auth0/docs/identity/javascript/DOC.md +968 -0
  14. package/dist/auth0/docs/identity/python/DOC.md +1199 -0
  15. package/dist/aws/docs/s3/javascript/DOC.md +1773 -0
  16. package/dist/aws/docs/s3/python/DOC.md +1807 -0
  17. package/dist/binance/docs/trading/javascript/DOC.md +1315 -0
  18. package/dist/binance/docs/trading/python/DOC.md +1454 -0
  19. package/dist/braintree/docs/gateway/javascript/DOC.md +1278 -0
  20. package/dist/braintree/docs/gateway/python/DOC.md +1179 -0
  21. package/dist/chromadb/docs/embeddings-db/javascript/DOC.md +1263 -0
  22. package/dist/chromadb/docs/embeddings-db/python/DOC.md +1707 -0
  23. package/dist/clerk/docs/auth/javascript/DOC.md +1220 -0
  24. package/dist/clerk/docs/auth/python/DOC.md +274 -0
  25. package/dist/cloudflare/docs/workers/javascript/DOC.md +918 -0
  26. package/dist/cloudflare/docs/workers/python/DOC.md +994 -0
  27. package/dist/cockroachdb/docs/distributed-db/DOC.md +1500 -0
  28. package/dist/cohere/docs/llm/DOC.md +1335 -0
  29. package/dist/datadog/docs/monitoring/javascript/DOC.md +1740 -0
  30. package/dist/datadog/docs/monitoring/python/DOC.md +1815 -0
  31. package/dist/deepgram/docs/speech/javascript/DOC.md +885 -0
  32. package/dist/deepgram/docs/speech/python/DOC.md +685 -0
  33. package/dist/deepl/docs/translation/javascript/DOC.md +887 -0
  34. package/dist/deepl/docs/translation/python/DOC.md +944 -0
  35. package/dist/deepseek/docs/llm/DOC.md +1220 -0
  36. package/dist/directus/docs/headless-cms/javascript/DOC.md +1128 -0
  37. package/dist/directus/docs/headless-cms/python/DOC.md +1276 -0
  38. package/dist/discord/docs/bot/javascript/DOC.md +1090 -0
  39. package/dist/discord/docs/bot/python/DOC.md +1130 -0
  40. package/dist/elasticsearch/docs/search/DOC.md +1634 -0
  41. package/dist/elevenlabs/docs/text-to-speech/javascript/DOC.md +336 -0
  42. package/dist/elevenlabs/docs/text-to-speech/python/DOC.md +552 -0
  43. package/dist/firebase/docs/auth/DOC.md +1015 -0
  44. package/dist/gemini/docs/genai/javascript/DOC.md +691 -0
  45. package/dist/gemini/docs/genai/python/DOC.md +555 -0
  46. package/dist/github/docs/octokit/DOC.md +1560 -0
  47. package/dist/google/docs/bigquery/javascript/DOC.md +1688 -0
  48. package/dist/google/docs/bigquery/python/DOC.md +1503 -0
  49. package/dist/hubspot/docs/crm/javascript/DOC.md +1805 -0
  50. package/dist/hubspot/docs/crm/python/DOC.md +2033 -0
  51. package/dist/huggingface/docs/transformers/DOC.md +948 -0
  52. package/dist/intercom/docs/messaging/javascript/DOC.md +1844 -0
  53. package/dist/intercom/docs/messaging/python/DOC.md +1797 -0
  54. package/dist/jira/docs/issues/javascript/DOC.md +1420 -0
  55. package/dist/jira/docs/issues/python/DOC.md +1492 -0
  56. package/dist/kafka/docs/streaming/javascript/DOC.md +1671 -0
  57. package/dist/kafka/docs/streaming/python/DOC.md +1464 -0
  58. package/dist/landingai-ade/docs/api/DOC.md +620 -0
  59. package/dist/landingai-ade/docs/sdk/python/DOC.md +489 -0
  60. package/dist/landingai-ade/docs/sdk/typescript/DOC.md +542 -0
  61. package/dist/landingai-ade/skills/SKILL.md +489 -0
  62. package/dist/launchdarkly/docs/feature-flags/javascript/DOC.md +1191 -0
  63. package/dist/launchdarkly/docs/feature-flags/python/DOC.md +1671 -0
  64. package/dist/linear/docs/tracker/DOC.md +1554 -0
  65. package/dist/livekit/docs/realtime/javascript/DOC.md +303 -0
  66. package/dist/livekit/docs/realtime/python/DOC.md +163 -0
  67. package/dist/mailchimp/docs/marketing/DOC.md +1420 -0
  68. package/dist/meilisearch/docs/search/DOC.md +1241 -0
  69. package/dist/microsoft/docs/onedrive/javascript/DOC.md +1421 -0
  70. package/dist/microsoft/docs/onedrive/python/DOC.md +1549 -0
  71. package/dist/mongodb/docs/atlas/DOC.md +2041 -0
  72. package/dist/notion/docs/workspace-api/javascript/DOC.md +1435 -0
  73. package/dist/notion/docs/workspace-api/python/DOC.md +1400 -0
  74. package/dist/okta/docs/identity/javascript/DOC.md +1171 -0
  75. package/dist/okta/docs/identity/python/DOC.md +1401 -0
  76. package/dist/openai/docs/chat/javascript/DOC.md +407 -0
  77. package/dist/openai/docs/chat/python/DOC.md +568 -0
  78. package/dist/paypal/docs/checkout/DOC.md +278 -0
  79. package/dist/pinecone/docs/sdk/javascript/DOC.md +984 -0
  80. package/dist/pinecone/docs/sdk/python/DOC.md +1395 -0
  81. package/dist/plaid/docs/banking/javascript/DOC.md +1163 -0
  82. package/dist/plaid/docs/banking/python/DOC.md +1203 -0
  83. package/dist/playwright-community/skills/login-flows/SKILL.md +108 -0
  84. package/dist/postmark/docs/transactional-email/DOC.md +1168 -0
  85. package/dist/prisma/docs/orm/javascript/DOC.md +1419 -0
  86. package/dist/prisma/docs/orm/python/DOC.md +1317 -0
  87. package/dist/qdrant/docs/vector-search/javascript/DOC.md +1221 -0
  88. package/dist/qdrant/docs/vector-search/python/DOC.md +1653 -0
  89. package/dist/rabbitmq/docs/message-queue/javascript/DOC.md +1193 -0
  90. package/dist/rabbitmq/docs/message-queue/python/DOC.md +1243 -0
  91. package/dist/razorpay/docs/payments/javascript/DOC.md +1219 -0
  92. package/dist/razorpay/docs/payments/python/DOC.md +1330 -0
  93. package/dist/redis/docs/key-value/javascript/DOC.md +1851 -0
  94. package/dist/redis/docs/key-value/python/DOC.md +2054 -0
  95. package/dist/registry.json +2817 -0
  96. package/dist/replicate/docs/model-hosting/DOC.md +1318 -0
  97. package/dist/resend/docs/email/DOC.md +1271 -0
  98. package/dist/salesforce/docs/crm/javascript/DOC.md +1241 -0
  99. package/dist/salesforce/docs/crm/python/DOC.md +1183 -0
  100. package/dist/search-index.json +1 -0
  101. package/dist/sendgrid/docs/email-api/javascript/DOC.md +371 -0
  102. package/dist/sendgrid/docs/email-api/python/DOC.md +656 -0
  103. package/dist/sentry/docs/error-tracking/javascript/DOC.md +1073 -0
  104. package/dist/sentry/docs/error-tracking/python/DOC.md +1309 -0
  105. package/dist/shopify/docs/storefront/DOC.md +457 -0
  106. package/dist/slack/docs/workspace/javascript/DOC.md +933 -0
  107. package/dist/slack/docs/workspace/python/DOC.md +271 -0
  108. package/dist/square/docs/payments/javascript/DOC.md +1855 -0
  109. package/dist/square/docs/payments/python/DOC.md +1728 -0
  110. package/dist/stripe/docs/api/DOC.md +1727 -0
  111. package/dist/stripe/docs/payments/DOC.md +1726 -0
  112. package/dist/stytch/docs/auth/javascript/DOC.md +1813 -0
  113. package/dist/stytch/docs/auth/python/DOC.md +1962 -0
  114. package/dist/supabase/docs/client/DOC.md +1606 -0
  115. package/dist/twilio/docs/messaging/python/DOC.md +469 -0
  116. package/dist/twilio/docs/messaging/typescript/DOC.md +946 -0
  117. package/dist/vercel/docs/platform/DOC.md +1940 -0
  118. package/dist/weaviate/docs/vector-db/javascript/DOC.md +1268 -0
  119. package/dist/weaviate/docs/vector-db/python/DOC.md +1388 -0
  120. package/dist/zendesk/docs/support/javascript/DOC.md +2150 -0
  121. package/dist/zendesk/docs/support/python/DOC.md +2297 -0
  122. package/package.json +22 -6
  123. package/skills/get-api-docs/SKILL.md +84 -0
  124. package/src/commands/annotate.js +83 -0
  125. package/src/commands/build.js +12 -1
  126. package/src/commands/feedback.js +150 -0
  127. package/src/commands/get.js +83 -42
  128. package/src/commands/search.js +7 -0
  129. package/src/index.js +43 -17
  130. package/src/lib/analytics.js +90 -0
  131. package/src/lib/annotations.js +57 -0
  132. package/src/lib/bm25.js +170 -0
  133. package/src/lib/cache.js +69 -6
  134. package/src/lib/config.js +8 -3
  135. package/src/lib/identity.js +99 -0
  136. package/src/lib/registry.js +103 -20
  137. package/src/lib/telemetry.js +86 -0
  138. package/src/mcp/server.js +177 -0
  139. package/src/mcp/tools.js +251 -0
@@ -0,0 +1,1090 @@
1
+ ---
2
+ name: bot
3
+ description: "Discord.js SDK for building Discord bots with slash commands and gateway events in JavaScript/TypeScript"
4
+ metadata:
5
+ languages: "javascript"
6
+ versions: "14.24.0"
7
+ updated-on: "2026-03-01"
8
+ source: maintainer
9
+ tags: "discord,bot,slash-commands,gateway,sdk"
10
+ ---
11
+
12
+ # Discord.js JavaScript/TypeScript SDK Coding Guidelines
13
+
14
+ You are a Discord.js coding expert. Help me with writing code using the Discord API calling the official libraries and SDKs.
15
+
16
+ You can find the official SDK documentation and code samples here:
17
+ https://discord.js.org/docs/packages/discord.js/14.24.0
18
+
19
+ ## Golden Rule: Use the Correct and Current SDK
20
+
21
+ Always use the discord.js library to interact with the Discord API, which is the standard library for all Discord bot interactions in JavaScript/TypeScript. Do not use legacy libraries or unofficial SDKs.
22
+
23
+ - **Library Name:** discord.js
24
+ - **NPM Package:** `discord.js`
25
+ - **Current Version:** 14.24.0 (v14)
26
+ - **Legacy Libraries:** discord.js v12, discord.js v13 are outdated and not recommended
27
+
28
+ **Installation:**
29
+
30
+ - **Correct:** `npm install discord.js`
31
+
32
+ **APIs and Usage:**
33
+
34
+ - **Correct:** `import { Client, GatewayIntentBits, Events } from 'discord.js'`
35
+ - **Correct:** `const client = new Client({ intents: [...] })`
36
+ - **Correct:** `client.on(Events.MessageCreate, ...)`
37
+ - **Correct:** `interaction.reply(...)`
38
+ - **Incorrect:** `Discord.Client` (use `Client` instead)
39
+ - **Incorrect:** `client.on('message', ...)` (use `client.on(Events.MessageCreate, ...)`)
40
+ - **Incorrect:** `MessageEmbed` (use `EmbedBuilder` in v14)
41
+
42
+ ## Installation
43
+
44
+ Install discord.js using npm:
45
+
46
+ ```bash
47
+ npm install discord.js
48
+ ```
49
+
50
+ **Environment Variables:**
51
+
52
+ Create a `.env` file with your bot token:
53
+
54
+ ```env
55
+ DISCORD_TOKEN=your_bot_token_here
56
+ CLIENT_ID=your_application_id_here
57
+ GUILD_ID=your_test_server_id_here
58
+ ```
59
+
60
+ Install dotenv to load environment variables:
61
+
62
+ ```bash
63
+ npm install dotenv
64
+ ```
65
+
66
+ ## Initialization
67
+
68
+ The `discord.js` library requires creating a `Client` instance with appropriate intents.
69
+
70
+ ```javascript
71
+ import { Client, GatewayIntentBits } from 'discord.js';
72
+ import dotenv from 'dotenv';
73
+
74
+ dotenv.config();
75
+
76
+ const client = new Client({
77
+ intents: [
78
+ GatewayIntentBits.Guilds,
79
+ GatewayIntentBits.GuildMessages,
80
+ GatewayIntentBits.MessageContent,
81
+ GatewayIntentBits.GuildMembers,
82
+ ],
83
+ });
84
+
85
+ client.login(process.env.DISCORD_TOKEN);
86
+ ```
87
+
88
+ ### Gateway Intents
89
+
90
+ Intents are named groups of pre-defined WebSocket events that your bot will receive. You must specify the intents your bot needs.
91
+
92
+ **Common Intents:**
93
+
94
+ - `GatewayIntentBits.Guilds` - Guild-related events (required for most bots)
95
+ - `GatewayIntentBits.GuildMessages` - Message events in guilds
96
+ - `GatewayIntentBits.MessageContent` - Access to message content (privileged)
97
+ - `GatewayIntentBits.GuildMembers` - Member join/leave events (privileged)
98
+ - `GatewayIntentBits.GuildPresences` - Presence updates (privileged)
99
+ - `GatewayIntentBits.DirectMessages` - DM events
100
+
101
+ **Privileged Intents:**
102
+
103
+ For `MessageContent`, `GuildMembers`, and `GuildPresences`, you must enable them in the Discord Developer Portal under your application's Bot settings.
104
+
105
+ ```javascript
106
+ const client = new Client({
107
+ intents: [
108
+ GatewayIntentBits.Guilds,
109
+ GatewayIntentBits.GuildMessages,
110
+ GatewayIntentBits.MessageContent, // Privileged - enable in Developer Portal
111
+ ],
112
+ });
113
+ ```
114
+
115
+ ## Basic Bot Setup
116
+
117
+ ### Ready Event
118
+
119
+ The `Ready` event fires when the bot successfully connects to Discord:
120
+
121
+ ```javascript
122
+ import { Client, GatewayIntentBits, Events } from 'discord.js';
123
+
124
+ const client = new Client({
125
+ intents: [GatewayIntentBits.Guilds],
126
+ });
127
+
128
+ client.once(Events.ClientReady, (readyClient) => {
129
+ console.log(`Logged in as ${readyClient.user.tag}`);
130
+ });
131
+
132
+ client.login(process.env.DISCORD_TOKEN);
133
+ ```
134
+
135
+ ### Message Events
136
+
137
+ Listen to messages in channels:
138
+
139
+ ```javascript
140
+ import { Client, GatewayIntentBits, Events } from 'discord.js';
141
+
142
+ const client = new Client({
143
+ intents: [
144
+ GatewayIntentBits.Guilds,
145
+ GatewayIntentBits.GuildMessages,
146
+ GatewayIntentBits.MessageContent,
147
+ ],
148
+ });
149
+
150
+ client.on(Events.MessageCreate, (message) => {
151
+ // Ignore messages from bots
152
+ if (message.author.bot) return;
153
+
154
+ if (message.content === '!ping') {
155
+ message.reply('Pong!');
156
+ }
157
+ });
158
+
159
+ client.login(process.env.DISCORD_TOKEN);
160
+ ```
161
+
162
+ ## Slash Commands
163
+
164
+ Slash commands are the primary way to interact with Discord bots. They provide a better user experience with autocomplete and validation.
165
+
166
+ ### Registering Slash Commands
167
+
168
+ Create a separate file to register commands with Discord's API:
169
+
170
+ ```javascript
171
+ import { REST, Routes, SlashCommandBuilder } from 'discord.js';
172
+ import dotenv from 'dotenv';
173
+
174
+ dotenv.config();
175
+
176
+ const commands = [
177
+ new SlashCommandBuilder()
178
+ .setName('ping')
179
+ .setDescription('Replies with Pong!')
180
+ .toJSON(),
181
+ new SlashCommandBuilder()
182
+ .setName('user')
183
+ .setDescription('Get info about a user')
184
+ .addUserOption((option) =>
185
+ option
186
+ .setName('target')
187
+ .setDescription('The user')
188
+ .setRequired(true)
189
+ )
190
+ .toJSON(),
191
+ new SlashCommandBuilder()
192
+ .setName('server')
193
+ .setDescription('Get info about the server')
194
+ .toJSON(),
195
+ ];
196
+
197
+ const rest = new REST().setToken(process.env.DISCORD_TOKEN);
198
+
199
+ (async () => {
200
+ try {
201
+ console.log(`Started refreshing ${commands.length} application (/) commands.`);
202
+
203
+ // Register commands globally (takes up to 1 hour to propagate)
204
+ const data = await rest.put(
205
+ Routes.applicationCommands(process.env.CLIENT_ID),
206
+ { body: commands }
207
+ );
208
+
209
+ // OR register to a specific guild (instant update - for testing)
210
+ // const data = await rest.put(
211
+ // Routes.applicationGuildCommands(process.env.CLIENT_ID, process.env.GUILD_ID),
212
+ // { body: commands }
213
+ // );
214
+
215
+ console.log(`Successfully reloaded ${data.length} application (/) commands.`);
216
+ } catch (error) {
217
+ console.error(error);
218
+ }
219
+ })();
220
+ ```
221
+
222
+ ### Handling Slash Command Interactions
223
+
224
+ ```javascript
225
+ import { Client, GatewayIntentBits, Events } from 'discord.js';
226
+
227
+ const client = new Client({
228
+ intents: [GatewayIntentBits.Guilds],
229
+ });
230
+
231
+ client.on(Events.InteractionCreate, async (interaction) => {
232
+ if (!interaction.isChatInputCommand()) return;
233
+
234
+ if (interaction.commandName === 'ping') {
235
+ await interaction.reply('Pong!');
236
+ } else if (interaction.commandName === 'user') {
237
+ const user = interaction.options.getUser('target');
238
+ await interaction.reply(`User: ${user.tag}, ID: ${user.id}`);
239
+ } else if (interaction.commandName === 'server') {
240
+ await interaction.reply(
241
+ `Server: ${interaction.guild.name}, Members: ${interaction.guild.memberCount}`
242
+ );
243
+ }
244
+ });
245
+
246
+ client.login(process.env.DISCORD_TOKEN);
247
+ ```
248
+
249
+ ### Advanced Slash Command Options
250
+
251
+ ```javascript
252
+ new SlashCommandBuilder()
253
+ .setName('echo')
254
+ .setDescription('Echoes your message')
255
+ .addStringOption((option) =>
256
+ option
257
+ .setName('message')
258
+ .setDescription('The message to echo')
259
+ .setRequired(true)
260
+ .setMaxLength(2000)
261
+ )
262
+ .addBooleanOption((option) =>
263
+ option
264
+ .setName('ephemeral')
265
+ .setDescription('Should the reply be private?')
266
+ .setRequired(false)
267
+ )
268
+ .addIntegerOption((option) =>
269
+ option
270
+ .setName('number')
271
+ .setDescription('A number')
272
+ .setMinValue(1)
273
+ .setMaxValue(100)
274
+ )
275
+ .addChannelOption((option) =>
276
+ option
277
+ .setName('channel')
278
+ .setDescription('Select a channel')
279
+ )
280
+ .addRoleOption((option) =>
281
+ option
282
+ .setName('role')
283
+ .setDescription('Select a role')
284
+ )
285
+ .toJSON()
286
+ ```
287
+
288
+ ### Choices in Slash Commands
289
+
290
+ Add predefined choices to string or number options:
291
+
292
+ ```javascript
293
+ new SlashCommandBuilder()
294
+ .setName('choose')
295
+ .setDescription('Choose an option')
296
+ .addStringOption((option) =>
297
+ option
298
+ .setName('option')
299
+ .setDescription('Select an option')
300
+ .setRequired(true)
301
+ .addChoices(
302
+ { name: 'Option A', value: 'option_a' },
303
+ { name: 'Option B', value: 'option_b' },
304
+ { name: 'Option C', value: 'option_c' }
305
+ )
306
+ )
307
+ .toJSON()
308
+ ```
309
+
310
+ ### Autocomplete
311
+
312
+ Enable autocomplete for dynamic options:
313
+
314
+ ```javascript
315
+ // In command definition
316
+ new SlashCommandBuilder()
317
+ .setName('search')
318
+ .setDescription('Search for something')
319
+ .addStringOption((option) =>
320
+ option
321
+ .setName('query')
322
+ .setDescription('Search query')
323
+ .setRequired(true)
324
+ .setAutocomplete(true)
325
+ )
326
+ .toJSON()
327
+
328
+ // In interaction handler
329
+ client.on(Events.InteractionCreate, async (interaction) => {
330
+ if (interaction.isAutocomplete()) {
331
+ const focusedValue = interaction.options.getFocused();
332
+
333
+ // Fetch or generate choices based on focusedValue
334
+ const choices = ['apple', 'banana', 'cherry', 'date', 'elderberry'];
335
+ const filtered = choices.filter((choice) =>
336
+ choice.startsWith(focusedValue.toLowerCase())
337
+ );
338
+
339
+ await interaction.respond(
340
+ filtered.map((choice) => ({ name: choice, value: choice }))
341
+ );
342
+ }
343
+ });
344
+ ```
345
+
346
+ ## Embeds
347
+
348
+ Embeds allow you to send rich, formatted messages with images, fields, and more.
349
+
350
+ ### Basic Embed
351
+
352
+ ```javascript
353
+ import { EmbedBuilder } from 'discord.js';
354
+
355
+ const embed = new EmbedBuilder()
356
+ .setTitle('Embed Title')
357
+ .setDescription('This is an embed description')
358
+ .setColor(0x0099ff)
359
+ .setTimestamp()
360
+ .setFooter({ text: 'Footer text' });
361
+
362
+ await interaction.reply({ embeds: [embed] });
363
+ ```
364
+
365
+ ### Advanced Embed
366
+
367
+ ```javascript
368
+ import { EmbedBuilder } from 'discord.js';
369
+
370
+ const embed = new EmbedBuilder()
371
+ .setColor('#0099ff')
372
+ .setTitle('Advanced Embed')
373
+ .setURL('https://discord.js.org')
374
+ .setAuthor({
375
+ name: 'Author Name',
376
+ iconURL: 'https://i.imgur.com/AfFp7pu.png',
377
+ url: 'https://discord.js.org',
378
+ })
379
+ .setDescription('Some description here')
380
+ .setThumbnail('https://i.imgur.com/AfFp7pu.png')
381
+ .addFields(
382
+ { name: 'Regular field title', value: 'Some value here' },
383
+ { name: '\u200B', value: '\u200B' }, // Blank field
384
+ { name: 'Inline field title', value: 'Some value here', inline: true },
385
+ { name: 'Inline field title', value: 'Some value here', inline: true }
386
+ )
387
+ .addFields({ name: 'Inline field title', value: 'Some value here', inline: true })
388
+ .setImage('https://i.imgur.com/AfFp7pu.png')
389
+ .setTimestamp()
390
+ .setFooter({
391
+ text: 'Some footer text here',
392
+ iconURL: 'https://i.imgur.com/AfFp7pu.png',
393
+ });
394
+
395
+ await channel.send({ embeds: [embed] });
396
+ ```
397
+
398
+ ### Embed Colors
399
+
400
+ ```javascript
401
+ // Hexadecimal
402
+ .setColor('#0099ff')
403
+
404
+ // Integer
405
+ .setColor(0x0099ff)
406
+
407
+ // RGB array
408
+ .setColor([0, 153, 255])
409
+
410
+ // Predefined colors
411
+ import { Colors } from 'discord.js';
412
+ .setColor(Colors.Blue)
413
+ .setColor(Colors.Red)
414
+ .setColor(Colors.Green)
415
+ ```
416
+
417
+ ## Buttons
418
+
419
+ Buttons are interactive components that users can click.
420
+
421
+ ### Basic Button
422
+
423
+ ```javascript
424
+ import { ActionRowBuilder, ButtonBuilder, ButtonStyle } from 'discord.js';
425
+
426
+ const row = new ActionRowBuilder()
427
+ .addComponents(
428
+ new ButtonBuilder()
429
+ .setCustomId('primary')
430
+ .setLabel('Click me!')
431
+ .setStyle(ButtonStyle.Primary)
432
+ );
433
+
434
+ await interaction.reply({
435
+ content: 'Click a button!',
436
+ components: [row],
437
+ });
438
+ ```
439
+
440
+ ### Multiple Buttons
441
+
442
+ ```javascript
443
+ import { ActionRowBuilder, ButtonBuilder, ButtonStyle } from 'discord.js';
444
+
445
+ const row = new ActionRowBuilder()
446
+ .addComponents(
447
+ new ButtonBuilder()
448
+ .setCustomId('primary')
449
+ .setLabel('Primary')
450
+ .setStyle(ButtonStyle.Primary),
451
+ new ButtonBuilder()
452
+ .setCustomId('secondary')
453
+ .setLabel('Secondary')
454
+ .setStyle(ButtonStyle.Secondary),
455
+ new ButtonBuilder()
456
+ .setCustomId('success')
457
+ .setLabel('Success')
458
+ .setStyle(ButtonStyle.Success),
459
+ new ButtonBuilder()
460
+ .setCustomId('danger')
461
+ .setLabel('Danger')
462
+ .setStyle(ButtonStyle.Danger)
463
+ );
464
+
465
+ await interaction.reply({
466
+ content: 'Choose a button!',
467
+ components: [row],
468
+ });
469
+ ```
470
+
471
+ ### Link Button
472
+
473
+ ```javascript
474
+ const row = new ActionRowBuilder()
475
+ .addComponents(
476
+ new ButtonBuilder()
477
+ .setLabel('Visit Website')
478
+ .setURL('https://discord.js.org')
479
+ .setStyle(ButtonStyle.Link)
480
+ );
481
+ ```
482
+
483
+ ### Handling Button Interactions
484
+
485
+ ```javascript
486
+ client.on(Events.InteractionCreate, async (interaction) => {
487
+ if (!interaction.isButton()) return;
488
+
489
+ if (interaction.customId === 'primary') {
490
+ await interaction.reply({ content: 'You clicked Primary!', ephemeral: true });
491
+ } else if (interaction.customId === 'danger') {
492
+ await interaction.reply({ content: 'Danger button clicked!', ephemeral: true });
493
+ }
494
+ });
495
+ ```
496
+
497
+ ### Disabled Buttons
498
+
499
+ ```javascript
500
+ new ButtonBuilder()
501
+ .setCustomId('disabled')
502
+ .setLabel('Disabled')
503
+ .setStyle(ButtonStyle.Primary)
504
+ .setDisabled(true)
505
+ ```
506
+
507
+ ## Select Menus
508
+
509
+ Select menus (dropdowns) allow users to choose from multiple options.
510
+
511
+ ### String Select Menu
512
+
513
+ ```javascript
514
+ import { ActionRowBuilder, StringSelectMenuBuilder, StringSelectMenuOptionBuilder } from 'discord.js';
515
+
516
+ const row = new ActionRowBuilder()
517
+ .addComponents(
518
+ new StringSelectMenuBuilder()
519
+ .setCustomId('select')
520
+ .setPlaceholder('Make a selection!')
521
+ .addOptions(
522
+ new StringSelectMenuOptionBuilder()
523
+ .setLabel('Option 1')
524
+ .setDescription('This is option 1')
525
+ .setValue('option_1'),
526
+ new StringSelectMenuOptionBuilder()
527
+ .setLabel('Option 2')
528
+ .setDescription('This is option 2')
529
+ .setValue('option_2'),
530
+ new StringSelectMenuOptionBuilder()
531
+ .setLabel('Option 3')
532
+ .setDescription('This is option 3')
533
+ .setValue('option_3')
534
+ )
535
+ );
536
+
537
+ await interaction.reply({
538
+ content: 'Choose an option:',
539
+ components: [row],
540
+ });
541
+ ```
542
+
543
+ ### Handling Select Menu Interactions
544
+
545
+ ```javascript
546
+ client.on(Events.InteractionCreate, async (interaction) => {
547
+ if (!interaction.isStringSelectMenu()) return;
548
+
549
+ if (interaction.customId === 'select') {
550
+ const selected = interaction.values[0];
551
+ await interaction.reply({ content: `You selected: ${selected}`, ephemeral: true });
552
+ }
553
+ });
554
+ ```
555
+
556
+ ### User Select Menu
557
+
558
+ ```javascript
559
+ import { UserSelectMenuBuilder } from 'discord.js';
560
+
561
+ const row = new ActionRowBuilder()
562
+ .addComponents(
563
+ new UserSelectMenuBuilder()
564
+ .setCustomId('user_select')
565
+ .setPlaceholder('Select a user')
566
+ .setMinValues(1)
567
+ .setMaxValues(3)
568
+ );
569
+ ```
570
+
571
+ ### Role Select Menu
572
+
573
+ ```javascript
574
+ import { RoleSelectMenuBuilder } from 'discord.js';
575
+
576
+ const row = new ActionRowBuilder()
577
+ .addComponents(
578
+ new RoleSelectMenuBuilder()
579
+ .setCustomId('role_select')
580
+ .setPlaceholder('Select a role')
581
+ );
582
+ ```
583
+
584
+ ### Channel Select Menu
585
+
586
+ ```javascript
587
+ import { ChannelSelectMenuBuilder, ChannelType } from 'discord.js';
588
+
589
+ const row = new ActionRowBuilder()
590
+ .addComponents(
591
+ new ChannelSelectMenuBuilder()
592
+ .setCustomId('channel_select')
593
+ .setPlaceholder('Select a channel')
594
+ .addChannelTypes(ChannelType.GuildText, ChannelType.GuildVoice)
595
+ );
596
+ ```
597
+
598
+ ## Modals
599
+
600
+ Modals are pop-up forms that allow users to submit text input.
601
+
602
+ ### Creating a Modal
603
+
604
+ ```javascript
605
+ import { ModalBuilder, TextInputBuilder, TextInputStyle, ActionRowBuilder } from 'discord.js';
606
+
607
+ const modal = new ModalBuilder()
608
+ .setCustomId('feedback_modal')
609
+ .setTitle('Feedback Form');
610
+
611
+ const nameInput = new TextInputBuilder()
612
+ .setCustomId('name_input')
613
+ .setLabel('What is your name?')
614
+ .setStyle(TextInputStyle.Short)
615
+ .setRequired(true);
616
+
617
+ const feedbackInput = new TextInputBuilder()
618
+ .setCustomId('feedback_input')
619
+ .setLabel('Your feedback')
620
+ .setStyle(TextInputStyle.Paragraph)
621
+ .setPlaceholder('Tell us what you think!')
622
+ .setRequired(true)
623
+ .setMaxLength(1000);
624
+
625
+ const firstActionRow = new ActionRowBuilder().addComponents(nameInput);
626
+ const secondActionRow = new ActionRowBuilder().addComponents(feedbackInput);
627
+
628
+ modal.addComponents(firstActionRow, secondActionRow);
629
+
630
+ await interaction.showModal(modal);
631
+ ```
632
+
633
+ ### Handling Modal Submissions
634
+
635
+ ```javascript
636
+ client.on(Events.InteractionCreate, async (interaction) => {
637
+ if (!interaction.isModalSubmit()) return;
638
+
639
+ if (interaction.customId === 'feedback_modal') {
640
+ const name = interaction.fields.getTextInputValue('name_input');
641
+ const feedback = interaction.fields.getTextInputValue('feedback_input');
642
+
643
+ await interaction.reply({
644
+ content: `Thank you for your feedback, ${name}!`,
645
+ ephemeral: true,
646
+ });
647
+ }
648
+ });
649
+ ```
650
+
651
+ ## Context Menus
652
+
653
+ Context menus appear when right-clicking on a user or message.
654
+
655
+ ### User Context Menu
656
+
657
+ ```javascript
658
+ import { ContextMenuCommandBuilder, ApplicationCommandType } from 'discord.js';
659
+
660
+ const command = new ContextMenuCommandBuilder()
661
+ .setName('Get User Info')
662
+ .setType(ApplicationCommandType.User)
663
+ .toJSON();
664
+ ```
665
+
666
+ ### Message Context Menu
667
+
668
+ ```javascript
669
+ const command = new ContextMenuCommandBuilder()
670
+ .setName('Report Message')
671
+ .setType(ApplicationCommandType.Message)
672
+ .toJSON();
673
+ ```
674
+
675
+ ### Handling Context Menu Interactions
676
+
677
+ ```javascript
678
+ client.on(Events.InteractionCreate, async (interaction) => {
679
+ if (!interaction.isContextMenuCommand()) return;
680
+
681
+ if (interaction.commandName === 'Get User Info') {
682
+ const user = interaction.targetUser;
683
+ await interaction.reply({
684
+ content: `User: ${user.tag}, ID: ${user.id}`,
685
+ ephemeral: true,
686
+ });
687
+ } else if (interaction.commandName === 'Report Message') {
688
+ const message = interaction.targetMessage;
689
+ await interaction.reply({
690
+ content: `Reported message from ${message.author.tag}`,
691
+ ephemeral: true,
692
+ });
693
+ }
694
+ });
695
+ ```
696
+
697
+ ## Sending Messages
698
+
699
+ ### Reply to Interaction
700
+
701
+ ```javascript
702
+ // Regular reply
703
+ await interaction.reply('Hello!');
704
+
705
+ // Ephemeral reply (only visible to user)
706
+ await interaction.reply({ content: 'Secret message!', ephemeral: true });
707
+
708
+ // Reply with embed
709
+ await interaction.reply({ embeds: [embed] });
710
+
711
+ // Reply with buttons
712
+ await interaction.reply({ content: 'Click!', components: [row] });
713
+ ```
714
+
715
+ ### Send Message to Channel
716
+
717
+ ```javascript
718
+ // Get channel by ID
719
+ const channel = client.channels.cache.get('channel_id');
720
+ await channel.send('Hello, channel!');
721
+
722
+ // From interaction
723
+ await interaction.channel.send('Message in this channel!');
724
+ ```
725
+
726
+ ### Edit Reply
727
+
728
+ ```javascript
729
+ await interaction.reply('Original message');
730
+ await interaction.editReply('Edited message');
731
+ ```
732
+
733
+ ### Follow-up Messages
734
+
735
+ ```javascript
736
+ await interaction.reply('First message');
737
+ await interaction.followUp('Second message');
738
+ await interaction.followUp({ content: 'Third message', ephemeral: true });
739
+ ```
740
+
741
+ ### Deferred Replies
742
+
743
+ For long-running operations:
744
+
745
+ ```javascript
746
+ await interaction.deferReply();
747
+ // Do long operation...
748
+ await interaction.editReply('Done!');
749
+
750
+ // Or defer with ephemeral
751
+ await interaction.deferReply({ ephemeral: true });
752
+ ```
753
+
754
+ ## Permissions
755
+
756
+ ### Check User Permissions
757
+
758
+ ```javascript
759
+ if (interaction.member.permissions.has(PermissionFlagsBits.Administrator)) {
760
+ await interaction.reply('You are an admin!');
761
+ }
762
+
763
+ import { PermissionFlagsBits } from 'discord.js';
764
+
765
+ if (interaction.member.permissions.has(PermissionFlagsBits.ManageMessages)) {
766
+ // User can manage messages
767
+ }
768
+ ```
769
+
770
+ ### Command Permissions
771
+
772
+ ```javascript
773
+ new SlashCommandBuilder()
774
+ .setName('admin')
775
+ .setDescription('Admin only command')
776
+ .setDefaultMemberPermissions(PermissionFlagsBits.Administrator)
777
+ .toJSON()
778
+ ```
779
+
780
+ ### Check Bot Permissions
781
+
782
+ ```javascript
783
+ const botMember = interaction.guild.members.me;
784
+ if (botMember.permissions.has(PermissionFlagsBits.ManageRoles)) {
785
+ // Bot can manage roles
786
+ }
787
+ ```
788
+
789
+ ## Events
790
+
791
+ ### Common Events
792
+
793
+ ```javascript
794
+ import { Events } from 'discord.js';
795
+
796
+ // Bot ready
797
+ client.once(Events.ClientReady, (c) => {
798
+ console.log(`Ready! Logged in as ${c.user.tag}`);
799
+ });
800
+
801
+ // Message created
802
+ client.on(Events.MessageCreate, (message) => {
803
+ console.log(`Message: ${message.content}`);
804
+ });
805
+
806
+ // Interaction created
807
+ client.on(Events.InteractionCreate, (interaction) => {
808
+ console.log(`Interaction: ${interaction.type}`);
809
+ });
810
+
811
+ // Guild member added
812
+ client.on(Events.GuildMemberAdd, (member) => {
813
+ console.log(`${member.user.tag} joined ${member.guild.name}`);
814
+ });
815
+
816
+ // Guild member removed
817
+ client.on(Events.GuildMemberRemove, (member) => {
818
+ console.log(`${member.user.tag} left ${member.guild.name}`);
819
+ });
820
+
821
+ // Message deleted
822
+ client.on(Events.MessageDelete, (message) => {
823
+ console.log(`Message deleted: ${message.content}`);
824
+ });
825
+
826
+ // Message updated
827
+ client.on(Events.MessageUpdate, (oldMessage, newMessage) => {
828
+ console.log(`Message edited from "${oldMessage.content}" to "${newMessage.content}"`);
829
+ });
830
+ ```
831
+
832
+ ## Fetching Data
833
+
834
+ ### Fetch User
835
+
836
+ ```javascript
837
+ const user = await client.users.fetch('user_id');
838
+ console.log(user.tag);
839
+ ```
840
+
841
+ ### Fetch Member
842
+
843
+ ```javascript
844
+ const member = await interaction.guild.members.fetch('user_id');
845
+ console.log(member.displayName);
846
+ ```
847
+
848
+ ### Fetch Channel
849
+
850
+ ```javascript
851
+ const channel = await client.channels.fetch('channel_id');
852
+ await channel.send('Hello!');
853
+ ```
854
+
855
+ ### Fetch Guild
856
+
857
+ ```javascript
858
+ const guild = await client.guilds.fetch('guild_id');
859
+ console.log(guild.name);
860
+ ```
861
+
862
+ ### Fetch Messages
863
+
864
+ ```javascript
865
+ // Fetch last 10 messages
866
+ const messages = await channel.messages.fetch({ limit: 10 });
867
+
868
+ // Fetch specific message
869
+ const message = await channel.messages.fetch('message_id');
870
+ ```
871
+
872
+ ## Error Handling
873
+
874
+ ### Basic Error Handling
875
+
876
+ ```javascript
877
+ client.on(Events.InteractionCreate, async (interaction) => {
878
+ try {
879
+ if (interaction.isChatInputCommand()) {
880
+ // Handle command
881
+ await interaction.reply('Success!');
882
+ }
883
+ } catch (error) {
884
+ console.error(error);
885
+
886
+ if (interaction.replied || interaction.deferred) {
887
+ await interaction.followUp({
888
+ content: 'There was an error executing this command!',
889
+ ephemeral: true,
890
+ });
891
+ } else {
892
+ await interaction.reply({
893
+ content: 'There was an error executing this command!',
894
+ ephemeral: true,
895
+ });
896
+ }
897
+ }
898
+ });
899
+ ```
900
+
901
+ ### Common Errors
902
+
903
+ ```javascript
904
+ // Unknown Interaction
905
+ if (interaction.isRepliable() && !interaction.replied) {
906
+ try {
907
+ await interaction.reply('...');
908
+ } catch (error) {
909
+ if (error.code === 10062) {
910
+ console.log('Unknown interaction - likely expired');
911
+ }
912
+ }
913
+ }
914
+
915
+ // Missing Permissions
916
+ catch (error) {
917
+ if (error.code === 50013) {
918
+ console.log('Missing permissions');
919
+ }
920
+ }
921
+
922
+ // Unknown Channel
923
+ catch (error) {
924
+ if (error.code === 10003) {
925
+ console.log('Unknown channel');
926
+ }
927
+ }
928
+ ```
929
+
930
+ ## Command Handler Structure
931
+
932
+ Organize commands into separate files:
933
+
934
+ ```javascript
935
+ // commands/ping.js
936
+ import { SlashCommandBuilder } from 'discord.js';
937
+
938
+ export const data = new SlashCommandBuilder()
939
+ .setName('ping')
940
+ .setDescription('Replies with Pong!');
941
+
942
+ export async function execute(interaction) {
943
+ await interaction.reply('Pong!');
944
+ }
945
+ ```
946
+
947
+ ```javascript
948
+ // index.js
949
+ import { Client, Collection, GatewayIntentBits, Events } from 'discord.js';
950
+ import { fileURLToPath } from 'url';
951
+ import { dirname, join } from 'path';
952
+ import { readdirSync } from 'fs';
953
+
954
+ const __dirname = dirname(fileURLToPath(import.meta.url));
955
+
956
+ const client = new Client({
957
+ intents: [GatewayIntentBits.Guilds],
958
+ });
959
+
960
+ client.commands = new Collection();
961
+
962
+ const commandsPath = join(__dirname, 'commands');
963
+ const commandFiles = readdirSync(commandsPath).filter((file) => file.endsWith('.js'));
964
+
965
+ for (const file of commandFiles) {
966
+ const filePath = join(commandsPath, file);
967
+ const command = await import(filePath);
968
+
969
+ if ('data' in command && 'execute' in command) {
970
+ client.commands.set(command.data.name, command);
971
+ }
972
+ }
973
+
974
+ client.on(Events.InteractionCreate, async (interaction) => {
975
+ if (!interaction.isChatInputCommand()) return;
976
+
977
+ const command = client.commands.get(interaction.commandName);
978
+
979
+ if (!command) {
980
+ console.error(`No command matching ${interaction.commandName} was found.`);
981
+ return;
982
+ }
983
+
984
+ try {
985
+ await command.execute(interaction);
986
+ } catch (error) {
987
+ console.error(error);
988
+
989
+ const errorMessage = {
990
+ content: 'There was an error while executing this command!',
991
+ ephemeral: true,
992
+ };
993
+
994
+ if (interaction.replied || interaction.deferred) {
995
+ await interaction.followUp(errorMessage);
996
+ } else {
997
+ await interaction.reply(errorMessage);
998
+ }
999
+ }
1000
+ });
1001
+
1002
+ client.login(process.env.DISCORD_TOKEN);
1003
+ ```
1004
+
1005
+ ## Advanced Features
1006
+
1007
+ ### Collectors
1008
+
1009
+ Collect button or select menu interactions:
1010
+
1011
+ ```javascript
1012
+ const filter = (i) => i.customId === 'primary' && i.user.id === interaction.user.id;
1013
+ const collector = interaction.channel.createMessageComponentCollector({
1014
+ filter,
1015
+ time: 60000, // 1 minute
1016
+ });
1017
+
1018
+ collector.on('collect', async (i) => {
1019
+ await i.update({ content: 'Button clicked!', components: [] });
1020
+ });
1021
+
1022
+ collector.on('end', (collected) => {
1023
+ console.log(`Collected ${collected.size} interactions.`);
1024
+ });
1025
+ ```
1026
+
1027
+ ### Reactions
1028
+
1029
+ ```javascript
1030
+ const message = await channel.send('React to this!');
1031
+ await message.react('👍');
1032
+ await message.react('👎');
1033
+
1034
+ // Reaction collector
1035
+ const filter = (reaction, user) => {
1036
+ return reaction.emoji.name === '👍' && user.id === interaction.user.id;
1037
+ };
1038
+
1039
+ const collector = message.createReactionCollector({ filter, time: 60000 });
1040
+
1041
+ collector.on('collect', (reaction, user) => {
1042
+ console.log(`${user.tag} reacted with ${reaction.emoji.name}`);
1043
+ });
1044
+ ```
1045
+
1046
+ ### Threads
1047
+
1048
+ ```javascript
1049
+ // Create thread from message
1050
+ const thread = await message.startThread({
1051
+ name: 'Thread Name',
1052
+ autoArchiveDuration: 60,
1053
+ });
1054
+
1055
+ // Create thread in channel
1056
+ const thread = await channel.threads.create({
1057
+ name: 'New Thread',
1058
+ autoArchiveDuration: 60,
1059
+ reason: 'Discussion thread',
1060
+ });
1061
+
1062
+ // Send message to thread
1063
+ await thread.send('Hello in thread!');
1064
+ ```
1065
+
1066
+ ### Voice Connections
1067
+
1068
+ For voice support, install `@discordjs/voice`:
1069
+
1070
+ ```bash
1071
+ npm install @discordjs/voice
1072
+ ```
1073
+
1074
+ ```javascript
1075
+ import { joinVoiceChannel } from '@discordjs/voice';
1076
+
1077
+ const connection = joinVoiceChannel({
1078
+ channelId: channel.id,
1079
+ guildId: channel.guild.id,
1080
+ adapterCreator: channel.guild.voiceAdapterCreator,
1081
+ });
1082
+ ```
1083
+
1084
+ ## Useful Links
1085
+
1086
+ - Documentation: https://discord.js.org/docs/packages/discord.js/14.24.0
1087
+ - Guide: https://discordjs.guide/
1088
+ - Discord API Docs: https://discord.com/developers/docs
1089
+ - Developer Portal: https://discord.com/developers/applications
1090
+ - Community Server: https://discord.gg/djs