or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

application-commands.mdchannels.mdclient.mdcommands.mderrors.mdevents.mdguild.mdindex.mdmessages.mdpermissions.mdtasks.mdui.mdusers.mdutilities.mdvoice.mdwebhooks.md

application-commands.mddocs/

0

# Nextcord Application Commands

1

2

Modern Discord application commands including slash commands, user commands, and message commands with comprehensive interaction handling capabilities.

3

4

## Slash Commands

5

6

Modern slash commands that provide a native Discord interface with autocomplete, options, and structured parameters.

7

8

### Command Decorators { .api }

9

10

```python

11

import nextcord

12

from nextcord import SlashOption, OptionType

13

from nextcord.ext import commands

14

from typing import Optional, List

15

16

def slash_command(

17

*,

18

name: Optional[str] = None,

19

description: Optional[str] = None,

20

guild_ids: Optional[List[int]] = None,

21

default_member_permissions: Optional[int] = None,

22

dm_permission: Optional[bool] = None,

23

nsfw: bool = False,

24

force_global: bool = False,

25

**kwargs

26

) -> Callable:

27

"""Decorator to create a slash command.

28

29

Parameters

30

----------

31

name: Optional[str]

32

The name of the command. If not provided, uses the function name.

33

description: Optional[str]

34

The description of the command. Required for slash commands.

35

guild_ids: Optional[List[int]]

36

List of guild IDs where this command should be registered.

37

default_member_permissions: Optional[int]

38

Default permissions required to use this command.

39

dm_permission: Optional[bool]

40

Whether this command can be used in DMs.

41

nsfw: bool

42

Whether this command is NSFW and requires an NSFW channel.

43

force_global: bool

44

Whether to force this command to be global even with guild_ids.

45

"""

46

...

47

48

# Basic slash command example

49

@bot.slash_command(description="Say hello to someone")

50

async def hello(interaction: nextcord.Interaction, user: nextcord.Member):

51

"""A simple slash command that greets a user."""

52

await interaction.response.send_message(f"Hello, {user.mention}!")

53

54

# Slash command with options

55

@bot.slash_command(description="Get information about a user")

56

async def userinfo(

57

interaction: nextcord.Interaction,

58

user: nextcord.Member = SlashOption(description="The user to get info about"),

59

show_avatar: bool = SlashOption(description="Show user avatar", default=True)

60

):

61

"""Get detailed information about a user."""

62

embed = nextcord.Embed(

63

title=f"User Info: {user.display_name}",

64

color=user.color

65

)

66

67

embed.add_field(name="Username", value=str(user), inline=True)

68

embed.add_field(name="ID", value=user.id, inline=True)

69

embed.add_field(name="Joined", value=user.joined_at.strftime("%Y-%m-%d"), inline=True)

70

71

if show_avatar:

72

embed.set_thumbnail(url=user.display_avatar.url)

73

74

await interaction.response.send_message(embed=embed)

75

```

76

77

### Slash Options { .api }

78

79

