CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-nextcord

A Python wrapper for the Discord API forked from discord.py

Pending
Overview
Eval results
Files

application-commands.mddocs/

Nextcord Application Commands

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

Slash Commands

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

Command Decorators { .api }

import nextcord
from nextcord import SlashOption, OptionType
from nextcord.ext import commands
from typing import Optional, List

def slash_command(
    *,
    name: Optional[str] = None,
    description: Optional[str] = None,
    guild_ids: Optional[List[int]] = None,
    default_member_permissions: Optional[int] = None,
    dm_permission: Optional[bool] = None,
    nsfw: bool = False,
    force_global: bool = False,
    **kwargs
) -> Callable:
    """Decorator to create a slash command.
    
    Parameters
    ----------
    name: Optional[str]
        The name of the command. If not provided, uses the function name.
    description: Optional[str]
        The description of the command. Required for slash commands.
    guild_ids: Optional[List[int]]
        List of guild IDs where this command should be registered.
    default_member_permissions: Optional[int]
        Default permissions required to use this command.
    dm_permission: Optional[bool]
        Whether this command can be used in DMs.
    nsfw: bool
        Whether this command is NSFW and requires an NSFW channel.
    force_global: bool
        Whether to force this command to be global even with guild_ids.
    """
    ...

# Basic slash command example
@bot.slash_command(description="Say hello to someone")
async def hello(interaction: nextcord.Interaction, user: nextcord.Member):
    """A simple slash command that greets a user."""
    await interaction.response.send_message(f"Hello, {user.mention}!")

# Slash command with options
@bot.slash_command(description="Get information about a user")
async def userinfo(
    interaction: nextcord.Interaction,
    user: nextcord.Member = SlashOption(description="The user to get info about"),
    show_avatar: bool = SlashOption(description="Show user avatar", default=True)
):
    """Get detailed information about a user."""
    embed = nextcord.Embed(
        title=f"User Info: {user.display_name}",
        color=user.color
    )
    
    embed.add_field(name="Username", value=str(user), inline=True)
    embed.add_field(name="ID", value=user.id, inline=True)
    embed.add_field(name="Joined", value=user.joined_at.strftime("%Y-%m-%d"), inline=True)
    
    if show_avatar:
        embed.set_thumbnail(url=user.display_avatar.url)
    
    await interaction.response.send_message(embed=embed)

Slash Options { .api }

from nextcord import SlashOption, OptionType, ChannelType
from typing import Union

class SlashOption:
    """Represents a slash command option parameter.
    
    Parameters
    ----------
    name: Optional[str]
        The name of the option. If not provided, uses parameter name.
    description: Optional[str]
        The description of the option.
    option_type: Optional[OptionType]
        The type of the option. Auto-detected from type hints if not provided.
    required: Optional[bool]
        Whether this option is required. Auto-detected from default values.
    default: Any
        The default value for this option.
    choices: Optional[Union[Dict[str, Union[str, int]], List[Union[str, int]]]]
        Predefined choices for this option.
    channel_types: Optional[List[ChannelType]]
        Valid channel types (for channel options).
    min_value: Optional[Union[int, float]]
        Minimum value (for number options).
    max_value: Optional[Union[int, float]]
        Maximum value (for number options).
    min_length: Optional[int]
        Minimum length (for string options).
    max_length: Optional[int]
        Maximum length (for string options).
    autocomplete: Optional[bool]
        Whether this option should use autocomplete.
    """
    
    def __init__(
        self,
        name: Optional[str] = None,
        description: Optional[str] = None,
        option_type: Optional[OptionType] = None,
        required: Optional[bool] = None,
        default: Any = MISSING,
        choices: Optional[Union[Dict[str, Union[str, int]], List[Union[str, int]]]] = None,
        channel_types: Optional[List[ChannelType]] = None,
        min_value: Optional[Union[int, float]] = None,
        max_value: Optional[Union[int, float]] = None,
        min_length: Optional[int] = None,
        max_length: Optional[int] = None,
        autocomplete: Optional[bool] = None,
    ):
        ...

