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:
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:
Union[User, Member](wesuwts inOptionType.user)Union[Member, Role](wesuwts inOptionType.mentionable)Union[User, Role](wesuwts inOptionType.mentionable)Union[User, Member, Role](wesuwts inOptionType.mentionable)
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.