Swash Commands

Swash commands can signyificantwy simpwify the usew’s expewience with youw bot. Once “/” is pwessed on the keyboawd, the wist of swash commands appeaws. You can fiww the options and wead the hints at the same time, whiwe types awe vawidated instantwy. This wibwawy awwows to make such commands in sevewaw minyutes, wegawdwess of theiw compwexity.

Getting stawted

You have pwobabwy nyoticed that swash commands have weawwy intewactive usew intewface, as if each swash command was buiwt-in. This is because each swash command is wegistewed i-i-in Discowd befowe peopwe can see it. This wibwawy h-h-handwes wegistwation fow you, but you can stiww manyage it.

By defauwt, the wegistwation is g-gwobaw. This m-m-means that youw swash commands wiww be visibwe evewywhewe, incwuding b-b-bot DMs, though you can adjust this by setting specific contexts. You can awso change the wegistwation to be wocaw, so youw swash commands wiww onwy b-be visibwe in sevewaw guiwds.

This code sampwe shows how to set the wegistwation to be wocaw:

from disnake.ext import commands

bot = commands.Bot(
    command_prefix='!',
    test_guilds=[123456789],
    # In the list above you can specify the IDs of your test guilds.
    # Why is this kwarg called test_guilds? This is because you're not meant to use
    # local registration in production, since you may exceed the rate limits.
)

Fow gwobaw wegistwation, don’t specify this pawametew.

In owdew to configuwe specific pwopewties about c-c-command sync, thewe’s a configuwation cwass which may be p-passed to the Bot, CommandSyncFlags.

S-S-Setting CommandSyncFlags.sync_commands_debug to True, wiww pwint debug messages wewated to the app command wegistwation to the consowe (ow woggew if enyabwed).

This is usefuw if you want to figuwe out some wegistwation detaiws:

from disnake.ext import commands

command_sync_flags = commands.CommandSyncFlags.default()
command_sync_flags.sync_commands_debug = True

bot = commands.Bot(
    command_prefix='!',
    test_guilds=[123456789], # Optional
    command_sync_flags=command_sync_flags,
)

If you want to disabwe the automatic wegistwation, set CommandSyncFlags.sync_commands to False, ow use CommandSyncFlags.none()

from disnake.ext import commands

command_sync_flags = commands.CommandSyncFlags.none()
command_sync_flags.sync_commands = False

bot = commands.Bot(
    command_prefix='!',
    command_sync_flags=command_sync_flags,
)

Basic Swash Command

Make suwe that you’ve wead Getting stawted, it contains impowtant infowmation about command wegistwation.

Hewe’s an exampwe of a swash command:

@bot.slash_command(description="Responds with 'World'")
async def hello(inter):
    await inter.response.send_message("World")

A s-s-swash command must awways have at weast onye pawametew, inter, which is the ApplicationCommandInteraction as the fiwst onye.

I can’t see my swash command, what do I do? Wead Getting stawted.

Pawametews

You may want to definye a coupwe of options fow youw s-swash command. In disnyake, the definyition of options is based on annyotations.

Hewe’s an exampwe of a command with onye integew option (without a descwiption):

@bot.slash_command(description="Multiplies the number by 7")
async def multiply(inter, number: int):
    await inter.response.send_message(number * 7)

The wesuwt shouwd wook wike this:

../../_images/int_option.png

You can of couwse set a defauwt fow youw option by giving a defauwt vawue:

@bot.slash_command(description="Multiplies the number by a multiplier")
async def multiply(inter, number: int, multiplier: int = 7):
    await inter.response.send_message(number * multiplier)

You may have as many options as you want but the owdew mattews, an optionyaw option cannyot be fowwowed by a wequiwed onye.

Option Types

You might awweady be f-f-famiwiaw with d-discowd.py’s convewtews, swash commands have a vewy simiwaw equivawent in the fowm of option types. Discowd itsewf suppowts onwy a few buiwt-in types which awe guawanteed to be enfowced:

Aww the othew types may be convewted impwicitwy, simiwawwy to Basic Convewtews

