Name already in use
discord-py-guide / slash-commands.md
- Go to file T
- Go to line L
- Copy path
- Copy permalink
1 contributor
Users who have contributed to this file
- Open with Desktop
- View raw
- Copy raw contents Copy raw contents
Copy raw contents
Copy raw contents
Если вы только начали изучать работу с библиотекой, то рекомендую сначала изучить основное руководство или хотя бы основы prefix-команд
На этом этапе надо отметить, что discord-py — устаревшая библиотека, которая не обновляется под новые фишки дискорда. Поэтому для работы со slash-командами, кнопками и выпадающими списками стоит удалить старую библиотеку и установить ее форк PyCord :
В целом, вся структура классов, их свойств и методов в PyCord осталась такой же как в discord-py , поэтому ничего менять и переписывать не нужно. Поэтому к PyCord подойдет документация от discord-py , но я все же рекомендую пользоваться документацией именно от PyCord
Для реализации slash-команд, в качестве объекта бота можно использвать все тот же класс discord.ext.commands.Bot .
Для slash-команд, остаются актуальными все свойства prefix-команд. Разве что, декоратор @bot.command() меняется на @bot.slash_command()
Декоратор @bot.slash_command() принимает некоторые необязательные аргументы. Рассмотрим следующие:
- name : название команды
- description : описание команды
- guild_ids : список id серверов, на которых эта команда будет доступна. Поскольку slash-команды синхронизируются с дискордом, данный параметр также имеет смысл указывать для ускорения процесса синхронизации. (Подробный разбор проблемы)
Теперь приступим к созданию команды. В декоратор можно сразу передать параметры названия и описания:
Конечно, там есть много других параметров, описание которых можно найти в документации по discord.SlashCommand
Далее создаем функцию команды. Поскольку дискорд обрабатывает команды интерактивно,
необходимо что-то делать с контекстом выполнения команды:
Либо его можно удалить ( await ctx.delete() ):
Результат:
Либо отправить ответ сразу ( await ctx.respond() ):
Результат:
Если не сделать что-то с конекстом, то дискорд не дождавшись ответа от бота, выдаст ошибку. Например, вот такая команда, которая ничего не возвращает, а просто осуществляет вывод в консоль
Действительно выведет сообщение в консоль, но вот обработка команды в дискорде будет выглядеть так:
Выглядит так, будто при выполнении произошла ошибка, но на деле это просто дискорд не получил ответа от бота. Однако это может произойти даже если команда подразумевает ответ. Например, если идут какие-то долгие вычисления, дискорд может просто не дождаться ответа и команда не выполнится. В таких случаях контекст стоит либо удалять, как показано в примере выше, либо использовать метод контекста defer() .
Из описания следует, что он нужен как раз для таких ситуаций: «Откладывает ответ на взаимодействие. Обычно это используется, когда взаимодействие подтверждено, а дополнительное действие будет выполнено позже.«
Результат:
Разумеется, использовать метод await ctx.defer() имеет смысл только если вы собираетесь что-то отвечать на команду. Если же никакого ответа не подразумевается, то лучше просто удалять контекст. Иначе бот просто бесконечно будет «думать» как на скрине выше.
Работа с аргументами
Работа с аргументами у slash-команд устроена иначе, нежели у prefix-команд. Чтобы PyCord распознал аргумент и передал его в дискорд, нужно в качестве аннотации типа аргумента команды указать экземпляр класса discord.Option
Для начала импортируем класс в код
Конструктор класса Option принимает некоторые параметры. В основном указывают следующие:
- тип аргумента
- name : название аргумента (Наследуется от имени переменной, если оно не указано в качестве параметра.)
- description : описание аргумента
- required : обязательно ли указывать этот аргумент при вызове команды ( True / False )
- default : стандартное значение аргумента, если он не был указан
Также есть следующие:
- min_value : минимальное число, которое пользователь может ввести в качестве аргумента (если тип аргумента — int / float )
- max_value : тоже самое, что и min_value , только это верхняя граница — максимальное число
- choices : список ( list ) значений аргумента, которые пользователь может выбрать
- min_length : минимальная длина строки, которую пользователь должен ввести в качестве значения аргумента
Есть и другие параметры, про которые все также можно почитать в документации к discord.Option . Некоторые из них будут разобраны позже.
Таким образом, получение любого аргумента будет выглядеть так:
Теперь давайте попробуем получить от пользователя следующие аргументы:
- Число в диапазоне от 1 до 10
- Значение типа bool
- Участника сервера ( discord.Member )
- Текст из нескольких слов
- Слово из списка для выбора
Реализация аргументов будет выглядеть так:
Результат:
- Аргументы можно указывать в разном порядке
- Встроенная проверка не даст ввести некорректное значение
- Необязательные ( required=False ) параметры можно не указывать
На выходе получаем:
Пользовательские типы аргументов
Предположим, вам нужно получить от пользователя bool -значение. Чтобы не указывать в описании аргумента за что отвечает True , а за что False , можно написать свой тип аргумента, который будет предлагать пользователю выбор Да / Нет (Вместо True / False ), затем автоматически конвертировать выбор в bool .
Для этого создадим новый статический класс, который будет наследоваться от discord.ext.commands.Converter .
Класс должен переопределять метод convert , принимающий аргументы:
- cls — объект этого класса
- ctx — контекст выполнения команды
- arg — значение аргумента
Данный метод будет конвертировать полученную строку ( str ) ‘Да’ / ‘Нет’ в bool в зависимоси от значения.
Также внутри класса можно сразу создать поле choices , содержащее варианты выбора:
Теперь подставим его в качестве типа аргумента. В параметр choices передадим значение поля класса:
Результат:
Разумеется, можно делать и более сложные конвертации во что угодно, буквально ограничиваясь своей фантазией и необходимостью. Вот пример преобразования слова в число:
How do i make a working slash command in discord.py
I am trying to make a slash command with discord.py I have tried a lot of stuff it doesn’t seem to be working. Help would be appreciated.
6 Answers 6
Note: I will include a version for pycord at the end because I think it’s much simpler, also it was the original answer.
discord.py version
First make sure that you have the newest version of discord.py installed. In your code, you first import the library:
and then you define your client and tree:
The tree holds all of your application commands. Then you can define your command:
Then you also have to sync your commands to discord once the client is ready, so we do that in the on_ready event:
And at the end we have to run our client:
pycord version
To install py-cord, first run pip uninstall discord.py and then pip install py-cord . Then in your code, first import the library with
create you bot class with
and create your slash command with
and then run the bot with your token
They’re sort of in the middle of adding slash commands to discord.py but you can see a few examples in https://gist.github.com/Rapptz/c4324f17a80c94776832430007ad40e6 You seem to be using discord_slash, which I have not used.
The main documentation for this stuff is https://discordpy.readthedocs.io/en/master/interactions/api.html?highlight=dropdown#decorators but the main "how to" is that you’ve gotta make a "tree", attach commands to that tree, and sync your tree for the commands to show up. discord.ext.Bot makes its own tree, which is why I’m using that instead of client, which I think doesn’t make a tree by default.
If you specify the guilds, the commands sync takes place instantly, but if you don’t specify the guild, I think it takes an hour to update or something like that, so specify the guild until you’re ready for deployment.
I’m not quite sure how to do it in cogs, because I have mine in groups but basically what I’m doing is a combination of @bot.tree.command() in the main bot file and a few groups in separate files.
So here’s my main file
and then the simplegeneralgroup file
There should be three commands: /slash, which will prompt the user for a number and string, /generalgroup hello, and /generalgroup version
Slash Commands
On March 24, 2021, Discord added Slash Commands to Discord as an easier, more efficient, and better way of using bot commands. Pycord has implemented Slash Commands into the library, so it's simple, efficient, and familiar.
Remember that Slash Commands require your bot to be invited with the application.commands scope or Slash Commands will not show up. Bots already in the guild can simply be invited again with the scope; there is no need to kick the bot.
Syntax
Let's create a simple Slash Command.
BobDotCom used / ping
Let's go through the code.
First, we import Pycord's discord package.
Next, we create a discord.Bot object and assign it to a variable bot .
We then go ahead and use the @bot.command decorator, which registers a new Slash Command. We pass a description parameter to give a description to the Slash Command. We can also pass a name parameter to change the Slash Command's name. By default, the name of the Slash Command will be the name of the function, in this case, /ping .
We create an async function called ping with parameters ctx , which, when called, sends the bot's ping/latency using ctx.respond .
Subcommand Groups
You might want to group certain commands together to make them more organised. A command group is exactly what it sounds like, a group of individual Slash Commands together.
In order to make a Slash Command group, you can use the bot.create_group function.
Or, you can instead manually make a SlashCommandGroup class like so:
Here's what the registered subcommands will look like in the Slash Command Menu:
You'll notice that there's the name of the Slash Command Group and then the name of the subcommand separated by a space.
Sub-groups
We've made a subcommand group, but did you know that you could create a group inside another?
The command created above can be invoked by typing /math advanced square_root .
Options & Option Types
Whenever you're using Slash Commands, you might notice that you can specify parameters that the user has to set or can optionally set. These are called Options.
Since you want different inputs from Options, you'll have to specify the type for that Option. There are a few ways of doing this.
- Using Type Annotations
- Using the SlashCommandOptionType enum
You could use Type Annotations and let Pycord figure out the option type, like shown below.
Getting Started
Before we begin getting started on everything else, it is recommended to check out the quickstart page first to get a basic grip on making slash commands for your bot.
Making a slash command.
The basics.
First, let’s explain by how commands are parsed through the Discord Bot API.
As you may know, Discord relies a lot on the interaction of HTTP Requests and JSON tables. As is with the case here, commands are the exact same way with having JSON tables to structure the design of it for Discord to understand. We can apply this information likewise with how slash commands are to be designed in the Python code. Below attached is from the Discord Developer Portal on Slash Commands for showing how they are designed.
Field
Type
Description
1-32 character name matching ^[\w-]<1,32>$ .
1-100 character description.
if the option is a subcommand or subcommand group type, this nested options will be the parameters.
This table shows us the way that Discord handles the structure of commands for slash commands through their Bot API. For visualization purposes, we’ll quickly make a JSON example (although we won’t be using it) in order to explain how this works:
Now that we have a basic understanding of how the JSON table works, we can take this knowledge and convert it into a decorator method for the Python code as shown below:
Now that we’ve gone over how Discord handles the declaration of slash commands through their Bot API, let’s go over what some of the other things mean within the logical part of our code, the command function:
Giving some options for variety.
The next thing that we will begin to talk about is the implementation of options, otherwise well-known as “arguments” in discord.py commands.
The JSON structure of options are designed up to be similar to the same premise of how a slash command is declared. Below is the given table of how an option JSON would appear as:
Field
Type
Description
1-32 character name matching ^[\w-]<1,32>$ .
1-100 character description.
the first required option for the user to complete–only one option can be default.
if the parameter is required or optional–default false .
choices for string and int types for the user to pick from.
if the option is a subcommand or subcommand group type, this nested options will be the parameters.
Now we have an idea of how options are declared. With this in mind, let’s quickly make a JSON example in order to visualize this concept even further:
While the table in the basics mentions an array in particular called ApplicationCommandOptionType , there isn’t that much of an explanation on how this works. Let’s put this into better laymen terms on what this means with a table below showing all of these values:
Name
Value
The purpose of having the ApplicationCommandOptionType value passed into our option JSON structure is so that we can help the Discord UI understand what kind of value we’re inputting here. For instance, if we’re wanting to put in a string response, we’ll pass the ID 3 so that the UI of Discord chat bar knows to format it visually this way. If we’re looking for a user, then we’ll pass ID 6 so that it presents us with a list of users in our server instead, making it easier on our lives.
This is not to be confused, however, with formatting the response type itself. This is merely a method so that the API wrapper can help us with passing the correct type or instance variable with the arguments of the command function’s code.
Now, we can finally visualize this by coding an example of this being used in the Python code shown below.
Additionally, we could also declare the type of our command’s option through this method shown here:
More in the option? Give them a choice.
Alas, there is also a way to give even more information to options with Discord’s Slash Commands: a choice. Not like something that you’re given at birth of when you become of legal age as an adult, we’re not here to give you that kind of life advice, but the choice of what value you want your option to rather pass. Below is a table that shows the JSON structure of how choices are represented for an option:
Field
Type
Description
1-32 character choice name.
value of the choice, up to 100 characters if string.
This time, only 2 fields are able to be passed for this. Below is a JSON example of how this would be designed:
To make it really simple, the name field is only to be used for how you want the choice to be presented through Discord’s UI. It’s the “appearance” of how you want your choice shown, not the actual returned value of it. Hence, this is why value is the second field passed for that, which can be either in the form of a string or integer. Below is an implementation of this design in the Python code:
Want to restrict access? Setup permissions!
Slash commands also support the ability to set permissions to allow only certain roles and/or users to run a slash command. Permissions can be applied to both global and guild based commands. They are defined per guild, per top-level command (the base command for subcommands), and each guild can have multiple permissions. Here is the table that shows the JSON structure of how permissions are represented:
Field
Type
Description
Snowflake value of type specified. Represents the target to apply permissions on.
True to allow, False to disallow.
How the type parameter works is very simple. Discord has many ids to represent different things. As you can set permissions to apply for User or Role, ApplicationCommandPermissionType is used. It’s a number and following table shows the supported id types for permissions:
Name
Value
This is an example of how a single permission will look when represented as a json object:
Now, let take a look at an example. The slash command decorator has a permissions parameter where it takes in a dictionary. The key being the guild id to apply permissions on, and value being the list of permissions to apply. For each permission, we can use the handy create_permission method to build the permission json explained above.
In this case, we are setting 2 permissions for a guild with an id of 12345678 . Firstly, we are allowing role with id 99999999 and disallowing user with id 88888888 from running the slash command.