0
# Application Commands
1
2
Modern Discord application commands including slash commands, user context menu commands, and message context menu commands. These provide native Discord UI integration with parameter validation, autocomplete, and rich interaction handling.
3
4
## Capabilities
5
6
### Slash Commands
7
8
Interactive commands that appear in Discord's command picker with built-in parameter validation and autocomplete support.
9
10
```python { .api }
11
def slash_command(
12
name: Optional[str] = None,
13
*,
14
description: Optional[str] = None,
15
guild_ids: Optional[Sequence[int]] = None,
16
dm_permission: Optional[bool] = None,
17
default_member_permissions: Optional[Union[Permissions, int]] = None,
18
nsfw: Optional[bool] = None,
19
auto_sync: Optional[bool] = None,
20
extras: Optional[Dict[str, Any]] = None
21
):
22
"""
23
Decorator for creating slash commands.
24
25
Parameters:
26
- name: Command name (defaults to function name)
27
- description: Command description shown in Discord
28
- guild_ids: Specific guilds to register command in (for testing)
29
- dm_permission: Whether command can be used in DMs
30
- default_member_permissions: Required permissions to use command
31
- nsfw: Whether command is NSFW
32
- auto_sync: Whether to auto-sync this command
33
- extras: Additional metadata
34
35
Returns:
36
Decorator function
37
"""
38
39
class SlashCommand:
40
def __init__(self): ...
41
42
name: str
43
description: str
44
guild_ids: Optional[List[int]]
45
dm_permission: Optional[bool]
46
default_member_permissions: Optional[Permissions]
47
nsfw: Optional[bool]
48
options: List[Option]
49
qualified_name: str
50
51
async def __call__(self, interaction: ApplicationCommandInteraction, *args, **kwargs) -> Any:
52
"""Execute the slash command."""
53
54
class Option:
55
def __init__(
56
self,
57
name: str,
58
description: str,
59
type: OptionType,
60
*,
61
required: bool = True,
62
choices: Optional[List[OptionChoice]] = None,
63
autocomplete: Optional[bool] = None,
64
channel_types: Optional[List[ChannelType]] = None,
65
min_value: Optional[Union[int, float]] = None,
66
max_value: Optional[Union[int, float]] = None,
67
min_length: Optional[int] = None,
68
max_length: Optional[int] = None
69
):
70
"""
71
Slash command option/parameter definition.
72
73
Parameters:
74
- name: Option name
75
- description: Option description
76
- type: Option type (string, integer, etc.)
77
- required: Whether option is required
78
- choices: Predefined choices for the option
79
- autocomplete: Whether option supports autocomplete
80
- channel_types: Allowed channel types (for channel options)
81
- min_value: Minimum value (for number options)
82
- max_value: Maximum value (for number options)
83
- min_length: Minimum string length
84
- max_length: Maximum string length
85
"""
86
87
class Param:
88
def __init__(
89
self,
90
default: Any = ...,
91
*,
92
name: Optional[str] = None,
93
description: Optional[str] = None,
94
choices: Optional[List[Union[str, int, float, OptionChoice]]] = None,
95
converter: Optional[Union[Converter, Callable[[str], Any]]] = None,
96
autocomplete: Optional[Union[bool, Callable[..., Awaitable[List[OptionChoice]]]]] = None,
97
channel_types: Optional[List[ChannelType]] = None,
98
min_value: Optional[Union[int, float]] = None,
99
max_value: Optional[Union[int, float]] = None,
100
min_length: Optional[int] = None,
101
max_length: Optional[int] = None,
102
large: Optional[bool] = None
103
):
104
"""
105
Parameter descriptor for advanced slash command parameters.
106
107
Parameters:
108
- default: Default value (use ... for required parameters)
109
- name: Parameter name override
110
- description: Parameter description
111
- choices: Predefined choices
112
- converter: Custom converter function
113
- autocomplete: Autocomplete function or boolean
114
- channel_types: Allowed channel types
115
- min_value: Minimum numeric value
116
- max_value: Maximum numeric value
117
- min_length: Minimum string length
118
- max_length: Maximum string length
119
- large: Whether to use large number type
120
"""
121
```
122
123
### User Context Menu Commands
124
125
Right-click context menu commands that operate on users and members.
126
127
```python { .api }
128
def user_command(
129
name: Optional[str] = None,
130
*,
131
guild_ids: Optional[Sequence[int]] = None,
132
dm_permission: Optional[bool] = None,
133
default_member_permissions: Optional[Union[Permissions, int]] = None,
134
nsfw: Optional[bool] = None,
135
auto_sync: Optional[bool] = None,
136
extras: Optional[Dict[str, Any]] = None
137
):
138
"""
139
Decorator for creating user context menu commands.
140
141
Parameters:
142
- name: Command name (defaults to function name)
143
- guild_ids: Specific guilds to register command in
144
- dm_permission: Whether command can be used in DMs
145
- default_member_permissions: Required permissions
146
- nsfw: Whether command is NSFW
147
- auto_sync: Whether to auto-sync this command
148
- extras: Additional metadata
149
150
Returns:
151
Decorator function
152
"""
153
154
class UserCommand:
155
def __init__(self): ...
156
157
name: str
158
guild_ids: Optional[List[int]]
159
dm_permission: Optional[bool]
160
default_member_permissions: Optional[Permissions]
161
nsfw: Optional[bool]
162
163
async def __call__(self, interaction: UserCommandInteraction, user: Union[User, Member]) -> Any:
164
"""Execute the user command."""
165
```
166
167
### Message Context Menu Commands
168
169
Right-click context menu commands that operate on messages.
170
171
```python { .api }
172
def message_command(
173
name: Optional[str] = None,
174
*,
175
guild_ids: Optional[Sequence[int]] = None,
176
dm_permission: Optional[bool] = None,
177
default_member_permissions: Optional[Union[Permissions, int]] = None,
178
nsfw: Optional[bool] = None,
179
auto_sync: Optional[bool] = None,
180
extras: Optional[Dict[str, Any]] = None
181
):
182
"""
183
Decorator for creating message context menu commands.
184
185
Parameters:
186
- name: Command name (defaults to function name)
187
- guild_ids: Specific guilds to register command in
188
- dm_permission: Whether command can be used in DMs
189
- default_member_permissions: Required permissions
190
- nsfw: Whether command is NSFW
191
- auto_sync: Whether to auto-sync this command
192
- extras: Additional metadata
193
194
Returns:
195
Decorator function
196
"""
197
198
class MessageCommand:
199
def __init__(self): ...
200
201
name: str
202
guild_ids: Optional[List[int]]
203
dm_permission: Optional[bool]
204
default_member_permissions: Optional[Permissions]
205
nsfw: Optional[bool]
206
207
async def __call__(self, interaction: MessageCommandInteraction, message: Message) -> Any:
208
"""Execute the message command."""
209
```
210
211
### Application Command Interactions
212
213
Interaction objects received when application commands are executed.
214
215
```python { .api }
216
class ApplicationCommandInteraction:
217
def __init__(self): ...
218
219
id: int
220
type: InteractionType
221
data: ApplicationCommandInteractionData
222
guild: Optional[Guild]
223
guild_id: Optional[int]
224
channel: Optional[Union[GuildChannel, PartialMessageable]]
225
channel_id: Optional[int]
226
user: Union[User, Member]
227
token: str
228
version: int
229
message: Optional[Message]
230
locale: Optional[Locale]
231
guild_locale: Optional[Locale]
232
created_at: datetime
233
expires_at: datetime
234
235
@property
236
def response(self) -> InteractionResponse:
237
"""Interaction response handler."""
238
239
@property
240
def followup(self) -> Webhook:
241
"""Webhook for followup messages."""
242
243
@property
244
def author(self) -> Union[User, Member]:
245
"""Alias for user."""
246
247
class ApplicationCommandInteractionData:
248
def __init__(self): ...
249
250
id: int
251
name: str
252
type: ApplicationCommandType
253
resolved: Optional[ApplicationCommandInteractionDataResolved]
254
options: List[ApplicationCommandInteractionDataOption]
255
guild_id: Optional[int]
256
target_id: Optional[int]
257
258
class ApplicationCommandInteractionDataOption:
259
def __init__(self): ...
260
261
name: str
262
type: OptionType
263
value: Optional[Union[str, int, float, bool]]
264
options: List[ApplicationCommandInteractionDataOption]
265
focused: Optional[bool]
266
267
class InteractionResponse:
268
def __init__(self): ...
269
270
async def send_message(
271
self,
272
content: Optional[str] = None,
273
*,
274
embed: Optional[Embed] = None,
275
embeds: Optional[List[Embed]] = None,
276
file: Optional[File] = None,
277
files: Optional[List[File]] = None,
278
view: Optional[View] = None,
279
components: Optional[Union[ActionRow, List[ActionRow], List[List[Component]], List[Component]]] = None,
280
tts: bool = False,
281
ephemeral: bool = False,
282
allowed_mentions: Optional[AllowedMentions] = None,
283
suppress_embeds: bool = False,
284
flags: Optional[MessageFlags] = None,
285
delete_after: Optional[float] = None
286
) -> None:
287
"""
288
Send an interaction response message.
289
290
Parameters:
291
- content: Message content
292
- embed: Single embed
293
- embeds: List of embeds
294
- file: Single file
295
- files: List of files
296
- view: UI components view
297
- components: Raw components
298
- tts: Text-to-speech
299
- ephemeral: Whether message is ephemeral (only visible to user)
300
- allowed_mentions: Mention controls
301
- suppress_embeds: Suppress embeds
302
- flags: Message flags
303
- delete_after: Auto-delete timer
304
"""
305
306
async def defer(self, *, ephemeral: bool = False, with_message: bool = False) -> None:
307
"""
308
Defer the interaction response.
309
310
Parameters:
311
- ephemeral: Whether deferred response should be ephemeral
312
- with_message: Whether to show "Bot is thinking..." message
313
"""
314
315
async def edit_message(
316
self,
317
content: Optional[str] = None,
318
*,
319
embed: Optional[Embed] = None,
320
embeds: Optional[List[Embed]] = None,
321
file: Optional[File] = None,
322
files: Optional[List[File]] = None,
323
attachments: Optional[List[Union[Attachment, File]]] = None,
324
view: Optional[View] = None,
325
components: Optional[Union[ActionRow, List[ActionRow], List[List[Component]], List[Component]]] = None,
326
allowed_mentions: Optional[AllowedMentions] = None,
327
delete_after: Optional[float] = None
328
) -> None:
329
"""
330
Edit the original interaction response message.
331
332
Parameters:
333
- content: New message content
334
- embed: Single embed
335
- embeds: List of embeds
336
- file: Single file
337
- files: List of files
338
- attachments: List of attachments/files
339
- view: UI components view
340
- components: Raw components
341
- allowed_mentions: Mention controls
342
- delete_after: Auto-delete timer
343
"""
344
345
async def send_modal(self, modal: Modal) -> None:
346
"""
347
Send a modal dialog response.
348
349
Parameters:
350
- modal: Modal to display
351
"""
352
353
@property
354
def is_done(self) -> bool:
355
"""Whether the interaction has been responded to."""
356
```
357
358
### Autocomplete
359
360
Dynamic option value suggestions for slash command parameters.
361
362
```python { .api }
363
async def autocomplete_function(
364
interaction: ApplicationCommandInteraction,
365
current: str
366
) -> List[OptionChoice]:
367
"""
368
Autocomplete function signature.
369
370
Parameters:
371
- interaction: Command interaction
372
- current: Current user input
373
374
Returns:
375
List of suggested choices (max 25)
376
"""
377
378
class OptionChoice:
379
def __init__(
380
self,
381
name: str,
382
value: Union[str, int, float],
383
*,
384
name_localizations: Optional[Dict[Locale, str]] = None
385
):
386
"""
387
Option choice for slash command parameters.
388
389
Parameters:
390
- name: Choice display name
391
- value: Choice value
392
- name_localizations: Localized names
393
"""
394
395
name: str
396
value: Union[str, int, float]
397
name_localizations: Optional[Dict[Locale, str]]
398
```
399
400
## Usage Examples
401
402
### Basic Slash Commands
403
404
```python
405
import disnake
406
from disnake.ext import commands
407
408
bot = commands.InteractionBot()
409
410
@bot.slash_command(description="Get bot latency")
411
async def ping(inter: disnake.ApplicationCommandInteraction):
412
latency = round(bot.latency * 1000)
413
await inter.response.send_message(f"Pong! {latency}ms")
414
415
@bot.slash_command(description="Say something")
416
async def say(
417
inter: disnake.ApplicationCommandInteraction,
418
message: str = disnake.Param(description="Message to say"),
419
channel: disnake.TextChannel = disnake.Param(default=None, description="Channel to send to")
420
):
421
target = channel or inter.channel
422
await target.send(message)
423
await inter.response.send_message(f"Message sent to {target.mention}!", ephemeral=True)
424
```
425
426
### Advanced Parameter Types
427
428
```python
429
@bot.slash_command(description="User information")
430
async def userinfo(
431
inter: disnake.ApplicationCommandInteraction,
432
user: disnake.Member = disnake.Param(description="User to get info about"),
433
show_avatar: bool = disnake.Param(default=False, description="Show user avatar")
434
):
435
embed = disnake.Embed(title=f"Info for {user.display_name}")
436
embed.add_field(name="Joined", value=user.joined_at.strftime("%Y-%m-%d"))
437
embed.add_field(name="Roles", value=len(user.roles))
438
439
if show_avatar and user.avatar:
440
embed.set_thumbnail(url=user.avatar.url)
441
442
await inter.response.send_message(embed=embed)
443
444
@bot.slash_command(description="Set slowmode")
445
async def slowmode(
446
inter: disnake.ApplicationCommandInteraction,
447
seconds: int = disnake.Param(
448
description="Slowmode delay in seconds",
449
min_value=0,
450
max_value=21600
451
)
452
):
453
await inter.channel.edit(slowmode_delay=seconds)
454
await inter.response.send_message(f"Slowmode set to {seconds} seconds")
455
```
456
457
### Slash Command Groups
458
459
```python
460
@bot.slash_command_group(description="Admin commands")
461
async def admin(inter: disnake.ApplicationCommandInteraction):
462
pass
463
464
@admin.sub_command(description="Ban a user")
465
async def ban(
466
inter: disnake.ApplicationCommandInteraction,
467
user: disnake.Member,
468
reason: str = disnake.Param(default="No reason provided")
469
):
470
await user.ban(reason=reason)
471
await inter.response.send_message(f"Banned {user}", ephemeral=True)
472
473
@admin.sub_command(description="Kick a user")
474
async def kick(
475
inter: disnake.ApplicationCommandInteraction,
476
user: disnake.Member,
477
reason: str = disnake.Param(default="No reason provided")
478
):
479
await user.kick(reason=reason)
480
await inter.response.send_message(f"Kicked {user}", ephemeral=True)
481
```
482
483
### Context Menu Commands
484
485
```python
486
@bot.user_command(name="User Info")
487
async def user_info_context(inter: disnake.UserCommandInteraction, user: disnake.Member):
488
embed = disnake.Embed(title=f"Info for {user.display_name}")
489
embed.add_field(name="ID", value=user.id)
490
embed.add_field(name="Joined", value=user.joined_at.strftime("%Y-%m-%d"))
491
embed.set_thumbnail(url=user.display_avatar.url)
492
493
await inter.response.send_message(embed=embed, ephemeral=True)
494
495
@bot.message_command(name="Pin Message")
496
async def pin_message_context(inter: disnake.MessageCommandInteraction, message: disnake.Message):
497
try:
498
await message.pin()
499
await inter.response.send_message("Message pinned!", ephemeral=True)
500
except disnake.HTTPException:
501
await inter.response.send_message("Failed to pin message.", ephemeral=True)
502
```
503
504
### Autocomplete
505
506
```python
507
# Static autocomplete choices
508
@bot.slash_command(description="Get information about a programming language")
509
async def language(
510
inter: disnake.ApplicationCommandInteraction,
511
lang: str = disnake.Param(
512
description="Programming language",
513
choices=["Python", "JavaScript", "Java", "C++", "Go", "Rust"]
514
)
515
):
516
await inter.response.send_message(f"You chose {lang}!")
517
518
# Dynamic autocomplete
519
async def tag_autocomplete(inter: disnake.ApplicationCommandInteraction, current: str):
520
tags = ["bug", "feature", "question", "documentation", "help", "discussion"]
521
choices = [
522
disnake.OptionChoice(name=tag, value=tag)
523
for tag in tags if current.lower() in tag.lower()
524
]
525
return choices[:25] # Discord limit
526
527
@bot.slash_command(description="Search by tag")
528
async def search(
529
inter: disnake.ApplicationCommandInteraction,
530
tag: str = disnake.Param(description="Tag to search", autocomplete=tag_autocomplete)
531
):
532
await inter.response.send_message(f"Searching for tag: {tag}")
533
```
534
535
### Deferred Responses
536
537
```python
538
@bot.slash_command(description="Process large data")
539
async def process(inter: disnake.ApplicationCommandInteraction):
540
# Defer response for long-running operations
541
await inter.response.defer()
542
543
# Simulate processing
544
await asyncio.sleep(5)
545
546
# Send followup message
547
await inter.followup.send("Processing complete!")
548
549
@bot.slash_command(description="Get user avatar")
550
async def avatar(
551
inter: disnake.ApplicationCommandInteraction,
552
user: disnake.Member = disnake.Param(description="User to get avatar for")
553
):
554
# Defer with ephemeral response
555
await inter.response.defer(ephemeral=True)
556
557
# Fetch high-res avatar
558
avatar_url = user.display_avatar.with_size(1024).url
559
560
embed = disnake.Embed(title=f"{user.display_name}'s Avatar")
561
embed.set_image(url=avatar_url)
562
563
# Edit the deferred response
564
await inter.edit_original_response(embed=embed)
565
```
566
567
### Error Handling
568
569
```python
570
@bot.slash_command(description="Divide two numbers")
571
async def divide(
572
inter: disnake.ApplicationCommandInteraction,
573
a: float = disnake.Param(description="First number"),
574
b: float = disnake.Param(description="Second number")
575
):
576
if b == 0:
577
await inter.response.send_message("Cannot divide by zero!", ephemeral=True)
578
return
579
580
result = a / b
581
await inter.response.send_message(f"{a} ÷ {b} = {result}")
582
583
@bot.event
584
async def on_slash_command_error(inter, error):
585
if isinstance(error, commands.MissingPermissions):
586
await inter.response.send_message(
587
"You don't have permission to use this command!",
588
ephemeral=True
589
)
590
else:
591
await inter.response.send_message(
592
"An error occurred while processing the command.",
593
ephemeral=True
594
)
595
```