# Examples of different option types
@bot.slash_command(description="Demonstration of various option types")
async def options_demo(
    interaction: nextcord.Interaction,
    # String option with choices
    color: str = SlashOption(
        description="Pick a color",
        choices=["red", "green", "blue", "yellow"]
    ),
    # Integer option with min/max
    amount: int = SlashOption(
        description="Amount (1-100)",
        min_value=1,
        max_value=100
    ),
    # Optional member parameter
    target: Optional[nextcord.Member] = SlashOption(
        description="Target member",
        default=None
    ),
    # Channel option with specific types
    channel: Optional[nextcord.TextChannel] = SlashOption(
        description="Text channel",
        channel_types=[ChannelType.text, ChannelType.news],
        default=None
    ),
    # Boolean option
    public: bool = SlashOption(
        description="Make response public",
        default=False
    ),
    # String with length limits
    message: str = SlashOption(
        description="Your message",
        min_length=1,
        max_length=200
    )
):
    """Demonstrate various slash option types."""
    response = f"Color: {color}, Amount: {amount}, Message: {message}"
    
    if target:
        response += f", Target: {target.mention}"
    if channel:
        response += f", Channel: {channel.mention}"
        
    await interaction.response.send_message(response, ephemeral=not public)

Subcommands and Groups { .api }

class SlashCommandGroup:
    """A group of related slash commands.
    
    Attributes
    ----------
    name: str
        The name of the command group.
    description: str
        The description of the command group.
    guild_ids: Optional[List[int]]
        Guild IDs where this group should be registered.
    """
    
    def __init__(
        self,
        name: str,
        description: str,
        *,
        guild_ids: Optional[List[int]] = None,
        default_member_permissions: Optional[int] = None,
        dm_permission: Optional[bool] = None,
        nsfw: bool = False,
    ):
        ...
    
    def subcommand(
        self,
        name: Optional[str] = None,
        description: Optional[str] = None,
        **kwargs
    ) -> Callable:
        """Decorator to add a subcommand to this group."""
        ...

# Command group example
moderation = nextcord.SlashCommandGroup(
    name="mod", 
    description="Moderation commands",
    default_member_permissions=nextcord.Permissions(moderate_members=True)
)

@moderation.subcommand(description="Timeout a member")
async def timeout(
    interaction: nextcord.Interaction,
    member: nextcord.Member = SlashOption(description="Member to timeout"),
    duration: int = SlashOption(description="Duration in minutes", min_value=1, max_value=40320),
    reason: Optional[str] = SlashOption(description="Reason for timeout", default=None)
):
    """Timeout a member for a specified duration."""
    from datetime import datetime, timedelta
    
    until = datetime.utcnow() + timedelta(minutes=duration)
    
    try:
        await member.timeout(until=until, reason=reason)
        await interaction.response.send_message(
            f"⏰ {member.mention} has been timed out for {duration} minutes.",
            ephemeral=True
        )
    except nextcord.Forbidden:
        await interaction.response.send_message(
            "❌ I don't have permission to timeout this member.",
            ephemeral=True
        )

@moderation.subcommand(description="Remove timeout from a member")
async def untimeout(
    interaction: nextcord.Interaction,
    member: nextcord.Member = SlashOption(description="Member to remove timeout from"),
    reason: Optional[str] = SlashOption(description="Reason", default=None)
):
    """Remove timeout from a member."""
    try:
        await member.timeout(until=None, reason=reason)
        await interaction.response.send_message(
            f"✅ Timeout removed from {member.mention}.",
            ephemeral=True
        )
    except nextcord.Forbidden:
        await interaction.response.send_message(
            "❌ I don't have permission to remove timeout from this member.",
            ephemeral=True
        )

# Register the command group
bot.add_application_command(moderation)

Autocomplete { .api }

from nextcord.ext import application_checks

@bot.slash_command(description="Search for items")
async def search(
    interaction: nextcord.Interaction,
    query: str = SlashOption(
        description="Search query",
        autocomplete=True
    )
):
    """Search command with autocomplete."""
    await interaction.response.send_message(f"Searching for: {query}")

@search.on_autocomplete("query")
async def search_autocomplete(interaction: nextcord.Interaction, query: str):
    """Provide autocomplete suggestions for the search command."""
    
    # Example search items
    items = [
        "Apple", "Banana", "Cherry", "Date", "Elderberry",
        "Fig", "Grape", "Honeydew", "Ice cream", "Jackfruit",
        "Kiwi", "Lemon", "Mango", "Nectarine", "Orange"
    ]
    
    # Filter items based on current input
    if query:
        filtered_items = [item for item in items if query.lower() in item.lower()]
    else:
        filtered_items = items[:10]  # Show first 10 if no query
    
    # Return up to 25 suggestions (Discord's limit)
    suggestions = filtered_items[:25]
    
    await interaction.response.send_autocomplete(
        {item: item for item in suggestions}
    )