```python

80

from nextcord import SlashOption, OptionType, ChannelType

81

from typing import Union

82

83

class SlashOption:

84

"""Represents a slash command option parameter.

85

86

Parameters

87

----------

88

name: Optional[str]

89

The name of the option. If not provided, uses parameter name.

90

description: Optional[str]

91

The description of the option.

92

option_type: Optional[OptionType]

93

The type of the option. Auto-detected from type hints if not provided.

94

required: Optional[bool]

95

Whether this option is required. Auto-detected from default values.

96

default: Any

97

The default value for this option.

98

choices: Optional[Union[Dict[str, Union[str, int]], List[Union[str, int]]]]

99

Predefined choices for this option.

100

channel_types: Optional[List[ChannelType]]

101

Valid channel types (for channel options).

102

min_value: Optional[Union[int, float]]

103

Minimum value (for number options).

104

max_value: Optional[Union[int, float]]

105

Maximum value (for number options).

106

min_length: Optional[int]

107

Minimum length (for string options).

108

max_length: Optional[int]

109

Maximum length (for string options).

110

autocomplete: Optional[bool]

111

Whether this option should use autocomplete.

112

"""

113

114

def __init__(

115

self,

116

name: Optional[str] = None,

117

description: Optional[str] = None,

118

option_type: Optional[OptionType] = None,

119

required: Optional[bool] = None,

120

default: Any = MISSING,

121

choices: Optional[Union[Dict[str, Union[str, int]], List[Union[str, int]]]] = None,

122

channel_types: Optional[List[ChannelType]] = None,

123

min_value: Optional[Union[int, float]] = None,

124

max_value: Optional[Union[int, float]] = None,

125

min_length: Optional[int] = None,

126

max_length: Optional[int] = None,

127

autocomplete: Optional[bool] = None,

128

):

129

...

130

131

# Examples of different option types

132

@bot.slash_command(description="Demonstration of various option types")

133

async def options_demo(

134

interaction: nextcord.Interaction,

135

# String option with choices

136

color: str = SlashOption(

137

description="Pick a color",

138

choices=["red", "green", "blue", "yellow"]

139

),

140

# Integer option with min/max

141

amount: int = SlashOption(

142

description="Amount (1-100)",

143

min_value=1,

144

max_value=100

145

),

146

# Optional member parameter

147

target: Optional[nextcord.Member] = SlashOption(

148

description="Target member",

149

default=None

150

),

151

# Channel option with specific types

152

channel: Optional[nextcord.TextChannel] = SlashOption(

153

description="Text channel",

154

channel_types=[ChannelType.text, ChannelType.news],

155

default=None

156

),

157

# Boolean option

158

public: bool = SlashOption(

159

description="Make response public",

160

default=False

161

),

162

# String with length limits

163

message: str = SlashOption(

164

description="Your message",

165

min_length=1,

166

max_length=200

167

)

168

):

169

"""Demonstrate various slash option types."""

170

response = f"Color: {color}, Amount: {amount}, Message: {message}"

171

172

if target:

173

response += f", Target: {target.mention}"

174

if channel:

175

response += f", Channel: {channel.mention}"

176

177

await interaction.response.send_message(response, ephemeral=not public)

178

```

179

180

### Subcommands and Groups { .api }

181

182

```python

183

class SlashCommandGroup:

184

"""A group of related slash commands.

185

186

Attributes

187

----------

188

name: str

189

The name of the command group.

190

description: str

191

The description of the command group.

192

guild_ids: Optional[List[int]]

193

Guild IDs where this group should be registered.

194

"""

195

196

def __init__(

197

self,

198

name: str,

199

description: str,

200

*,

201

guild_ids: Optional[List[int]] = None,

202

default_member_permissions: Optional[int] = None,

203

dm_permission: Optional[bool] = None,

204

nsfw: bool = False,

205

):

206

...

207

208

def subcommand(

209

self,

210

name: Optional[str] = None,

211

description: Optional[str] = None,

212

**kwargs

213

) -> Callable:

214

"""Decorator to add a subcommand to this group."""

215

...

216

217

# Command group example

218

moderation = nextcord.SlashCommandGroup(

219

name="mod",

220

description="Moderation commands",

221

default_member_permissions=nextcord.Permissions(moderate_members=True)

222

)

223

224

@moderation.subcommand(description="Timeout a member")

225

async def timeout(

226

interaction: nextcord.Interaction,

227

member: nextcord.Member = SlashOption(description="Member to timeout"),

228

duration: int = SlashOption(description="Duration in minutes", min_value=1, max_value=40320),

229

reason: Optional[str] = SlashOption(description="Reason for timeout", default=None)

230

):

231

"""Timeout a member for a specified duration."""

232

from datetime import datetime, timedelta

233

234

until = datetime.utcnow() + timedelta(minutes=duration)

235

236

try:

237

await member.timeout(until=until, reason=reason)

238

await interaction.response.send_message(

239

f"⏰ {member.mention} has been timed out for {duration} minutes.",

240

ephemeral=True

241

)

242

except nextcord.Forbidden:

243

await interaction.response.send_message(

244

"❌ I don't have permission to timeout this member.",

245

ephemeral=True

246

)

247

248

@moderation.subcommand(description="Remove timeout from a member")

249

async def untimeout(

250

interaction: nextcord.Interaction,

251

member: nextcord.Member = SlashOption(description="Member to remove timeout from"),

252

reason: Optional[str] = SlashOption(description="Reason", default=None)

253

):

254

"""Remove timeout from a member."""

255

try:

256

await member.timeout(until=None, reason=reason)

257

await interaction.response.send_message(

258

f"✅ Timeout removed from {member.mention}.",

259

ephemeral=True

260

)

261

except nextcord.Forbidden:

262

await interaction.response.send_message(

263

"❌ I don't have permission to remove timeout from this member.",

264

ephemeral=True

265

)

266

267

# Register the command group

268

bot.add_application_command(moderation)

269

```