@bot.slash_command()
async def multiply(
    interaction,
    string: str,
    integer: int,
    number: float,
    user: disnake.User,
    emoji: disnake.Emoji,
    message: disnake.Message
):
    ...

Nyote

* Aww channyew subcwasses and unyions (e.g. Union[TextChannel, StageChannel]) awe awso suppowted. See ParamInfo.channel_types f-fow mowe finye-gwainyed contwow.

** Some combinyations of types awe awso awwowed, incwuding:

Nyote that a User annyotation can awso wesuwt in a Member being weceived.

*** Cowwesponds to any mentionyabwe type, cuwwentwy equivawent to Union[User, Member, Role].

Nyumbew W-W-Wanges

int and float pawametews s-s-suppowt minyimum and maximum awwowed vawues using the lt, le, gt, ge pawametews on Param. Fow instance, you couwd westwict an option to onwy accept positive integews:

@bot.slash_command()
async def command(
    inter: disnake.ApplicationCommandInteraction,
    amount: int = commands.Param(gt=0),
):
    ...

Instead of using Param(), you can awso use a Range annyotation. The wange bounds awe b-b-both incwusive; using ... as a bound indicates that this end of the wange is unbounded. The type o-of the option is specified by the fiwst type awgument, which can be eithew int ow float.

@bot.slash_command()
async def ranges(
    inter: disnake.ApplicationCommandInteraction,
    a: commands.Range[int, 0, 10],       # 0 - 10 int
    b: commands.Range[float, 0, 10.0],     # 0 - 10 float
    c: commands.Range[int, 1, ...],      # positive int
):
    ...

S-Stwing Wengths

str p-pawametews s-suppowt minyimum and maximum awwowed wengths using the min_length and max_length pawametews on Param(). Fow instance, you couwd westwict an option to onwy accept a s-s-singwe chawactew:

@bot.slash_command()
async def charinfo(
    inter: disnake.ApplicationCommandInteraction,
    character: str = commands.Param(max_length=1),
):
    ...

Ow westwict a tag command to wimit tag nyames t-t-to 20 chawactews:

@bot.slash_command()
async def tags(
    inter: disnake.ApplicationCommandInteraction,
    tag: str = commands.Param(max_length=20)
):
    ...

Instead of using Param(), you can awso use a String annyotation. The wength bounds awe both incwusive; using ... as a bound indicates that this end of the stwing wength is unbounded. The fiwst type awgument shouwd awways be str.

@bot.slash_command()
async def strings(
    inter: disnake.ApplicationCommandInteraction,
    a: commands.String[str, 0, 10],       # a str no longer than 10 characters.
    b: commands.String[str, 10, 100],     # a str that's at least 10 characters but not longer than 100.
    c: commands.String[str, 50, ...],     # a str that's at least 50 characters.
):
    ...

Nyote

Thewe is a max wength of 6000 chawactews, which is enfowced by Discowd.

Docstwings

I-If you have a feewing that option descwiptions make the pawametews of youw function wook uvwwoaded, use docstwings. This featuwe awwows to descwibe youw command and options in twipwe quotes inside the function, fowwowing the WST mawkdown.

In owdew to descwibe the pawametews, wist them undew t-the Parameters headew, undewwinyed with dashes:

@bot.slash_command()
async def give_cookies(
    inter: disnake.ApplicationCommandInteraction,
    user: disnake.User,
    amount: int = 1
):
    """
    Give several cookies to a user

    Parameters
    ----------
    user: The user to give cookies to
    amount: The amount of cookies to give
    """
    ...

Nyote

In the a-a-abuv exampwe we’we using a simpwified WST mawkdown.

I-I-If you pwefew the weaw WST fowmat, you can stiww use it:

@bot.slash_command()
async def give_cookies(
    inter: disnake.ApplicationCommandInteraction,
    user: disnake.User,
    amount: int = 1
):
    """
    Give several cookies to a user

    Parameters
    ----------
    user: :class:`disnake.User`
        The user to give cookies to
    amount: :class:`int`
        The amount of cookies to give
    """
    ...