# More complex autocomplete with database lookup
@bot.slash_command(description="Get user by name")
async def find_user(
    interaction: nextcord.Interaction,
    username: str = SlashOption(
        description="Username to search for",
        autocomplete=True
    )
):
    """Find a user by username with autocomplete."""
    # Search for the user
    user = nextcord.utils.get(interaction.guild.members, name=username)
    if user:
        await interaction.response.send_message(f"Found user: {user.mention}")
    else:
        await interaction.response.send_message("User not found.")

@find_user.on_autocomplete("username")
async def username_autocomplete(interaction: nextcord.Interaction, username: str):
    """Provide username autocomplete suggestions."""
    
    # Get guild members matching the query
    if username:
        matching_members = [
            member for member in interaction.guild.members
            if username.lower() in member.name.lower()
        ][:25]
    else:
        matching_members = interaction.guild.members[:25]
    
    suggestions = {member.name: member.name for member in matching_members}
    
    await interaction.response.send_autocomplete(suggestions)

Context Menu Commands

Right-click context menu commands for users and messages.

User Commands { .api }

def user_command(
    *,
    name: Optional[str] = None,
    guild_ids: Optional[List[int]] = None,
    default_member_permissions: Optional[int] = None,
    dm_permission: Optional[bool] = None,
    nsfw: bool = False,
    force_global: bool = False,
) -> Callable:
    """Decorator to create a user context menu command.
    
    Parameters
    ----------
    name: Optional[str]
        The name of the command. If not provided, uses function name.
    guild_ids: Optional[List[int]]
        List of guild IDs where this command should be registered.
    default_member_permissions: Optional[int]
        Default permissions required to use this command.
    dm_permission: Optional[bool]
        Whether this command can be used in DMs.
    nsfw: bool
        Whether this command is NSFW.
    force_global: bool
        Whether to force this command to be global.
    """
    ...

# User context menu command example
@bot.user_command(name="Get Avatar")
async def get_avatar(interaction: nextcord.Interaction, user: nextcord.Member):
    """Get a user's avatar via right-click menu."""
    embed = nextcord.Embed(
        title=f"{user.display_name}'s Avatar",
        color=user.color or nextcord.Color.blue()
    )
    embed.set_image(url=user.display_avatar.url)
    embed.set_footer(text=f"User ID: {user.id}")
    
    await interaction.response.send_message(embed=embed, ephemeral=True)

@bot.user_command(name="User Info")
async def user_info_context(interaction: nextcord.Interaction, user: nextcord.Member):
    """Get detailed user information via context menu."""
    embed = nextcord.Embed(
        title=f"User Info: {user.display_name}",
        color=user.color or nextcord.Color.blue()
    )
    
    embed.add_field(name="Username", value=str(user), inline=True)
    embed.add_field(name="ID", value=user.id, inline=True)
    embed.add_field(name="Bot", value="Yes" if user.bot else "No", inline=True)
    
    if user.joined_at:
        embed.add_field(
            name="Joined Server", 
            value=user.joined_at.strftime("%Y-%m-%d %H:%M UTC"), 
            inline=True
        )
    
    embed.add_field(
        name="Account Created", 
        value=user.created_at.strftime("%Y-%m-%d %H:%M UTC"), 
        inline=True
    )
    
    if user.roles[1:]:  # Exclude @everyone
        roles = [role.mention for role in user.roles[1:][:10]]  # Show first 10 roles
        embed.add_field(
            name="Roles", 
            value=", ".join(roles) + ("..." if len(user.roles) > 11 else ""), 
            inline=False
        )
    
    embed.set_thumbnail(url=user.display_avatar.url)
    
    await interaction.response.send_message(embed=embed, ephemeral=True)

Message Commands { .api }