270

271

### Autocomplete { .api }

272

273

```python

274

from nextcord.ext import application_checks

275

276

@bot.slash_command(description="Search for items")

277

async def search(

278

interaction: nextcord.Interaction,

279

query: str = SlashOption(

280

description="Search query",

281

autocomplete=True

282

)

283

):

284

"""Search command with autocomplete."""

285

await interaction.response.send_message(f"Searching for: {query}")

286

287

@search.on_autocomplete("query")

288

async def search_autocomplete(interaction: nextcord.Interaction, query: str):

289

"""Provide autocomplete suggestions for the search command."""

290

291

# Example search items

292

items = [

293

"Apple", "Banana", "Cherry", "Date", "Elderberry",

294

"Fig", "Grape", "Honeydew", "Ice cream", "Jackfruit",

295

"Kiwi", "Lemon", "Mango", "Nectarine", "Orange"

296

]

297

298

# Filter items based on current input

299

if query:

300

filtered_items = [item for item in items if query.lower() in item.lower()]

301

else:

302

filtered_items = items[:10] # Show first 10 if no query

303

304

# Return up to 25 suggestions (Discord's limit)

305

suggestions = filtered_items[:25]

306

307

await interaction.response.send_autocomplete(

308

{item: item for item in suggestions}

309

)

310

311

# More complex autocomplete with database lookup

312

@bot.slash_command(description="Get user by name")

313

async def find_user(

314

interaction: nextcord.Interaction,

315

username: str = SlashOption(

316

description="Username to search for",

317

autocomplete=True

318

)

319

):

320

"""Find a user by username with autocomplete."""

321

# Search for the user

322

user = nextcord.utils.get(interaction.guild.members, name=username)

323

if user:

324

await interaction.response.send_message(f"Found user: {user.mention}")

325

else:

326

await interaction.response.send_message("User not found.")

327

328

@find_user.on_autocomplete("username")

329

async def username_autocomplete(interaction: nextcord.Interaction, username: str):

330

"""Provide username autocomplete suggestions."""

331

332

# Get guild members matching the query

333

if username:

334

matching_members = [

335

member for member in interaction.guild.members

336

if username.lower() in member.name.lower()

337

][:25]

338

else:

339

matching_members = interaction.guild.members[:25]

340

341

suggestions = {member.name: member.name for member in matching_members}

342

343

await interaction.response.send_autocomplete(suggestions)

344

```

345

346

## Context Menu Commands

347

348

Right-click context menu commands for users and messages.

349

350

### User Commands { .api }

351

352