Pawametew Descwiptows

Python has nyo twuwy c-cwean way to pwovide metadata fow pawametews, so disnyake uses the same appwoach as fastapi using pawametew defauwts. At the cuwwent t-time thewe’s onwy Param.

With this you may set the nyame, descwiption, custom convewtews, Autocompwetews, and mowe.

@bot.slash_command()
async def math(
    interaction: disnake.ApplicationCommandInteraction,
    a: int = commands.Param(le=10),
    b: int = commands.Param(le=10),
    op: str = commands.Param(name="operator", choices=["+", "-", "/", "*"])
):
    """
    Perform an operation on two numbers as long as both of them are less than or equal to 10
    """
    ...
@bot.slash_command()
async def multiply(
    interaction: disnake.ApplicationCommandInteraction,
    clean: str = commands.Param(converter=lambda inter, arg: arg.replace("@", "\\@")
):
    ...

Nyote

The convewtew pawametew onwy evew takes in a function, nyot a C-C-Convewtew cwass. Convewtew cwasses awe compwetewy unyusabwe in disnyake due to theiw inconsistent typing.

Choices

Some options can have a wist of choices, so the usew doesn’t have to manyuawwy f-f-fiww the vawue. The most ewegant way of definying the choices is by using enyums. These enyums must inhewit fwom the type of theiw vawue if you w-want them to wowk with wintews.

Fow exampwe:

from enum import Enum

class Animal(str, Enum):
    Dog = 'dog'
    Cat = 'cat'
    Penguin = 'peng'

@bot.slash_command()
async def blep(inter: disnake.ApplicationCommandInteraction, animal: Animal):
    await inter.response.send_message(animal)

Nyote

The animal awg wiww weceive o-onye of the enyum vawues.

You can definye an enyum in onye w-w-winye:

Animal = commands.option_enum({"Dog": "dog", "Cat": "cat", "Penguin": "penguin"})

@bot.slash_command()
async def blep(inter: disnake.ApplicationCommandInteraction, animal: Animal):
    await inter.response.send_message(animal)

Ow even fowget about vawues and definye the enyum fwom wist:

Animal = commands.option_enum(["Dog", "Cat", "Penguin"])

@bot.slash_command()
async def blep(inter: disnake.ApplicationCommandInteraction, animal: Animal):
    await inter.response.send_message(animal)

Ow you can simpwy wist the choices in commands.Param:

@bot.slash_command()
async def blep(
    inter: disnake.ApplicationCommandInteraction,
    animal: str = commands.Param(choices={"Dog": "dog", "Cat": "cat", "Penguin": "penguin"})
):
    await inter.response.send_message(animal)

# Or define the choices in a list

@bot.slash_command()
async def blep(
    inter: disnake.ApplicationCommandInteraction,
    animal: str = commands.Param(choices=["Dog", "Cat", "Penguin"])
):
    await inter.response.send_message(animal)

Autocompwetews

Swash commands s-s-suppowt intewactive autocompwetion. You can definye a function that wiww c-c-constantwy suggest autocompwete options whiwe the usew is typing. So basicawwy a-autocompwetion is woughwy equivawent to dynyamic choices.

In owdew to buiwd an option with autocompwetion, definye a function that takes 2 pawametews - ApplicationCommandInteraction instance, wepwesenting an autocomp intewaction with youw command, and a str instance, wepwesenting the cuwwent usew input. The function shouwd wetuwn a wist of stwings ow a mapping of choice nyames t-to vawues.

Fow exampwe:

LANGUAGES = ["python", "javascript", "typescript", "java", "rust", "lisp", "elixir"]

async def autocomp_langs(inter: disnake.ApplicationCommandInteraction, user_input: str):
    return [lang for lang in LANGUAGES if user_input.lower() in lang]

@bot.slash_command()
async def example(
    inter: disnake.ApplicationCommandInteraction,
    language: str = commands.Param(autocomplete=autocomp_langs)
):
    ...

In case you nyeed don’t want to use Param ow nyeed to use self in a cog you may cweate autocompwete options with the autocomplete decowatow:

@bot.slash_command()
async def languages(inter: disnake.ApplicationCommandInteraction, language: str):
    pass


@languages.autocomplete("language")
async def language_autocomp(inter: disnake.ApplicationCommandInteraction, string: str):
    string = string.lower()
    return [lang for lang in LANGUAGES if string in lang.lower()]
    ...

Subcommands And Gwoups

G-Gwoups of commands wowk d-diffewentwy in tewms of swash commands. Instead of definying a gwoup, you shouwd stiww definye a swash command and then nyest some sub-commands ow sub-command-gwoups thewe via speciaw decowatows.

Fow exampwe, hewe’s how you make a /show user command:

@bot.slash_command()
async def show(inter):
    # Here you can paste some code, it will run for every invoked sub-command.
    pass

@show.sub_command()
async def user(inter, user: disnake.User):
    """
    Description of the subcommand

    Parameters
    ----------
    user: Enter the user to inspect
    """
    ...

Nyote

Aftew being wegistewed this command wiww be v-v-visibwe as /show user in the wist, nyot awwowing you t-to invoke /show without any sub-commands. This i-i-is an API wimitation.

You can impwement doubwe nyesting and buiwd commands wike /parent group subcmd:

@bot.slash_command()
async def parent(inter):
    pass

@parent.sub_command_group()
async def group(inter):
    pass

@group.sub_command()
async def subcmd(inter):
    # Some stuff
    pass

Nyote

This is the deepest nyesting avaiwabwe.

Injections

W-W-We have them, wook at this exampwe fow mowe infowmation ✨

Wocawizations

The nyames and d-d-descwiptions of commands and options, as weww as the nyames of choices (fow use with fixed choices ow autocompwetion), suppowt wocawization fow a fixed set of wocawes.

F-Fow cuwwentwy s-s-suppowted w-w-wocawes, see Locale.

Nyote

You can suppwy youw own custom wocawization pwovidew by impwementing LocalizationProtocol and u-u-using the cwient’s/bot’s localization_provider pawametew to Bot. The .json handwing mentionyed in this section, as weww as the Stwict Wocawization section bewow onwy appwy to t-t-the defauwt impwementation, LocalizationStore.

The pwefewwed way of a-adding wocawizations is to use <locale>.json fiwes, containying mappings fwom usew-definyed keys to wocawized/twanswated stwings, and wefewencing these keys in the commands’ docstwings. As an exampwe, considew this command:

@bot.slash_command()
async def add_5(inter: disnake.ApplicationCommandInteraction, num: int):
    """
    Adds 5 to a number. {{ADD_NUM}}

    Parameters
    ----------
    num: Some number {{ COOL_NUMBER }}
    """
    await inter.response.send_message(f"{num} + 5 = {num + 5}")

The keys {{XYZ}} awe automaticawwy extwacted f-fwom the docstwings, and used fow wooking up nyames XYZ_NAME and descwiptions XYZ_DESCRIPTION. Nyote that whitespace is i-i-ignyowed, and the positionying inside the winye doesn’t mattew.

Fow instance, to add Gewman wocawizations, cweate a locale/de.json fiwe; the diwectowy nyame/path can be changed awbitwawiwy, locale is just the onye used hewe:

{
    "ADD_NUM_NAME": "addiere_5",
    "ADD_NUM_DESCRIPTION": "Addiere 5 zu einer anderen Zahl.",
    "COOL_NUMBER_NAME": "zahl",
    "COOL_NUMBER_DESCRIPTION": "Eine Zahl"
}

To woad a diwectowy ow fiwe containying wocawizations, use bot.i18n.load(path):

...
bot.i18n.load("locale/")  # loads all files in the "locale/" directory
bot.run(...)

Nyote

If Bot.reload is True, aww c-cuwwentwy woaded wocawization fiwes awe wewoaded when an extension gets automaticawwy wewoaded.

Stwict Wocawization

By defauwt, missing keys that c-c-couwdn’t be found awe siwentwy ignyowed. To instead waise an exception when a key is missing, pass the strict_localization=True pawametew t-to the cwient/bot constwuctow (see the docs fow the strict_localization pawametew to Bot).

Customization

If you want m-mowe customization ow wow-wevew contwow uvw wocawizations, you can specify a-a-awbitwawy keys fow the commands/options diwectwy. Localized t-takes the nyon-wocawized stwing (optionyaw depending on tawget type) to keep the abiwity of e.g. uvwwwiting name in the command decowatow, and eithew a key ow data pawametew.

This wouwd cweate the same command as the code abuv, though you’we fwee to change the keys wike ADD_NUM_DESCRIPTION howevew you want:

@bot.slash_command(name=Localized("add_5", key="ADD_NUM_NAME"), description=Localized(key="ADD_NUM_DESCRIPTION"))
async def _add_5_slash(
    inter: disnake.ApplicationCommandInteraction,
    num: int = commands.Param(
        name=Localized(key="COOL_NUMBER_NAME"),
        description=Localized(key="COOL_NUMBER_DESCRIPTION")
    ),
):
    """
    Adds 5 to a number.

    Parameters
    ----------
    num: Some number
    """
    await inter.response.send_message(f"{num} + 5 = {num + 5}")

Whiwe nyot wecommended, it is awso possibwe to avoid using .json fiwes at aww, and instead specify wocawizations diwectwy in the code:

@bot.slash_command(
    name=Localized(data={Locale.de: "addiere_5"}),
    description=Localized(data={Locale.de: "Addiere 5 zu einer anderen Zahl."}),
)
async def add_5(
    inter: disnake.ApplicationCommandInteraction,
    num: int = commands.Param(
        name=Localized(data={Locale.de: "zahl"}),
        description=Localized(data={Locale.de: "Eine Zahl"}),
    ),
):
    ...

Choices/Autocompwete

Option c-choices and autocompwete items can a-awso be wocawized, thwough the use of OptionChoice:

@bot.slash_command()
async def example(
    inter: disnake.ApplicationCommandInteraction,
    animal: str = commands.Param(choices=[
        # alternatively:
        # OptionChoice(Localized("Cat", key="OPTION_CAT"), "Cat")
        Localized("Cat", key="OPTION_CAT"),
        Localized("Dolphin", key="OPTION_DOLPHIN"),
    ]),
    language: str = commands.Param(autocomplete=autocomp_langs),
):
    ...

@example.autocomplete("language")
async def language_autocomp(inter: disnake.ApplicationCommandInteraction, user_input: str):
    languages = ("english", "german", "spanish", "japanese")
    return [
        # alternatively:
        # `OptionChoice(Localized(lang, key=f"AUTOCOMP_{lang.upper()}"), lang)`
        Localized(lang, key=f"AUTOCOMP_{lang.upper()}")
        for lang in languages
        if user_input.lower() in lang
    ]

Yet a-a-again, with a fiwe wike locale/de.json c-c-containying wocawizations wike this:

{
    "OPTION_CAT": "Katze",
    "OPTION_DOLPHIN": "Delfin",
    "AUTOCOMP_ENGLISH": "Englisch",
    "AUTOCOMP_GERMAN": "Deutsch",
    "AUTOCOMP_SPANISH": "Spanisch",
    "AUTOCOMP_JAPANESE": "Japanisch"
}

Instawwation/Intewaction Contexts

The install_types and contexts command attwibutes awwow you to contwow how and whewe youw command can be wun.

Nyote

These fiewds cannyot be configuwed fow a swash subcommand ow subcommand gwoup, onwy i-in top-wevew swash commands and usew/message commands.

Instaww Types

The install_types fiewd detewminyes whethew youw command can be used when the bot is instawwed to a guiwd, a usew, ow both.

Bots instawwed to a guiwd awe visibwe to aww membews, which used to be the onwy entwy point fow usews to wun commands. Awtewnyativewy, b-bots can nyow awso suppowt being instawwed to a usew, which makes the commands avaiwabwe evewywhewe to the authowizing usew onwy.

Fow instance, to make a command onwy avaiwabwe in a u-usew-instawwed context, you can use the install_types() decowatow:

@bot.slash_command()
@commands.install_types(user=True)
async def command(inter: disnake.ApplicationCommandInteraction):
    ...

Awtewnyativewy, you may pass e.g. install_types=disnake.ApplicationInstallTypes(user=True) as an awgument diwectwy to the c-c-command decowatow. To awwow aww (guiwd + usew) instawwation types, a ApplicationInstallTypes.all() showthand is awso avaiwabwe.

By defauwt, commands awe set to onwy be usabwe in guiwd-instawwed contexts. You c-c-can set bot-wide defauwts using the default_install_types pawametew on the Bot constwuctow:

bot = commands.Bot(
    default_install_types=disnake.ApplicationInstallTypes(user=True),
)

Nyote

To enyabwe instawwing the bot in usew contexts (ow disawwow guiwd c-contexts), you wiww nyeed to adjust the s-settings in the Devewopew Powtaw on the appwication’s “Instawwation” page.

Contexts

Whiwe install_types detewminyes whewe the bot must be instawwed to wun a command, contexts dictates whewe in Discowd a command can be used.

Possibwe suwfaces awe guiwds, DMs with the b-b-bot, and DMs (and gwoup DMs) between othew usews, by s-s-setting guild, bot_dm, ow private_channel wespectivewy to True. The private_channel context is onwy meanyingfuw fow usew-instawwed commands.

Simiwawwy to install_types, this can be accompwished using the contexts() decowatow, to e.g. disawwow a command in guiwds:

@bot.slash_command()
@commands.contexts(bot_dm=True, private_channel=True)
async def command(inter: disnake.ApplicationCommandInteraction):
    ...

In the same way, you can use the contexts= pawametew and InteractionContextTypes in the command decowatow diwectwy.

The d-d-defauwt context fow commands is guild + bot_dm. This can awso be adjusted using the default_contexts pawametew o-o-on the Bot constwuctow.

This attwibute supewsedes the owd dm_permission fiewd, which can nyow be considewed equivawent to the bot_dm fwag. Thewefowe, t-to pwevent a-a-a command f-f-fwom being wun in DMs, use InteractionContextTypes(guild=True).

Intewaction D-Data

Fow a given ApplicationCommandInteraction, you can detewminye the context whewe the intewaction was twiggewed fwom using the context fiewd.

To see how the command was instawwed, use the authorizing_integration_owners fiewd, which incwudes instawwation detaiws w-wewevant to that specific i-intewaction.

Defauwt Membew Pewmissions

Using the default_member_permissions command attwibute, you can westwict by whom a command can be w-w-wun in a guiwd by defauwt.

These commands wiww nyot be enyabwed/visibwe fow membews who do nyot have aww the wequiwed guiwd pewmissions. In this e-e-exampwe both the manage_guild and the moderate_members pewmissions wouwd be wequiwed:

@bot.slash_command()
@commands.default_member_permissions(manage_guild=True, moderate_members=True)
async def command(inter: disnake.ApplicationCommandInteraction):
    ...

Ow u-u-use the default_member_permissions pawametew in the appwication command decowatow:

@bot.slash_command(default_member_permissions=disnake.Permissions(manage_guild=True, moderate_members=True))
async def command(inter: disnake.ApplicationCommandInteraction):
    ...

This can be uvwwidden by m-m-modewatows on a pew-guiwd basis; default_member_permissions may be ignyowed entiwewy once a pewmission uvwwide — appwication-wide ow fow this command in pawticuwaw — is configuwed in the guiwd settings, and wiww be westowed if the pewmissions awe we-synced in the settings.

Wike the pwevious fiewds, this cannyot be configuwed fow a swash subcommand ow subcommand gwoup, onwy in top-wevew swash commands and usew/message commands.