def message_command(
    *,
    name: Optional[str] = None,
    guild_ids: Optional[List[int]] = None,
    default_member_permissions: Optional[int] = None,
    dm_permission: Optional[bool] = None,
    nsfw: bool = False,
    force_global: bool = False,
) -> Callable:
    """Decorator to create a message context menu command.
    
    Parameters
    ----------
    name: Optional[str]
        The name of the command. If not provided, uses function name.
    guild_ids: Optional[List[int]]
        List of guild IDs where this command should be registered.
    default_member_permissions: Optional[int]
        Default permissions required to use this command.
    dm_permission: Optional[bool]
        Whether this command can be used in DMs.
    nsfw: bool
        Whether this command is NSFW.
    force_global: bool
        Whether to force this command to be global.
    """
    ...

# Message context menu command examples
@bot.message_command(name="Quote Message")
async def quote_message(interaction: nextcord.Interaction, message: nextcord.Message):
    """Quote a message via right-click menu."""
    embed = nextcord.Embed(
        description=message.content or "*No text content*",
        timestamp=message.created_at,
        color=nextcord.Color.blue()
    )
    
    embed.set_author(
        name=message.author.display_name,
        icon_url=message.author.display_avatar.url
    )
    
    embed.set_footer(text=f"Originally in #{message.channel.name}")
    
    # Handle attachments
    if message.attachments:
        embed.add_field(
            name="Attachments",
            value=f"{len(message.attachments)} file(s)",
            inline=True
        )
    
    await interaction.response.send_message(embed=embed)

@bot.message_command(name="Message Info")
async def message_info(interaction: nextcord.Interaction, message: nextcord.Message):
    """Get detailed message information."""
    embed = nextcord.Embed(
        title="Message Information",
        color=nextcord.Color.blue()
    )
    
    embed.add_field(name="Author", value=message.author.mention, inline=True)
    embed.add_field(name="Message ID", value=message.id, inline=True)
    embed.add_field(name="Channel", value=message.channel.mention, inline=True)
    
    embed.add_field(
        name="Created At", 
        value=message.created_at.strftime("%Y-%m-%d %H:%M:%S UTC"), 
        inline=True
    )
    
    if message.edited_at:
        embed.add_field(
            name="Last Edited", 
            value=message.edited_at.strftime("%Y-%m-%d %H:%M:%S UTC"), 
            inline=True
        )
    
    embed.add_field(
        name="Jump to Message", 
        value=f"[Click here]({message.jump_url})", 
        inline=True
    )
    
    # Content preview
    if message.content:
        content_preview = message.content[:100] + ("..." if len(message.content) > 100 else "")
        embed.add_field(name="Content Preview", value=content_preview, inline=False)
    
    # Attachments
    if message.attachments:
        attachment_info = []
        for attachment in message.attachments[:5]:  # Show first 5 attachments
            size_kb = attachment.size // 1024
            attachment_info.append(f"• {attachment.filename} ({size_kb} KB)")
        
        embed.add_field(
            name=f"Attachments ({len(message.attachments)})",
            value="\n".join(attachment_info),
            inline=False
        )
    
    # Reactions
    if message.reactions:
        reaction_info = []
        for reaction in message.reactions[:10]:  # Show first 10 reactions
            reaction_info.append(f"{reaction.emoji} ({reaction.count})")
        
        embed.add_field(
            name="Reactions",
            value=" ".join(reaction_info),
            inline=False
        )
    
    await interaction.response.send_message(embed=embed, ephemeral=True)

@bot.message_command(name="Copy Message ID")
async def copy_message_id(interaction: nextcord.Interaction, message: nextcord.Message):
    """Copy a message ID to clipboard-friendly format."""
    await interaction.response.send_message(
        f"Message ID: `{message.id}`\n"
        f"Jump URL: {message.jump_url}",
        ephemeral=True
    )

Interactions

Interaction objects and response handling for application commands.

Interaction Class { .api }