```python

353

def user_command(

354

*,

355

name: Optional[str] = None,

356

guild_ids: Optional[List[int]] = None,

357

default_member_permissions: Optional[int] = None,

358

dm_permission: Optional[bool] = None,

359

nsfw: bool = False,

360

force_global: bool = False,

361

) -> Callable:

362

"""Decorator to create a user context menu command.

363

364

Parameters

365

----------

366

name: Optional[str]

367

The name of the command. If not provided, uses function name.

368

guild_ids: Optional[List[int]]

369

List of guild IDs where this command should be registered.

370

default_member_permissions: Optional[int]

371

Default permissions required to use this command.

372

dm_permission: Optional[bool]

373

Whether this command can be used in DMs.

374

nsfw: bool

375

Whether this command is NSFW.

376

force_global: bool

377

Whether to force this command to be global.

378

"""

379

...

380

381

# User context menu command example

382

@bot.user_command(name="Get Avatar")

383

async def get_avatar(interaction: nextcord.Interaction, user: nextcord.Member):

384

"""Get a user's avatar via right-click menu."""

385

embed = nextcord.Embed(

386

title=f"{user.display_name}'s Avatar",

387

color=user.color or nextcord.Color.blue()

388

)

389

embed.set_image(url=user.display_avatar.url)

390

embed.set_footer(text=f"User ID: {user.id}")

391

392

await interaction.response.send_message(embed=embed, ephemeral=True)

393

394

@bot.user_command(name="User Info")

395

async def user_info_context(interaction: nextcord.Interaction, user: nextcord.Member):

396

"""Get detailed user information via context menu."""

397

embed = nextcord.Embed(

398

title=f"User Info: {user.display_name}",

399

color=user.color or nextcord.Color.blue()

400

)

401

402

embed.add_field(name="Username", value=str(user), inline=True)

403

embed.add_field(name="ID", value=user.id, inline=True)

404

embed.add_field(name="Bot", value="Yes" if user.bot else "No", inline=True)

405

406

if user.joined_at:

407

embed.add_field(

408

name="Joined Server",

409

value=user.joined_at.strftime("%Y-%m-%d %H:%M UTC"),

410

inline=True

411

)

412

413

embed.add_field(

414

name="Account Created",

415

value=user.created_at.strftime("%Y-%m-%d %H:%M UTC"),

416

inline=True

417

)

418

419

if user.roles[1:]: # Exclude @everyone

420

roles = [role.mention for role in user.roles[1:][:10]] # Show first 10 roles

421

embed.add_field(

422

name="Roles",

423

value=", ".join(roles) + ("..." if len(user.roles) > 11 else ""),

424

inline=False

425

)

426

427

embed.set_thumbnail(url=user.display_avatar.url)

428

429

await interaction.response.send_message(embed=embed, ephemeral=True)

430

```

431

432

### Message Commands { .api }

433

434

```python

435

def message_command(

436

*,

437

name: Optional[str] = None,

438

guild_ids: Optional[List[int]] = None,

439

default_member_permissions: Optional[int] = None,

440

dm_permission: Optional[bool] = None,

441

nsfw: bool = False,

442

force_global: bool = False,

443

) -> Callable:

444

"""Decorator to create a message context menu command.

445

446

Parameters

447

----------

448

name: Optional[str]

449

The name of the command. If not provided, uses function name.

450

guild_ids: Optional[List[int]]

451

List of guild IDs where this command should be registered.

452

default_member_permissions: Optional[int]

453

Default permissions required to use this command.

454

dm_permission: Optional[bool]

455

Whether this command can be used in DMs.

456

nsfw: bool

457

Whether this command is NSFW.

458

force_global: bool

459

Whether to force this command to be global.

460

"""

461

...

462

463

# Message context menu command examples

464

@bot.message_command(name="Quote Message")

465

async def quote_message(interaction: nextcord.Interaction, message: nextcord.Message):

466

"""Quote a message via right-click menu."""

467

embed = nextcord.Embed(

468

description=message.content or "*No text content*",

469

timestamp=message.created_at,

470

color=nextcord.Color.blue()

471

)

472

473

embed.set_author(

474

name=message.author.display_name,

475

icon_url=message.author.display_avatar.url

476

)

477

478

embed.set_footer(text=f"Originally in #{message.channel.name}")

479

480

# Handle attachments

481

if message.attachments:

482

embed.add_field(

483

name="Attachments",

484

value=f"{len(message.attachments)} file(s)",

485

inline=True

486

)

487

488

await interaction.response.send_message(embed=embed)

489

490

@bot.message_command(name="Message Info")

491

async def message_info(interaction: nextcord.Interaction, message: nextcord.Message):

492

"""Get detailed message information."""

493

embed = nextcord.Embed(

494

title="Message Information",

495

color=nextcord.Color.blue()

496

)

497

498

embed.add_field(name="Author", value=message.author.mention, inline=True)

499

embed.add_field(name="Message ID", value=message.id, inline=True)

500

embed.add_field(name="Channel", value=message.channel.mention, inline=True)

501

502

embed.add_field(

503

name="Created At",

504

value=message.created_at.strftime("%Y-%m-%d %H:%M:%S UTC"),

505

inline=True

506

)

507

508

if message.edited_at:

509

embed.add_field(

510

name="Last Edited",

511

value=message.edited_at.strftime("%Y-%m-%d %H:%M:%S UTC"),

512

inline=True

513

)

514

515

embed.add_field(

516

name="Jump to Message",

517

value=f"[Click here]({message.jump_url})",

518

inline=True

519

)

520

521

# Content preview

522

if message.content:

523

content_preview = message.content[:100] + ("..." if len(message.content) > 100 else "")

524

embed.add_field(name="Content Preview", value=content_preview, inline=False)

525

526

# Attachments

527

if message.attachments:

528

attachment_info = []

529

for attachment in message.attachments[:5]: # Show first 5 attachments

530

size_kb = attachment.size // 1024

531

attachment_info.append(f"• {attachment.filename} ({size_kb} KB)")

532

533

embed.add_field(

534

name=f"Attachments ({len(message.attachments)})",

535

value="\n".join(attachment_info),

536

inline=False

537

)

538

539

# Reactions

540

if message.reactions:

541

reaction_info = []

542

for reaction in message.reactions[:10]: # Show first 10 reactions

543

reaction_info.append(f"{reaction.emoji} ({reaction.count})")

544

545

embed.add_field(

546

name="Reactions",

547

value=" ".join(reaction_info),

548

inline=False

549

)

550

551

await interaction.response.send_message(embed=embed, ephemeral=True)

552

553

@bot.message_command(name="Copy Message ID")

554

async def copy_message_id(interaction: nextcord.Interaction, message: nextcord.Message):

555

"""Copy a message ID to clipboard-friendly format."""

556

await interaction.response.send_message(

557

f"Message ID: `{message.id}`\n"

558

f"Jump URL: {message.jump_url}",

559

ephemeral=True

560

)

561

```

