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,1130 @@
1
+ ---
2
+ name: bot
3
+ description: "Discord.py SDK for building Discord bots with slash commands and gateway events in Python"
4
+ metadata:
5
+ languages: "python"
6
+ versions: "2.6.4"
7
+ updated-on: "2026-03-01"
8
+ source: maintainer
9
+ tags: "discord,bot,slash-commands,gateway,sdk"
10
+ ---
11
+
12
+ # Discord.py Python SDK Coding Guidelines
13
+
14
+ You are a discord.py 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://discordpy.readthedocs.io/en/stable/
18
+
19
+ ## Golden Rule: Use the Correct and Current SDK
20
+
21
+ Always use the discord.py library to interact with the Discord API, which is the standard library for all Discord bot interactions in Python. Do not use legacy libraries or unofficial SDKs.
22
+
23
+ - **Library Name:** discord.py
24
+ - **PyPI Package:** `discord.py`
25
+ - **Current Version:** 2.6.4
26
+ - **Legacy Libraries:** discord.py v1.x is outdated and not recommended
27
+
28
+ **Installation:**
29
+
30
+ - **Correct:** `pip install discord.py`
31
+ - **Correct (with voice support):** `pip install discord.py[voice]`
32
+
33
+ **APIs and Usage:**
34
+
35
+ - **Correct:** `import discord`
36
+ - **Correct:** `from discord.ext import commands`
37
+ - **Correct:** `bot = commands.Bot(command_prefix='!', intents=intents)`
38
+ - **Correct:** `@bot.command()`
39
+ - **Correct:** `await interaction.response.send_message(...)`
40
+ - **Incorrect:** `discord.Client()` without intents (use `discord.Client(intents=intents)`)
41
+ - **Incorrect:** `@client.event` in cogs (use `@commands.Cog.listener()`)
42
+
43
+ ## Installation
44
+
45
+ Install discord.py using pip:
46
+
47
+ ```bash
48
+ pip install discord.py
49
+ ```
50
+
51
+ **With Voice Support:**
52
+
53
+ ```bash
54
+ pip install discord.py[voice]
55
+ ```
56
+
57
+ **Environment Variables:**
58
+
59
+ Create a `.env` file with your bot token:
60
+
61
+ ```env
62
+ DISCORD_TOKEN=your_bot_token_here
63
+ ```
64
+
65
+ Install python-dotenv to load environment variables:
66
+
67
+ ```bash
68
+ pip install python-dotenv
69
+ ```
70
+
71
+ ## Initialization
72
+
73
+ The `discord.py` library requires creating a bot with appropriate intents.
74
+
75
+ ```python
76
+ import discord
77
+ from discord.ext import commands
78
+ import os
79
+ from dotenv import load_dotenv
80
+
81
+ load_dotenv()
82
+
83
+ intents = discord.Intents.default()
84
+ intents.message_content = True
85
+ intents.members = True
86
+
87
+ bot = commands.Bot(command_prefix='!', intents=intents)
88
+
89
+ bot.run(os.getenv('DISCORD_TOKEN'))
90
+ ```
91
+
92
+ ### Intents
93
+
94
+ Intents specify which events your bot will receive from Discord. You must explicitly enable intents.
95
+
96
+ **Common Intents:**
97
+
98
+ ```python
99
+ intents = discord.Intents.default()
100
+ intents.message_content = True # Privileged - enable in Developer Portal
101
+ intents.members = True # Privileged - enable in Developer Portal
102
+ intents.presences = True # Privileged - enable in Developer Portal
103
+ intents.guilds = True
104
+ intents.messages = True
105
+ intents.reactions = True
106
+ ```
107
+
108
+ **All Intents (for development):**
109
+
110
+ ```python
111
+ intents = discord.Intents.all()
112
+ ```
113
+
114
+ **Minimal Intents:**
115
+
116
+ ```python
117
+ intents = discord.Intents.default()
118
+ ```
119
+
120
+ **Privileged Intents:**
121
+
122
+ For `message_content`, `members`, and `presences`, you must enable them in the Discord Developer Portal under your application's Bot settings.
123
+
124
+ ## Basic Bot Setup
125
+
126
+ ### Using Commands Extension
127
+
128
+ The recommended way to build bots:
129
+
130
+ ```python
131
+ import discord
132
+ from discord.ext import commands
133
+ import os
134
+
135
+ intents = discord.Intents.default()
136
+ intents.message_content = True
137
+
138
+ bot = commands.Bot(command_prefix='!', intents=intents)
139
+
140
+ @bot.event
141
+ async def on_ready():
142
+ print(f'{bot.user} has connected to Discord!')
143
+
144
+ @bot.command()
145
+ async def ping(ctx):
146
+ await ctx.send('Pong!')
147
+
148
+ bot.run(os.getenv('DISCORD_TOKEN'))
149
+ ```
150
+
151
+ ### Using Client Only
152
+
153
+ For simpler bots without commands:
154
+
155
+ ```python
156
+ import discord
157
+ import os
158
+
159
+ intents = discord.Intents.default()
160
+ intents.message_content = True
161
+
162
+ client = discord.Client(intents=intents)
163
+
164
+ @client.event
165
+ async def on_ready():
166
+ print(f'{client.user} has logged in!')
167
+
168
+ @client.event
169
+ async def on_message(message):
170
+ if message.author == client.user:
171
+ return
172
+
173
+ if message.content.startswith('!hello'):
174
+ await message.channel.send('Hello!')
175
+
176
+ client.run(os.getenv('DISCORD_TOKEN'))
177
+ ```
178
+
179
+ ## Commands
180
+
181
+ ### Basic Command
182
+
183
+ ```python
184
+ @bot.command()
185
+ async def hello(ctx):
186
+ await ctx.send(f'Hello {ctx.author.mention}!')
187
+ ```
188
+
189
+ ### Command with Arguments
190
+
191
+ ```python
192
+ @bot.command()
193
+ async def say(ctx, *, message: str):
194
+ await ctx.send(message)
195
+
196
+ @bot.command()
197
+ async def add(ctx, a: int, b: int):
198
+ await ctx.send(f'{a} + {b} = {a + b}')
199
+ ```
200
+
201
+ ### Command with Optional Arguments
202
+
203
+ ```python
204
+ @bot.command()
205
+ async def greet(ctx, name: str = None):
206
+ if name is None:
207
+ await ctx.send(f'Hello {ctx.author.name}!')
208
+ else:
209
+ await ctx.send(f'Hello {name}!')
210
+ ```
211
+
212
+ ### Command Aliases
213
+
214
+ ```python
215
+ @bot.command(aliases=['p'])
216
+ async def ping(ctx):
217
+ await ctx.send('Pong!')
218
+ ```
219
+
220
+ ### Command with Description
221
+
222
+ ```python
223
+ @bot.command(
224
+ name='info',
225
+ description='Get bot information',
226
+ help='Displays information about the bot'
227
+ )
228
+ async def info(ctx):
229
+ await ctx.send('This is my Discord bot!')
230
+ ```
231
+
232
+ ### Converters
233
+
234
+ ```python
235
+ @bot.command()
236
+ async def kick(ctx, member: discord.Member, *, reason: str = 'No reason provided'):
237
+ await member.kick(reason=reason)
238
+ await ctx.send(f'{member.mention} has been kicked.')
239
+
240
+ @bot.command()
241
+ async def ban(ctx, user: discord.User, *, reason: str = None):
242
+ await ctx.guild.ban(user, reason=reason)
243
+ await ctx.send(f'{user.mention} has been banned.')
244
+ ```
245
+
246
+ ## Slash Commands (Application Commands)
247
+
248
+ Slash commands provide a better user experience with autocomplete and validation.
249
+
250
+ ### Basic Slash Command
251
+
252
+ ```python
253
+ import discord
254
+ from discord import app_commands
255
+
256
+ intents = discord.Intents.default()
257
+ client = discord.Client(intents=intents)
258
+ tree = app_commands.CommandTree(client)
259
+
260
+ @tree.command(name='ping', description='Replies with Pong!')
261
+ async def ping(interaction: discord.Interaction):
262
+ await interaction.response.send_message('Pong!')
263
+
264
+ @client.event
265
+ async def on_ready():
266
+ await tree.sync()
267
+ print(f'{client.user} is ready!')
268
+
269
+ client.run(os.getenv('DISCORD_TOKEN'))
270
+ ```
271
+
272
+ ### Slash Command with Parameters
273
+
274
+ ```python
275
+ @tree.command(name='greet', description='Greet a user')
276
+ @app_commands.describe(user='The user to greet', message='Custom greeting message')
277
+ async def greet(interaction: discord.Interaction, user: discord.Member, message: str = 'Hello'):
278
+ await interaction.response.send_message(f'{message}, {user.mention}!')
279
+ ```
280
+
281
+ ### Slash Command with Choices
282
+
283
+ ```python
284
+ @tree.command(name='color', description='Choose a color')
285
+ @app_commands.describe(color='Your favorite color')
286
+ @app_commands.choices(color=[
287
+ app_commands.Choice(name='Red', value='red'),
288
+ app_commands.Choice(name='Blue', value='blue'),
289
+ app_commands.Choice(name='Green', value='green'),
290
+ ])
291
+ async def color(interaction: discord.Interaction, color: app_commands.Choice[str]):
292
+ await interaction.response.send_message(f'You chose {color.name}!')
293
+ ```
294
+
295
+ ### Autocomplete
296
+
297
+ ```python
298
+ async def fruit_autocomplete(
299
+ interaction: discord.Interaction,
300
+ current: str,
301
+ ) -> list[app_commands.Choice[str]]:
302
+ fruits = ['apple', 'banana', 'cherry', 'date', 'elderberry']
303
+ return [
304
+ app_commands.Choice(name=fruit, value=fruit)
305
+ for fruit in fruits if current.lower() in fruit.lower()
306
+ ]
307
+
308
+ @tree.command(name='fruit', description='Choose a fruit')
309
+ @app_commands.autocomplete(fruit=fruit_autocomplete)
310
+ async def fruit(interaction: discord.Interaction, fruit: str):
311
+ await interaction.response.send_message(f'You chose: {fruit}')
312
+ ```
313
+
314
+ ### Hybrid Commands
315
+
316
+ Hybrid commands work as both slash commands and text commands:
317
+
318
+ ```python
319
+ from discord.ext import commands
320
+
321
+ bot = commands.Bot(command_prefix='!', intents=intents)
322
+
323
+ @bot.hybrid_command(name='ping', description='Check bot latency')
324
+ async def ping(ctx):
325
+ await ctx.send(f'Pong! Latency: {round(bot.latency * 1000)}ms')
326
+
327
+ @bot.event
328
+ async def on_ready():
329
+ await bot.tree.sync()
330
+ print(f'{bot.user} is ready!')
331
+
332
+ bot.run(os.getenv('DISCORD_TOKEN'))
333
+ ```
334
+
335
+ ## Embeds
336
+
337
+ Embeds allow you to send rich, formatted messages.
338
+
339
+ ### Basic Embed
340
+
341
+ ```python
342
+ embed = discord.Embed(
343
+ title='Embed Title',
344
+ description='This is an embed description',
345
+ color=discord.Color.blue()
346
+ )
347
+ await ctx.send(embed=embed)
348
+ ```
349
+
350
+ ### Advanced Embed
351
+
352
+ ```python
353
+ embed = discord.Embed(
354
+ title='Advanced Embed',
355
+ description='This is a detailed embed',
356
+ color=0x00ff00,
357
+ url='https://discordpy.readthedocs.io/',
358
+ timestamp=discord.utils.utcnow()
359
+ )
360
+
361
+ embed.set_author(
362
+ name='Author Name',
363
+ url='https://discordpy.readthedocs.io/',
364
+ icon_url='https://i.imgur.com/AfFp7pu.png'
365
+ )
366
+ embed.set_thumbnail(url='https://i.imgur.com/AfFp7pu.png')
367
+ embed.set_image(url='https://i.imgur.com/AfFp7pu.png')
368
+
369
+ embed.add_field(name='Field 1', value='Value 1', inline=True)
370
+ embed.add_field(name='Field 2', value='Value 2', inline=True)
371
+ embed.add_field(name='Field 3', value='Value 3', inline=False)
372
+
373
+ embed.set_footer(text='Footer text', icon_url='https://i.imgur.com/AfFp7pu.png')
374
+
375
+ await ctx.send(embed=embed)
376
+ ```
377
+
378
+ ### Embed Colors
379
+
380
+ ```python
381
+ # Using Color class
382
+ embed.color = discord.Color.red()
383
+ embed.color = discord.Color.blue()
384
+ embed.color = discord.Color.green()
385
+ embed.color = discord.Color.gold()
386
+
387
+ # Using hex
388
+ embed.color = 0x00ff00
389
+
390
+ # Using RGB
391
+ embed.color = discord.Color.from_rgb(255, 0, 0)
392
+ ```
393
+
394
+ ## Buttons
395
+
396
+ Buttons are interactive UI components.
397
+
398
+ ### Basic Button
399
+
400
+ ```python
401
+ import discord
402
+ from discord.ui import Button, View
403
+
404
+ class MyView(View):
405
+ @discord.ui.button(label='Click me!', style=discord.ButtonStyle.primary)
406
+ async def button_callback(self, interaction: discord.Interaction, button: Button):
407
+ await interaction.response.send_message('Button clicked!', ephemeral=True)
408
+
409
+ @bot.command()
410
+ async def buttons(ctx):
411
+ view = MyView()
412
+ await ctx.send('Click a button:', view=view)
413
+ ```
414
+
415
+ ### Multiple Buttons
416
+
417
+ ```python
418
+ class MyView(View):
419
+ @discord.ui.button(label='Primary', style=discord.ButtonStyle.primary)
420
+ async def primary(self, interaction: discord.Interaction, button: Button):
421
+ await interaction.response.send_message('Primary clicked!', ephemeral=True)
422
+
423
+ @discord.ui.button(label='Secondary', style=discord.ButtonStyle.secondary)
424
+ async def secondary(self, interaction: discord.Interaction, button: Button):
425
+ await interaction.response.send_message('Secondary clicked!', ephemeral=True)
426
+
427
+ @discord.ui.button(label='Success', style=discord.ButtonStyle.success)
428
+ async def success(self, interaction: discord.Interaction, button: Button):
429
+ await interaction.response.send_message('Success clicked!', ephemeral=True)
430
+
431
+ @discord.ui.button(label='Danger', style=discord.ButtonStyle.danger)
432
+ async def danger(self, interaction: discord.Interaction, button: Button):
433
+ await interaction.response.send_message('Danger clicked!', ephemeral=True)
434
+
435
+ @bot.command()
436
+ async def buttons(ctx):
437
+ view = MyView()
438
+ await ctx.send('Choose a button:', view=view)
439
+ ```
440
+
441
+ ### Link Button
442
+
443
+ ```python
444
+ view = View()
445
+ button = Button(label='Visit Website', url='https://discordpy.readthedocs.io/')
446
+ view.add_item(button)
447
+
448
+ await ctx.send('Visit our docs:', view=view)
449
+ ```
450
+
451
+ ### Disabled Button
452
+
453
+ ```python
454
+ @discord.ui.button(label='Disabled', style=discord.ButtonStyle.primary, disabled=True)
455
+ async def disabled_button(self, interaction: discord.Interaction, button: Button):
456
+ pass
457
+ ```
458
+
459
+ ### Button with Emoji
460
+
461
+ ```python
462
+ @discord.ui.button(label='Like', style=discord.ButtonStyle.primary, emoji='👍')
463
+ async def like_button(self, interaction: discord.Interaction, button: Button):
464
+ await interaction.response.send_message('Thanks!', ephemeral=True)
465
+ ```
466
+
467
+ ## Select Menus
468
+
469
+ Select menus (dropdowns) allow users to choose from multiple options.
470
+
471
+ ### String Select Menu
472
+
473
+ ```python
474
+ import discord
475
+ from discord.ui import Select, View
476
+
477
+ class MyView(View):
478
+ @discord.ui.select(
479
+ placeholder='Choose an option...',
480
+ options=[
481
+ discord.SelectOption(label='Option 1', description='This is option 1', value='1'),
482
+ discord.SelectOption(label='Option 2', description='This is option 2', value='2'),
483
+ discord.SelectOption(label='Option 3', description='This is option 3', value='3'),
484
+ ]
485
+ )
486
+ async def select_callback(self, interaction: discord.Interaction, select: Select):
487
+ await interaction.response.send_message(f'You selected: {select.values[0]}', ephemeral=True)
488
+
489
+ @bot.command()
490
+ async def dropdown(ctx):
491
+ view = MyView()
492
+ await ctx.send('Choose an option:', view=view)
493
+ ```
494
+
495
+ ### User Select Menu
496
+
497
+ ```python
498
+ class MyView(View):
499
+ @discord.ui.select(cls=discord.ui.UserSelect, placeholder='Select a user')
500
+ async def user_select(self, interaction: discord.Interaction, select: discord.ui.UserSelect):
501
+ user = select.values[0]
502
+ await interaction.response.send_message(f'You selected: {user.mention}', ephemeral=True)
503
+ ```
504
+
505
+ ### Role Select Menu
506
+
507
+ ```python
508
+ class MyView(View):
509
+ @discord.ui.select(cls=discord.ui.RoleSelect, placeholder='Select a role')
510
+ async def role_select(self, interaction: discord.Interaction, select: discord.ui.RoleSelect):
511
+ role = select.values[0]
512
+ await interaction.response.send_message(f'You selected: {role.mention}', ephemeral=True)
513
+ ```
514
+
515
+ ### Channel Select Menu
516
+
517
+ ```python
518
+ class MyView(View):
519
+ @discord.ui.select(
520
+ cls=discord.ui.ChannelSelect,
521
+ placeholder='Select a channel',
522
+ channel_types=[discord.ChannelType.text, discord.ChannelType.voice]
523
+ )
524
+ async def channel_select(self, interaction: discord.Interaction, select: discord.ui.ChannelSelect):
525
+ channel = select.values[0]
526
+ await interaction.response.send_message(f'You selected: {channel.mention}', ephemeral=True)
527
+ ```
528
+
529
+ ## Modals
530
+
531
+ Modals are pop-up forms for user input.
532
+
533
+ ### Basic Modal
534
+
535
+ ```python
536
+ import discord
537
+ from discord.ui import Modal, TextInput
538
+
539
+ class FeedbackModal(Modal, title='Feedback Form'):
540
+ name = TextInput(label='Name', placeholder='Your name here...', required=True)
541
+ feedback = TextInput(
542
+ label='Feedback',
543
+ style=discord.TextStyle.paragraph,
544
+ placeholder='Tell us what you think...',
545
+ required=True,
546
+ max_length=1000
547
+ )
548
+
549
+ async def on_submit(self, interaction: discord.Interaction):
550
+ await interaction.response.send_message(
551
+ f'Thanks for your feedback, {self.name.value}!',
552
+ ephemeral=True
553
+ )
554
+
555
+ @bot.command()
556
+ async def feedback(ctx):
557
+ await ctx.send('Click the button to give feedback!')
558
+
559
+ # To show modal from button
560
+ class FeedbackView(discord.ui.View):
561
+ @discord.ui.button(label='Give Feedback', style=discord.ButtonStyle.primary)
562
+ async def feedback_button(self, interaction: discord.Interaction, button: discord.ui.Button):
563
+ await interaction.response.send_modal(FeedbackModal())
564
+
565
+ @bot.command()
566
+ async def feedback(ctx):
567
+ view = FeedbackView()
568
+ await ctx.send('Click to provide feedback:', view=view)
569
+ ```
570
+
571
+ ### Modal from Slash Command
572
+
573
+ ```python
574
+ @tree.command(name='feedback', description='Provide feedback')
575
+ async def feedback_slash(interaction: discord.Interaction):
576
+ await interaction.response.send_modal(FeedbackModal())
577
+ ```
578
+
579
+ ## Context Menus
580
+
581
+ Context menus appear when right-clicking on users or messages.
582
+
583
+ ### User Context Menu
584
+
585
+ ```python
586
+ @tree.context_menu(name='Get User Info')
587
+ async def user_info(interaction: discord.Interaction, user: discord.Member):
588
+ await interaction.response.send_message(
589
+ f'User: {user.name}\nID: {user.id}\nJoined: {user.joined_at}',
590
+ ephemeral=True
591
+ )
592
+ ```
593
+
594
+ ### Message Context Menu
595
+
596
+ ```python
597
+ @tree.context_menu(name='Report Message')
598
+ async def report_message(interaction: discord.Interaction, message: discord.Message):
599
+ await interaction.response.send_message(
600
+ f'Reported message from {message.author.mention}',
601
+ ephemeral=True
602
+ )
603
+ ```
604
+
605
+ ## Events
606
+
607
+ ### Common Events
608
+
609
+ ```python
610
+ @bot.event
611
+ async def on_ready():
612
+ print(f'{bot.user} has connected to Discord!')
613
+ print(f'Bot ID: {bot.user.id}')
614
+
615
+ @bot.event
616
+ async def on_message(message):
617
+ if message.author == bot.user:
618
+ return
619
+
620
+ if 'hello' in message.content.lower():
621
+ await message.channel.send('Hello!')
622
+
623
+ # Important: process commands after custom on_message logic
624
+ await bot.process_commands(message)
625
+
626
+ @bot.event
627
+ async def on_member_join(member):
628
+ channel = member.guild.system_channel
629
+ if channel is not None:
630
+ await channel.send(f'Welcome {member.mention}!')
631
+
632
+ @bot.event
633
+ async def on_member_remove(member):
634
+ channel = member.guild.system_channel
635
+ if channel is not None:
636
+ await channel.send(f'{member.name} has left the server.')
637
+
638
+ @bot.event
639
+ async def on_message_delete(message):
640
+ print(f'Message deleted: {message.content}')
641
+
642
+ @bot.event
643
+ async def on_message_edit(before, after):
644
+ print(f'Message edited from "{before.content}" to "{after.content}"')
645
+
646
+ @bot.event
647
+ async def on_reaction_add(reaction, user):
648
+ print(f'{user.name} added {reaction.emoji}')
649
+
650
+ @bot.event
651
+ async def on_guild_join(guild):
652
+ print(f'Joined guild: {guild.name}')
653
+
654
+ @bot.event
655
+ async def on_error(event, *args, **kwargs):
656
+ print(f'Error in {event}')
657
+ ```
658
+
659
+ ## Cogs
660
+
661
+ Cogs organize commands and listeners into modular classes.
662
+
663
+ ### Basic Cog
664
+
665
+ ```python
666
+ from discord.ext import commands
667
+
668
+ class MyCog(commands.Cog):
669
+ def __init__(self, bot):
670
+ self.bot = bot
671
+
672
+ @commands.command()
673
+ async def hello(self, ctx):
674
+ await ctx.send('Hello from cog!')
675
+
676
+ @commands.Cog.listener()
677
+ async def on_message(self, message):
678
+ if message.author == self.bot.user:
679
+ return
680
+ print(f'Message from {message.author}: {message.content}')
681
+
682
+ async def setup(bot):
683
+ await bot.add_cog(MyCog(bot))
684
+ ```
685
+
686
+ ### Loading Cogs
687
+
688
+ ```python
689
+ import asyncio
690
+
691
+ async def load_extensions():
692
+ for filename in os.listdir('./cogs'):
693
+ if filename.endswith('.py'):
694
+ await bot.load_extension(f'cogs.{filename[:-3]}')
695
+
696
+ async def main():
697
+ async with bot:
698
+ await load_extensions()
699
+ await bot.start(os.getenv('DISCORD_TOKEN'))
700
+
701
+ asyncio.run(main())
702
+ ```
703
+
704
+ ### Cog with Slash Commands
705
+
706
+ ```python
707
+ from discord import app_commands
708
+
709
+ class SlashCog(commands.Cog):
710
+ def __init__(self, bot):
711
+ self.bot = bot
712
+
713
+ @app_commands.command(name='ping', description='Ping command')
714
+ async def ping(self, interaction: discord.Interaction):
715
+ await interaction.response.send_message('Pong!')
716
+
717
+ @commands.Cog.listener()
718
+ async def on_ready(self):
719
+ print(f'{self.__class__.__name__} cog is ready!')
720
+
721
+ async def setup(bot):
722
+ await bot.add_cog(SlashCog(bot))
723
+ ```
724
+
725
+ ## Permissions
726
+
727
+ ### Check User Permissions
728
+
729
+ ```python
730
+ @bot.command()
731
+ @commands.has_permissions(administrator=True)
732
+ async def admin(ctx):
733
+ await ctx.send('You are an admin!')
734
+
735
+ @bot.command()
736
+ @commands.has_permissions(manage_messages=True)
737
+ async def purge(ctx, amount: int):
738
+ await ctx.channel.purge(limit=amount + 1)
739
+ await ctx.send(f'Deleted {amount} messages.', delete_after=5)
740
+ ```
741
+
742
+ ### Check Bot Permissions
743
+
744
+ ```python
745
+ @bot.command()
746
+ @commands.bot_has_permissions(manage_roles=True)
747
+ async def mute(ctx, member: discord.Member):
748
+ # Bot can manage roles
749
+ await ctx.send(f'{member.mention} has been muted.')
750
+ ```
751
+
752
+ ### Custom Permission Checks
753
+
754
+ ```python
755
+ def is_owner():
756
+ async def predicate(ctx):
757
+ return ctx.author.id == 123456789 # Your user ID
758
+ return commands.check(predicate)
759
+
760
+ @bot.command()
761
+ @is_owner()
762
+ async def secret(ctx):
763
+ await ctx.send('Secret command for owner only!')
764
+ ```
765
+
766
+ ### Slash Command Permissions
767
+
768
+ ```python
769
+ @tree.command(name='admin', description='Admin only command')
770
+ @app_commands.default_permissions(administrator=True)
771
+ async def admin_slash(interaction: discord.Interaction):
772
+ await interaction.response.send_message('Admin command!', ephemeral=True)
773
+ ```
774
+
775
+ ## Error Handling
776
+
777
+ ### Command Error Handling
778
+
779
+ ```python
780
+ @bot.event
781
+ async def on_command_error(ctx, error):
782
+ if isinstance(error, commands.MissingRequiredArgument):
783
+ await ctx.send('Missing required argument!')
784
+ elif isinstance(error, commands.MissingPermissions):
785
+ await ctx.send("You don't have permission to use this command!")
786
+ elif isinstance(error, commands.BotMissingPermissions):
787
+ await ctx.send("I don't have permission to do that!")
788
+ elif isinstance(error, commands.CommandNotFound):
789
+ pass # Ignore command not found
790
+ else:
791
+ print(f'Error: {error}')
792
+ ```
793
+
794
+ ### Local Error Handler
795
+
796
+ ```python
797
+ @bot.command()
798
+ async def divide(ctx, a: int, b: int):
799
+ result = a / b
800
+ await ctx.send(f'{a} / {b} = {result}')
801
+
802
+ @divide.error
803
+ async def divide_error(ctx, error):
804
+ if isinstance(error, commands.BadArgument):
805
+ await ctx.send('Please provide valid numbers!')
806
+ elif isinstance(error, ZeroDivisionError):
807
+ await ctx.send("Cannot divide by zero!")
808
+ ```
809
+
810
+ ### Interaction Error Handling
811
+
812
+ ```python
813
+ @tree.error
814
+ async def on_app_command_error(interaction: discord.Interaction, error: app_commands.AppCommandError):
815
+ if isinstance(error, app_commands.CommandOnCooldown):
816
+ await interaction.response.send_message(
817
+ f'Command is on cooldown. Try again in {error.retry_after:.2f}s',
818
+ ephemeral=True
819
+ )
820
+ elif isinstance(error, app_commands.MissingPermissions):
821
+ await interaction.response.send_message(
822
+ "You don't have permission to use this command!",
823
+ ephemeral=True
824
+ )
825
+ else:
826
+ await interaction.response.send_message('An error occurred!', ephemeral=True)
827
+ ```
828
+
829
+ ## Cooldowns
830
+
831
+ ### Command Cooldown
832
+
833
+ ```python
834
+ from discord.ext import commands
835
+
836
+ @bot.command()
837
+ @commands.cooldown(1, 60, commands.BucketType.user) # 1 use per 60 seconds per user
838
+ async def daily(ctx):
839
+ await ctx.send('You claimed your daily reward!')
840
+
841
+ @daily.error
842
+ async def daily_error(ctx, error):
843
+ if isinstance(error, commands.CommandOnCooldown):
844
+ await ctx.send(f'Try again in {error.retry_after:.2f} seconds.')
845
+ ```
846
+
847
+ ### Slash Command Cooldown
848
+
849
+ ```python
850
+ @tree.command(name='daily', description='Claim daily reward')
851
+ @app_commands.checks.cooldown(1, 60, key=lambda i: i.user.id)
852
+ async def daily_slash(interaction: discord.Interaction):
853
+ await interaction.response.send_message('Daily reward claimed!', ephemeral=True)
854
+ ```
855
+
856
+ ## Fetching Data
857
+
858
+ ### Fetch User
859
+
860
+ ```python
861
+ user = await bot.fetch_user(123456789)
862
+ print(user.name)
863
+ ```
864
+
865
+ ### Fetch Member
866
+
867
+ ```python
868
+ member = await ctx.guild.fetch_member(123456789)
869
+ print(member.display_name)
870
+ ```
871
+
872
+ ### Fetch Channel
873
+
874
+ ```python
875
+ channel = await bot.fetch_channel(123456789)
876
+ await channel.send('Hello!')
877
+ ```
878
+
879
+ ### Fetch Guild
880
+
881
+ ```python
882
+ guild = await bot.fetch_guild(123456789)
883
+ print(guild.name)
884
+ ```
885
+
886
+ ### Fetch Messages
887
+
888
+ ```python
889
+ # Fetch last 10 messages
890
+ messages = [message async for message in channel.history(limit=10)]
891
+
892
+ # Fetch specific message
893
+ message = await channel.fetch_message(123456789)
894
+ ```
895
+
896
+ ## Sending Messages
897
+
898
+ ### Basic Send
899
+
900
+ ```python
901
+ await ctx.send('Hello!')
902
+ await channel.send('Hello!')
903
+ ```
904
+
905
+ ### Send with Embed
906
+
907
+ ```python
908
+ embed = discord.Embed(title='Title', description='Description')
909
+ await ctx.send(embed=embed)
910
+ ```
911
+
912
+ ### Send with Components
913
+
914
+ ```python
915
+ view = MyView()
916
+ await ctx.send('Click a button:', view=view)
917
+ ```
918
+
919
+ ### Send Ephemeral (Slash Commands)
920
+
921
+ ```python
922
+ await interaction.response.send_message('Secret message!', ephemeral=True)
923
+ ```
924
+
925
+ ### Send File
926
+
927
+ ```python
928
+ file = discord.File('path/to/file.png')
929
+ await ctx.send(file=file)
930
+
931
+ # With embed
932
+ embed = discord.Embed(title='Image')
933
+ embed.set_image(url='attachment://file.png')
934
+ await ctx.send(embed=embed, file=file)
935
+ ```
936
+
937
+ ### Edit Message
938
+
939
+ ```python
940
+ message = await ctx.send('Original message')
941
+ await message.edit(content='Edited message')
942
+ ```
943
+
944
+ ### Delete Message
945
+
946
+ ```python
947
+ message = await ctx.send('This will be deleted')
948
+ await message.delete()
949
+
950
+ # Delete after delay
951
+ await ctx.send('Deleted in 5s', delete_after=5)
952
+ ```
953
+
954
+ ## Reactions
955
+
956
+ ### Add Reaction
957
+
958
+ ```python
959
+ message = await ctx.send('React to this!')
960
+ await message.add_reaction('👍')
961
+ await message.add_reaction('👎')
962
+ ```
963
+
964
+ ### Remove Reaction
965
+
966
+ ```python
967
+ await message.remove_reaction('👍', ctx.author)
968
+ ```
969
+
970
+ ### Clear Reactions
971
+
972
+ ```python
973
+ await message.clear_reactions()
974
+ ```
975
+
976
+ ### Wait for Reaction
977
+
978
+ ```python
979
+ message = await ctx.send('React with 👍')
980
+ await message.add_reaction('👍')
981
+
982
+ def check(reaction, user):
983
+ return user == ctx.author and str(reaction.emoji) == '👍'
984
+
985
+ try:
986
+ reaction, user = await bot.wait_for('reaction_add', timeout=60.0, check=check)
987
+ await ctx.send('Thanks for reacting!')
988
+ except asyncio.TimeoutError:
989
+ await ctx.send('You took too long!')
990
+ ```
991
+
992
+ ## Tasks and Loops
993
+
994
+ ### Basic Loop
995
+
996
+ ```python
997
+ from discord.ext import tasks
998
+
999
+ @tasks.loop(seconds=60)
1000
+ async def my_task():
1001
+ channel = bot.get_channel(123456789)
1002
+ await channel.send('This runs every minute!')
1003
+
1004
+ @my_task.before_loop
1005
+ async def before_my_task():
1006
+ await bot.wait_until_ready()
1007
+
1008
+ my_task.start()
1009
+ ```
1010
+
1011
+ ### Loop with Time
1012
+
1013
+ ```python
1014
+ import datetime
1015
+
1016
+ @tasks.loop(time=datetime.time(hour=12, minute=0))
1017
+ async def daily_task():
1018
+ channel = bot.get_channel(123456789)
1019
+ await channel.send('Daily message at noon!')
1020
+
1021
+ daily_task.start()
1022
+ ```
1023
+
1024
+ ### Cancel Loop
1025
+
1026
+ ```python
1027
+ my_task.stop()
1028
+ ```
1029
+
1030
+ ## Voice
1031
+
1032
+ ### Join Voice Channel
1033
+
1034
+ ```python
1035
+ @bot.command()
1036
+ async def join(ctx):
1037
+ if ctx.author.voice:
1038
+ channel = ctx.author.voice.channel
1039
+ await channel.connect()
1040
+ else:
1041
+ await ctx.send('You are not in a voice channel!')
1042
+ ```
1043
+
1044
+ ### Leave Voice Channel
1045
+
1046
+ ```python
1047
+ @bot.command()
1048
+ async def leave(ctx):
1049
+ if ctx.voice_client:
1050
+ await ctx.voice_client.disconnect()
1051
+ else:
1052
+ await ctx.send('I am not in a voice channel!')
1053
+ ```
1054
+
1055
+ ### Play Audio
1056
+
1057
+ ```python
1058
+ import discord
1059
+ from discord import FFmpegPCMAudio
1060
+
1061
+ @bot.command()
1062
+ async def play(ctx):
1063
+ if ctx.voice_client:
1064
+ source = FFmpegPCMAudio('audio.mp3')
1065
+ ctx.voice_client.play(source)
1066
+ else:
1067
+ await ctx.send('Bot is not in a voice channel!')
1068
+ ```
1069
+
1070
+ ## Advanced Features
1071
+
1072
+ ### Paginator
1073
+
1074
+ ```python
1075
+ from discord.ext import menus
1076
+
1077
+ class MySource(menus.ListPageSource):
1078
+ def __init__(self, data):
1079
+ super().__init__(data, per_page=10)
1080
+
1081
+ async def format_page(self, menu, entries):
1082
+ offset = menu.current_page * self.per_page
1083
+ return '\n'.join(f'{i}. {v}' for i, v in enumerate(entries, start=offset))
1084
+
1085
+ @bot.command()
1086
+ async def pages(ctx):
1087
+ data = [f'Item {i}' for i in range(1, 100)]
1088
+ pages = menus.MenuPages(source=MySource(data))
1089
+ await pages.start(ctx)
1090
+ ```
1091
+
1092
+ ### Wait For Message
1093
+
1094
+ ```python
1095
+ @bot.command()
1096
+ async def ask(ctx):
1097
+ await ctx.send('What is your name?')
1098
+
1099
+ def check(m):
1100
+ return m.author == ctx.author and m.channel == ctx.channel
1101
+
1102
+ try:
1103
+ msg = await bot.wait_for('message', check=check, timeout=30.0)
1104
+ await ctx.send(f'Hello {msg.content}!')
1105
+ except asyncio.TimeoutError:
1106
+ await ctx.send('You took too long!')
1107
+ ```
1108
+
1109
+ ### Webhooks
1110
+
1111
+ ```python
1112
+ # Create webhook
1113
+ webhook = await channel.create_webhook(name='My Webhook')
1114
+
1115
+ # Send via webhook
1116
+ await webhook.send('Message from webhook!', username='Custom Name')
1117
+
1118
+ # Get webhooks
1119
+ webhooks = await channel.webhooks()
1120
+ for webhook in webhooks:
1121
+ print(webhook.name)
1122
+ ```
1123
+
1124
+ ## Useful Links
1125
+
1126
+ - Documentation: https://discordpy.readthedocs.io/en/stable/
1127
+ - API Reference: https://discordpy.readthedocs.io/en/stable/api.html
1128
+ - Discord API Docs: https://discord.com/developers/docs
1129
+ - Developer Portal: https://discord.com/developers/applications
1130
+ - GitHub: https://github.com/Rapptz/discord.py