class Interaction:
    """Represents a Discord interaction.
    
    Attributes
    ----------
    id: int
        The interaction ID.
    application_id: int
        The application ID that received this interaction.
    type: InteractionType
        The type of interaction.
    data: Optional[InteractionData]
        The interaction data payload.
    guild_id: Optional[int]
        The guild ID where this interaction was sent from.
    channel_id: Optional[int]
        The channel ID where this interaction was sent from.
    user: Union[User, Member]
        The user who invoked this interaction.
    token: str
        The interaction token.
    version: int
        The version of interaction.
    message: Optional[Message]
        The message this interaction is attached to.
    locale: Optional[str]
        The selected language of the user who invoked this interaction.
    guild_locale: Optional[str]
        The guild's preferred locale.
    """
    
    @property
    def guild(self) -> Optional[Guild]:
        """Optional[Guild]: The guild this interaction was sent from."""
        ...
    
    @property
    def channel(self) -> Optional[Union[GuildChannel, PartialMessageable]]:
        """The channel this interaction was sent from."""
        ...
    
    @property
    def permissions(self) -> Permissions:
        """Permissions: The resolved permissions of the user in the channel."""
        ...
    
    @property
    def response(self) -> InteractionResponse:
        """InteractionResponse: Returns an object responsible for handling responses."""
        ...
    
    @property
    def followup(self) -> Webhook:
        """Webhook: Returns the follow-up webhook for this interaction."""
        ...
    
    def is_expired(self) -> bool:
        """bool: Whether the interaction is expired and can no longer be responded to."""
        ...
    
    async def edit_original_message(self, **kwargs) -> InteractionMessage:
        """Edit the original interaction response message."""
        ...
    
    async def delete_original_message(self) -> None:
        """Delete the original interaction response message."""
        ...
    
    async def original_message(self) -> InteractionMessage:
        """Fetch the original interaction response message."""
        ...

Interaction Response { .api }

class InteractionResponse:
    """Handles responding to Discord interactions.
    
    This class is accessed via Interaction.response and provides
    methods for sending initial responses to interactions.
    """
    
    async def send_message(
        self,
        content: Optional[str] = None,
        *,
        embed: Optional[Embed] = None,
        embeds: Optional[List[Embed]] = None,
        file: Optional[File] = None,
        files: Optional[List[File]] = None,
        view: Optional[View] = None,
        tts: bool = False,
        ephemeral: bool = False,
        allowed_mentions: Optional[AllowedMentions] = None,
        suppress_embeds: bool = False,
        delete_after: Optional[float] = None,
    ) -> None:
        """Send a message response to the interaction.
        
        Parameters
        ----------
        content: Optional[str]
            The message content to send.
        embed: Optional[Embed]
            An embed to send with the message.
        embeds: Optional[List[Embed]]
            A list of embeds to send. Maximum of 10.
        file: Optional[File]
            A file to send with the message.
        files: Optional[List[File]]
            A list of files to send. Maximum of 10.
        view: Optional[View]
            A UI view to attach to the message.
        tts: bool
            Whether the message should be text-to-speech.
        ephemeral: bool
            Whether the message should be ephemeral (only visible to the user).
        allowed_mentions: Optional[AllowedMentions]
            Controls which mentions are processed.
        suppress_embeds: bool
            Whether to suppress embeds in the message.
        delete_after: Optional[float]
            Delete the message after this many seconds.
        """
        ...
    
    async def defer(self, *, ephemeral: bool = False, thinking: bool = False) -> None:
        """Defer the interaction response.
        
        This allows you to respond later using followup messages.
        
        Parameters
        ----------
        ephemeral: bool
            Whether the deferred response should be ephemeral.
        thinking: bool
            Whether to show "Bot is thinking..." message.
        """
        ...
    
    async def edit_message(
        self,
        content: Optional[str] = MISSING,
        *,
        embed: Optional[Embed] = MISSING,
        embeds: Optional[List[Embed]] = MISSING,
        file: Optional[File] = MISSING,
        files: Optional[List[File]] = MISSING,
        attachments: Optional[List[Attachment]] = MISSING,
        view: Optional[View] = MISSING,
        allowed_mentions: Optional[AllowedMentions] = MISSING,
        delete_after: Optional[float] = None,
    ) -> None:
        """Edit the message that triggered this interaction.
        
        Note: This is only available for component interactions.
        """
        ...
    
    async def send_autocomplete(
        self, 
        choices: Dict[str, Union[str, int, float]]
    ) -> None:
        """Send autocomplete suggestions.
        
        Parameters
        ----------
        choices: Dict[str, Union[str, int, float]]
            A dictionary of choices where keys are display names
            and values are the actual values to be used.
        """
        ...
    
    async def send_modal(self, modal: Modal) -> None:
        """Send a modal dialog in response to the interaction.
        
        Parameters
        ----------
        modal: Modal
            The modal dialog to send.
        """
        ...
    
    @property
    def is_done(self) -> bool:
        """bool: Whether an initial response has been sent."""
        ...

Follow-up Messages { .api }