562

563

## Interactions

564

565

Interaction objects and response handling for application commands.

566

567

### Interaction Class { .api }

568

569

```python

570

class Interaction:

571

"""Represents a Discord interaction.

572

573

Attributes

574

----------

575

id: int

576

The interaction ID.

577

application_id: int

578

The application ID that received this interaction.

579

type: InteractionType

580

The type of interaction.

581

data: Optional[InteractionData]

582

The interaction data payload.

583

guild_id: Optional[int]

584

The guild ID where this interaction was sent from.

585

channel_id: Optional[int]

586

The channel ID where this interaction was sent from.

587

user: Union[User, Member]

588

The user who invoked this interaction.

589

token: str

590

The interaction token.

591

version: int

592

The version of interaction.

593

message: Optional[Message]

594

The message this interaction is attached to.

595

locale: Optional[str]

596

The selected language of the user who invoked this interaction.

597

guild_locale: Optional[str]

598

The guild's preferred locale.

599

"""

600

601

@property

602

def guild(self) -> Optional[Guild]:

603

"""Optional[Guild]: The guild this interaction was sent from."""

604

...

605

606

@property

607

def channel(self) -> Optional[Union[GuildChannel, PartialMessageable]]:

608

"""The channel this interaction was sent from."""

609

...

610

611

@property

612

def permissions(self) -> Permissions:

613

"""Permissions: The resolved permissions of the user in the channel."""

614

...

615

616

@property

617

def response(self) -> InteractionResponse:

618

"""InteractionResponse: Returns an object responsible for handling responses."""

619

...

620

621

@property

622

def followup(self) -> Webhook:

623

"""Webhook: Returns the follow-up webhook for this interaction."""

624

...

625

626

def is_expired(self) -> bool:

627

"""bool: Whether the interaction is expired and can no longer be responded to."""

628

...

629

630

async def edit_original_message(self, **kwargs) -> InteractionMessage:

631

"""Edit the original interaction response message."""

632

...

633

634

async def delete_original_message(self) -> None:

635

"""Delete the original interaction response message."""

636

...

637

638

async def original_message(self) -> InteractionMessage:

639

"""Fetch the original interaction response message."""

640

...

641

```

642

643

### Interaction Response { .api }

644

645

```python

646

class InteractionResponse:

647

"""Handles responding to Discord interactions.

648

649

This class is accessed via Interaction.response and provides

650

methods for sending initial responses to interactions.

651

"""

652

653

async def send_message(

654

self,

655

content: Optional[str] = None,

656

*,

657

embed: Optional[Embed] = None,

658

embeds: Optional[List[Embed]] = None,

659

file: Optional[File] = None,

660

files: Optional[List[File]] = None,

661

view: Optional[View] = None,

662

tts: bool = False,

663

ephemeral: bool = False,

664

allowed_mentions: Optional[AllowedMentions] = None,

665

suppress_embeds: bool = False,

666

delete_after: Optional[float] = None,

667

) -> None:

668

"""Send a message response to the interaction.

669

670

Parameters

671

----------

672

content: Optional[str]

673

The message content to send.

674

embed: Optional[Embed]

675

An embed to send with the message.

676

embeds: Optional[List[Embed]]

677

A list of embeds to send. Maximum of 10.

678

file: Optional[File]

679

A file to send with the message.

680

files: Optional[List[File]]

681

A list of files to send. Maximum of 10.

682

view: Optional[View]

683

A UI view to attach to the message.

684

tts: bool

685

Whether the message should be text-to-speech.

686

ephemeral: bool

687

Whether the message should be ephemeral (only visible to the user).

688

allowed_mentions: Optional[AllowedMentions]

689

Controls which mentions are processed.

690

suppress_embeds: bool

691

Whether to suppress embeds in the message.

692

delete_after: Optional[float]

693

Delete the message after this many seconds.

694

"""

695

...

696

697

async def defer(self, *, ephemeral: bool = False, thinking: bool = False) -> None:

698

"""Defer the interaction response.

699

700

This allows you to respond later using followup messages.

701

702

Parameters

703

----------

704

ephemeral: bool

705

Whether the deferred response should be ephemeral.

706

thinking: bool

707

Whether to show "Bot is thinking..." message.

708

"""

709

...

710

711

async def edit_message(

712

self,

713

content: Optional[str] = MISSING,

714

*,

715

embed: Optional[Embed] = MISSING,

716

embeds: Optional[List[Embed]] = MISSING,

717

file: Optional[File] = MISSING,

718

files: Optional[List[File]] = MISSING,

719

attachments: Optional[List[Attachment]] = MISSING,

720

view: Optional[View] = MISSING,

721

allowed_mentions: Optional[AllowedMentions] = MISSING,

722

delete_after: Optional[float] = None,

723

) -> None:

724

"""Edit the message that triggered this interaction.

725

726

Note: This is only available for component interactions.

727

"""

728

...

729

730

async def send_autocomplete(

731

self,

732

choices: Dict[str, Union[str, int, float]]

733

) -> None:

734

"""Send autocomplete suggestions.

735

736

Parameters

737

----------

738

choices: Dict[str, Union[str, int, float]]

739

A dictionary of choices where keys are display names

740

and values are the actual values to be used.

741

"""

742

...

743

744

async def send_modal(self, modal: Modal) -> None:

745

"""Send a modal dialog in response to the interaction.

746

747

Parameters

748

----------

749

modal: Modal

750

The modal dialog to send.

751

"""

752

...

753

754

@property

755

def is_done(self) -> bool:

756

"""bool: Whether an initial response has been sent."""

757

...

758

```

759

760

### Follow-up Messages { .api }

761

762

```python

763

# Follow-up messages are sent after the initial response

764

@bot.slash_command(description="Example of follow-up messages")

765

async def followup_example(interaction: nextcord.Interaction):

766

"""Demonstrate follow-up message usage."""

767

768

# Send initial response

769

await interaction.response.send_message("Processing your request...")

770

771

# Simulate some work

772

import asyncio

773

await asyncio.sleep(2)

774

775

# Send follow-up message

776

await interaction.followup.send("Step 1 complete!")

777

778

await asyncio.sleep(1)

779

780

# Another follow-up

781

embed = nextcord.Embed(title="Final Result", description="Task completed successfully!")

782

await interaction.followup.send(embed=embed)

783

784

# You can also edit the original message

785

await interaction.edit_original_message(content="✅ All steps completed!")

786

787

@bot.slash_command(description="Example with deferred response")

788

async def long_task(interaction: nextcord.Interaction):

789

"""Example of using deferred response for long tasks."""

790

791

# Defer the response to give more time

792

await interaction.response.defer(ephemeral=True)

793

794

# Simulate long-running task

795

import asyncio

796

await asyncio.sleep(5)

797

798

# Send the actual response via followup

799

embed = nextcord.Embed(

800

title="Long Task Complete",

801

description="The task that took 5 seconds has finished!",

802

color=nextcord.Color.green()

803

)

804

805

await interaction.followup.send(embed=embed)

806

```