# Follow-up messages are sent after the initial response
@bot.slash_command(description="Example of follow-up messages")
async def followup_example(interaction: nextcord.Interaction):
    """Demonstrate follow-up message usage."""
    
    # Send initial response
    await interaction.response.send_message("Processing your request...")
    
    # Simulate some work
    import asyncio
    await asyncio.sleep(2)
    
    # Send follow-up message
    await interaction.followup.send("Step 1 complete!")
    
    await asyncio.sleep(1)
    
    # Another follow-up
    embed = nextcord.Embed(title="Final Result", description="Task completed successfully!")
    await interaction.followup.send(embed=embed)
    
    # You can also edit the original message
    await interaction.edit_original_message(content="✅ All steps completed!")

@bot.slash_command(description="Example with deferred response")
async def long_task(interaction: nextcord.Interaction):
    """Example of using deferred response for long tasks."""
    
    # Defer the response to give more time
    await interaction.response.defer(ephemeral=True)
    
    # Simulate long-running task
    import asyncio
    await asyncio.sleep(5)
    
    # Send the actual response via followup
    embed = nextcord.Embed(
        title="Long Task Complete",
        description="The task that took 5 seconds has finished!",
        color=nextcord.Color.green()
    )
    
    await interaction.followup.send(embed=embed)

Application Command Checks

Permission and validation checks for application commands.

Built-in Checks { .api }

from nextcord.ext import application_checks

# Permission-based checks
@application_checks.has_permissions(manage_messages=True)
@bot.slash_command(description="Delete messages")
async def purge(
    interaction: nextcord.Interaction,
    amount: int = SlashOption(description="Number of messages to delete", min_value=1, max_value=100)
):
    """Delete messages (requires manage_messages permission)."""
    deleted = await interaction.channel.purge(limit=amount)
    await interaction.response.send_message(
        f"Deleted {len(deleted)} messages.",
        ephemeral=True
    )

# Role-based checks
@application_checks.has_any_role("Admin", "Moderator")
@bot.slash_command(description="Admin only command")
async def admin_command(interaction: nextcord.Interaction):
    """Command only available to users with Admin or Moderator role."""
    await interaction.response.send_message("Admin command executed!", ephemeral=True)

# Guild-only check
@application_checks.guild_only()
@bot.slash_command(description="Server only command")
async def server_only(interaction: nextcord.Interaction):
    """This command can only be used in servers, not DMs."""
    await interaction.response.send_message(f"Server: {interaction.guild.name}")

# Owner check
@application_checks.is_owner()
@bot.slash_command(description="Bot owner only")
async def owner_only(interaction: nextcord.Interaction):
    """Command only available to the bot owner."""
    await interaction.response.send_message("Owner command executed!", ephemeral=True)

# Custom check function
def is_in_voice_channel():
    """Check if user is in a voice channel."""
    async def predicate(interaction: nextcord.Interaction) -> bool:
        if not interaction.user.voice:
            await interaction.response.send_message(
                "You must be in a voice channel to use this command!",
                ephemeral=True
            )
            return False
        return True
    return application_checks.check(predicate)

@is_in_voice_channel()
@bot.slash_command(description="Voice channel required")
async def voice_command(interaction: nextcord.Interaction):
    """Command that requires being in a voice channel."""
    channel = interaction.user.voice.channel
    await interaction.response.send_message(f"You're in {channel.name}!")

Custom Check Decorators { .api }

from functools import wraps
from nextcord.ext.application_checks import ApplicationCheckFailure

class NotInMaintenanceMode(ApplicationCheckFailure):
    """Custom exception for maintenance mode check."""
    pass

def not_in_maintenance():
    """Custom check to prevent command usage during maintenance."""
    def decorator(func):
        @wraps(func)
        async def wrapper(interaction: nextcord.Interaction, *args, **kwargs):
            # Check some maintenance flag (could be from database, config, etc.)
            maintenance_mode = False  # Replace with actual check
            
            if maintenance_mode:
                await interaction.response.send_message(
                    "🔧 Bot is currently in maintenance mode. Please try again later.",
                    ephemeral=True
                )
                raise NotInMaintenanceMode("Bot is in maintenance mode")
            
            return await func(interaction, *args, **kwargs)
        return wrapper
    return decorator