807

808

## Application Command Checks

809

810

Permission and validation checks for application commands.

811

812

### Built-in Checks { .api }

813

814

```python

815

from nextcord.ext import application_checks

816

817

# Permission-based checks

818

@application_checks.has_permissions(manage_messages=True)

819

@bot.slash_command(description="Delete messages")

820

async def purge(

821

interaction: nextcord.Interaction,

822

amount: int = SlashOption(description="Number of messages to delete", min_value=1, max_value=100)

823

):

824

"""Delete messages (requires manage_messages permission)."""

825

deleted = await interaction.channel.purge(limit=amount)

826

await interaction.response.send_message(

827

f"Deleted {len(deleted)} messages.",

828

ephemeral=True

829

)

830

831

# Role-based checks

832

@application_checks.has_any_role("Admin", "Moderator")

833

@bot.slash_command(description="Admin only command")

834

async def admin_command(interaction: nextcord.Interaction):

835

"""Command only available to users with Admin or Moderator role."""

836

await interaction.response.send_message("Admin command executed!", ephemeral=True)

837

838

# Guild-only check

839

@application_checks.guild_only()

840

@bot.slash_command(description="Server only command")

841

async def server_only(interaction: nextcord.Interaction):

842

"""This command can only be used in servers, not DMs."""

843

await interaction.response.send_message(f"Server: {interaction.guild.name}")

844

845

# Owner check

846

@application_checks.is_owner()

847

@bot.slash_command(description="Bot owner only")

848

async def owner_only(interaction: nextcord.Interaction):

849

"""Command only available to the bot owner."""

850

await interaction.response.send_message("Owner command executed!", ephemeral=True)

851

852

# Custom check function

853

def is_in_voice_channel():

854

"""Check if user is in a voice channel."""

855

async def predicate(interaction: nextcord.Interaction) -> bool:

856

if not interaction.user.voice:

857

await interaction.response.send_message(

858

"You must be in a voice channel to use this command!",

859

ephemeral=True

860

)

861

return False

862

return True

863

return application_checks.check(predicate)

864

865

@is_in_voice_channel()

866

@bot.slash_command(description="Voice channel required")

867

async def voice_command(interaction: nextcord.Interaction):

868

"""Command that requires being in a voice channel."""

869

channel = interaction.user.voice.channel

870

await interaction.response.send_message(f"You're in {channel.name}!")

871

```

872

873

### Custom Check Decorators { .api }

874

875

```python

876

from functools import wraps

877

from nextcord.ext.application_checks import ApplicationCheckFailure

878

879

class NotInMaintenanceMode(ApplicationCheckFailure):

880

"""Custom exception for maintenance mode check."""

881

pass

882

883

def not_in_maintenance():

884

"""Custom check to prevent command usage during maintenance."""

885

def decorator(func):

886

@wraps(func)

887

async def wrapper(interaction: nextcord.Interaction, *args, **kwargs):

888

# Check some maintenance flag (could be from database, config, etc.)

889

maintenance_mode = False # Replace with actual check

890

891

if maintenance_mode:

892

await interaction.response.send_message(

893

"🔧 Bot is currently in maintenance mode. Please try again later.",

894

ephemeral=True

895

)

896

raise NotInMaintenanceMode("Bot is in maintenance mode")

897

898

return await func(interaction, *args, **kwargs)

899

return wrapper

900

return decorator

901

902

def cooldown_check(rate: int, per: float):

903

"""Custom cooldown check for application commands."""

904

def decorator(func):

905

cooldowns = {}

906

907

@wraps(func)

908

async def wrapper(interaction: nextcord.Interaction, *args, **kwargs):

909

import time

910

911

user_id = interaction.user.id

912

current_time = time.time()

913

914

if user_id in cooldowns:

915

time_left = cooldowns[user_id] + per - current_time

916

if time_left > 0:

917

await interaction.response.send_message(

918

f"Command on cooldown. Try again in {time_left:.1f} seconds.",

919

ephemeral=True

920

)

921

return

922

923

cooldowns[user_id] = current_time

924

return await func(interaction, *args, **kwargs)

925

926

return wrapper

927

return decorator

928

929

# Usage of custom checks

930

@not_in_maintenance()

931

@cooldown_check(rate=1, per=30.0) # 1 use per 30 seconds

932

@bot.slash_command(description="Command with custom checks")

933

async def custom_checked_command(interaction: nextcord.Interaction):

934

"""Command with maintenance and cooldown checks."""

935

await interaction.response.send_message("Command executed successfully!")

936

```

937

938

## Error Handling

939

940

Comprehensive error handling for application commands.

941

942

### Error Handler { .api }

943

944

```python

945

@bot.event

946

async def on_application_command_error(interaction: nextcord.Interaction, error: Exception):

947

"""Global error handler for application commands."""

948

949

if isinstance(error, application_checks.MissingPermissions):

950

missing = ", ".join(error.missing_permissions)

951

await interaction.response.send_message(

952

f"❌ You're missing the following permissions: {missing}",

953

ephemeral=True

954

)

955

956

elif isinstance(error, application_checks.MissingAnyRole):

957

roles = ", ".join(error.missing_roles)

958

await interaction.response.send_message(

959

f"❌ You need one of these roles: {roles}",

960

ephemeral=True

961

)

962

963

elif isinstance(error, application_checks.NotOwner):

964

await interaction.response.send_message(

965

"❌ This command is only available to the bot owner.",

966

ephemeral=True

967

)

968

969

elif isinstance(error, application_checks.NoPrivateMessage):

970

await interaction.response.send_message(

971

"❌ This command cannot be used in direct messages.",

972

ephemeral=True

973

)

974

975

elif isinstance(error, nextcord.errors.ApplicationInvokeError):

976

# Handle errors within command execution

977

original_error = error.original

978

979

if isinstance(original_error, nextcord.Forbidden):

980

await interaction.response.send_message(

981

"❌ I don't have permission to perform this action.",

982

ephemeral=True

983

)

984

elif isinstance(original_error, nextcord.NotFound):

985

await interaction.response.send_message(

986

"❌ The requested resource was not found.",

987

ephemeral=True

988

)

989

else:

990

# Log unexpected errors

991

import traceback

992

print(f"Unexpected error in command: {error}")

993

traceback.print_exception(type(original_error), original_error, original_error.__traceback__)

994

995

if not interaction.response.is_done():

996

await interaction.response.send_message(

997

"❌ An unexpected error occurred. Please try again later.",

998

ephemeral=True

999

)

1000

1001

else:

1002

# Handle other unexpected errors

1003

print(f"Unhandled application command error: {error}")

1004

1005

if not interaction.response.is_done():

1006

await interaction.response.send_message(

1007

"❌ An error occurred while processing your command.",

1008

ephemeral=True

1009

)

1010

1011

# Command-specific error handling

1012

@bot.slash_command(description="Command with specific error handling")

1013

async def error_prone_command(

1014

interaction: nextcord.Interaction,

1015

user: nextcord.Member = SlashOption(description="Target user")

1016

):

1017

"""Command that demonstrates error handling."""

1018

try:

1019

# Some operation that might fail

1020

await user.send("Hello from the bot!")

1021

await interaction.response.send_message(f"Message sent to {user.mention}!")

1022

1023

except nextcord.Forbidden:

1024

await interaction.response.send_message(

1025

f"❌ I can't send a DM to {user.mention}. They may have DMs disabled.",

1026

ephemeral=True

1027

)

1028

except nextcord.HTTPException as e:

1029

await interaction.response.send_message(

1030

f"❌ Failed to send message: {e}",

1031

ephemeral=True

1032

)

1033

except Exception as e:

1034

await interaction.response.send_message(

1035

"❌ An unexpected error occurred.",

1036

ephemeral=True

1037

)

1038

# Log the error for debugging

1039

import traceback

1040

traceback.print_exc()

1041

```

1042

1043

This comprehensive documentation covers all aspects of nextcord's application command system, providing developers with the knowledge needed to implement modern Discord interactions effectively.