def cooldown_check(rate: int, per: float):
    """Custom cooldown check for application commands."""
    def decorator(func):
        cooldowns = {}
        
        @wraps(func)
        async def wrapper(interaction: nextcord.Interaction, *args, **kwargs):
            import time
            
            user_id = interaction.user.id
            current_time = time.time()
            
            if user_id in cooldowns:
                time_left = cooldowns[user_id] + per - current_time
                if time_left > 0:
                    await interaction.response.send_message(
                        f"Command on cooldown. Try again in {time_left:.1f} seconds.",
                        ephemeral=True
                    )
                    return
            
            cooldowns[user_id] = current_time
            return await func(interaction, *args, **kwargs)
        
        return wrapper
    return decorator

# Usage of custom checks
@not_in_maintenance()
@cooldown_check(rate=1, per=30.0)  # 1 use per 30 seconds
@bot.slash_command(description="Command with custom checks")
async def custom_checked_command(interaction: nextcord.Interaction):
    """Command with maintenance and cooldown checks."""
    await interaction.response.send_message("Command executed successfully!")

Error Handling

Comprehensive error handling for application commands.

Error Handler { .api }

@bot.event
async def on_application_command_error(interaction: nextcord.Interaction, error: Exception):
    """Global error handler for application commands."""
    
    if isinstance(error, application_checks.MissingPermissions):
        missing = ", ".join(error.missing_permissions)
        await interaction.response.send_message(
            f"❌ You're missing the following permissions: {missing}",
            ephemeral=True
        )
    
    elif isinstance(error, application_checks.MissingAnyRole):
        roles = ", ".join(error.missing_roles)
        await interaction.response.send_message(
            f"❌ You need one of these roles: {roles}",
            ephemeral=True
        )
    
    elif isinstance(error, application_checks.NotOwner):
        await interaction.response.send_message(
            "❌ This command is only available to the bot owner.",
            ephemeral=True
        )
    
    elif isinstance(error, application_checks.NoPrivateMessage):
        await interaction.response.send_message(
            "❌ This command cannot be used in direct messages.",
            ephemeral=True
        )
    
    elif isinstance(error, nextcord.errors.ApplicationInvokeError):
        # Handle errors within command execution
        original_error = error.original
        
        if isinstance(original_error, nextcord.Forbidden):
            await interaction.response.send_message(
                "❌ I don't have permission to perform this action.",
                ephemeral=True
            )
        elif isinstance(original_error, nextcord.NotFound):
            await interaction.response.send_message(
                "❌ The requested resource was not found.",
                ephemeral=True
            )
        else:
            # Log unexpected errors
            import traceback
            print(f"Unexpected error in command: {error}")
            traceback.print_exception(type(original_error), original_error, original_error.__traceback__)
            
            if not interaction.response.is_done():
                await interaction.response.send_message(
                    "❌ An unexpected error occurred. Please try again later.",
                    ephemeral=True
                )
    
    else:
        # Handle other unexpected errors
        print(f"Unhandled application command error: {error}")
        
        if not interaction.response.is_done():
            await interaction.response.send_message(
                "❌ An error occurred while processing your command.",
                ephemeral=True
            )

# Command-specific error handling
@bot.slash_command(description="Command with specific error handling")
async def error_prone_command(
    interaction: nextcord.Interaction,
    user: nextcord.Member = SlashOption(description="Target user")
):
    """Command that demonstrates error handling."""
    try:
        # Some operation that might fail
        await user.send("Hello from the bot!")
        await interaction.response.send_message(f"Message sent to {user.mention}!")
        
    except nextcord.Forbidden:
        await interaction.response.send_message(
            f"❌ I can't send a DM to {user.mention}. They may have DMs disabled.",
            ephemeral=True
        )
    except nextcord.HTTPException as e:
        await interaction.response.send_message(
            f"❌ Failed to send message: {e}",
            ephemeral=True
        )
    except Exception as e:
        await interaction.response.send_message(
            "❌ An unexpected error occurred.",
            ephemeral=True
        )
        # Log the error for debugging
        import traceback
        traceback.print_exc()

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

Install with Tessl CLI

npx tessl i tessl/pypi-nextcord

docs

application-commands.md

channels.md

client.md

commands.md

errors.md

events.md

guild.md

index.md

messages.md

permissions.md

tasks.md

ui.md

users.md

utilities.md

voice.md

webhooks.md

tile.json