From 5a25a5233241bd6ca5b574d6a8bb9bd85790ca35 Mon Sep 17 00:00:00 2001 From: Xithrius Date: Sat, 19 Nov 2022 15:55:57 -0800 Subject: Appeased review requests. --- .../resources/guides/python-guides/app_commands.md | 49 +++++++++++----------- 1 file changed, 25 insertions(+), 24 deletions(-) diff --git a/pydis_site/apps/content/resources/guides/python-guides/app_commands.md b/pydis_site/apps/content/resources/guides/python-guides/app_commands.md index c319ebb1..ed6b24cd 100644 --- a/pydis_site/apps/content/resources/guides/python-guides/app_commands.md +++ b/pydis_site/apps/content/resources/guides/python-guides/app_commands.md @@ -2,19 +2,19 @@ --- -Upon resumption of the most popular discord API wrapper library for python, `discord.py`, while catching on to the latest features of the discord API, there have been numerous changes with addition of features to the library. Some additions to the library are -> Buttons support, Select Menus Support, Forms (AKA Modals), Slash Commands (AKA Application Commands) and a bunch of more handy features! All the changes can be found [here](https://discordpy.readthedocs.io/en/latest/migrating.html). Original discord.py gist regarding resumation can be found [here](https://gist.github.com/Rapptz/c4324f17a80c94776832430007ad40e6). +Upon resumption of the most popular discord API wrapper library for python, `discord.py`, while catching on to the latest features of the discord API, there have been numerous changes with addition of features to the library. Some additions to the library are -> Buttons support, Select Menus Support, Forms (AKA Modals), Slash Commands (AKA Application Commands) and a bunch of more handy features! All the changes can be found [here](https://discordpy.readthedocs.io/en/latest/migrating.html). Original discord.py Gist regarding resumption can be found [here](https://Gist.github.com/Rapptz/c4324f17a80c94776832430007ad40e6). -# Why this gist? +# Why this Gist? --- This Gist is being created as an update to Slash Commands (app commands) with explanation and examples. This Gist mainly focuses on **SLASH COMMANDS** for discord.py 2.0 (and above)! -# What Are Slash Commands? +# What are Slash Commands? --- -Slash Commands are the exciting new way to build and interact with bots on Discord. With Slash Commands, all you have to do is type / and you're ready to use your favourite bot. You can easily see all the commands a bot has, and validation and error handling help you get the command right the first time. +Slash Commands are the exciting new way to build and interact with bots on Discord. As soon as you type "/", you can easily see all the commands a bot has. It also comes with autocomplete, validation and error handling, which will all help you get the command right the first time. # Install the latest version of discord.py @@ -22,27 +22,28 @@ Slash Commands are the exciting new way to build and interact with bots on Disco To use Slash Commands with discord.py. The latest up-to-date version has to be installed. Make sure that the version is 2.0 or above! And make sure to uninstall any third party libraries that support Slash Commands for discord.py (if any) as a few of them [monkey patch](https://en.wikipedia.org/wiki/Monkey_patch#:~:text=A%20monkey%20patch%20is%20a,running%20instance%20of%20the%20program) discord.py! -The latest and up-to-date usable discord.py version can be installed using `pip install -U git+https://github.com/Rapptz/discord.py`. +The latest and up-to-date usable discord.py version can be installed using `pip install -U discord.py`. If you get an error such as: `'git' is not recognized...`, it means that you don't have it installed on your platform. In that case, you will need to do do so by going through the required steps for [installing git](https://git-scm.com/downloads) and make sure to enable the `add to path` option while in the installation wizard. After installing git you can run `pip install -U discord.py` again to install discord.py 2.0. -If you get an error such as: `'git' is not recognized...`. [Install git](https://git-scm.com/downloads) for your platform. Go through the required steps for installing git and make sure to enable the `add to path` option while in the installation wizard. After installing git you can run `pip install -U git+https://github.com/Rapptz/discord.py` again to install discord.py 2.0. **BEFORE MIGRATING TO DISCORD.PY 2.0, PLEASE READ THE CONSEQUENCES OF THE UPDATE [HERE](https://discordpy.readthedocs.io/en/latest/migrating.html)**. -# Basic Structure for Discord.py Slash Commands! +# Basic structure for discord.py Slash Commands! --- ### Note that Slash Commands in discord.py are also referred to as **Application Commmands** and **App Commands** and every *interaction* is a *webhook*. Slash commands in discord.py are held by a container, [CommandTree](https://discordpy.readthedocs.io/en/latest/interactions/api.html?highlight=commandtree#discord.app_commands.CommandTree). A command tree is required to create Slash Commands in discord.py. This command tree provides a `command` method which decorates an asynchronous function indicating to discord.py that the decorated function is intended to be a slash command. This asynchronous function expects a default argument which acts as the interaction which took place that invoked the slash command. This default argument is an instance of the **Interaction** class from discord.py. Further up, the command logic takes over the behaviour of the slash command. -# Fundamentals for this gist! +# Fundamentals for this Gist! --- -The fundamental for this gist will remain to be the `setup_hook`. The `setup_hook` is a special asynchronous method of the Client and Bot classes which can be overwritten to perform numerous tasks. This method is safe to use as it is always triggered before any events are dispatched, i.e. this method is triggered before the *IDENTIFY* payload is sent to the discord gateway. +The fundamental for this Gist will remain to be the `setup_hook`. The `setup_hook` is a special asynchronous method of the Client and Bot classes which can be overwritten to perform numerous tasks. This method is safe to use as it is always triggered before any events are dispatched, i.e. this method is triggered before the *IDENTIFY* payload is sent to the discord gateway. Note that methods of the Bot class such as `change_presence` will not work in setup_hook as the current application does not have an active connection to the gateway at this point. -__**FOLLOWING IS THE EXAMPLE OF HOW A `SETUP_HOOK` FUNCTION CAN BE DEFINED**__ +__**THE FOLLOWING ARE EXAMPLES OF HOW A `SETUP_HOOK` FUNCTION CAN BE DEFINED**__ + +Note that the default intents are defined [here](https://discordpy.readthedocs.io/en/stable/api.html?highlight=discord%20intents%20default#discord.Intents.default) to have all intents enabled except presences, members, and message_content. ```python import discord @@ -67,7 +68,7 @@ client.setup_hook = my_setup_hook # Basic Slash Command application using discord.py. -#### The `CommandTree` class resides within the `app_commands` of discord.py package. +#### The `CommandTree` class resides within the `app_commands` of the discord.py package. --- ## Slash Command Application with a Client @@ -98,14 +99,14 @@ __**EXPLANATION**__ - `import discord` imports the **discord.py** package. - `class SlashClient(discord.Client)` is a class subclassing **Client**. Though there is no particular reason except readability to subclass the **Client** class, using the `Client.setup_hook = my_func` is equally valid. -- Next up `super().__init__(...)` runs the `__init__` function of the **Client** class, this is equivalent to `discord.Client(...)`. Then, `self.tree = discord.app_commands.CommandTree(self)` creates a CommandTree which acts as the container for slash commaands. -- Then in the `setup_hook`, `self.tree.copy_global_to(...)` adds the slash command to the guild of which the ID is provided as a `discord.Object` object. Further up, `self.tree.sync()` updates the API with any changes to the Slash Commands. +- Next up `super().__init__(...)` runs the `__init__` function of the **Client** class, this is equivalent to `discord.Client(...)`. Then, `self.tree = discord.app_commands.CommandTree(self)` creates a CommandTree which acts as the container for slash commands. +- Then in the `setup_hook`, `self.tree.copy_global_to(...)` adds the slash command to the guild of which the ID is provided as a `discord.Object` object. **Essential to creation of commands** Further up, `self.tree.sync()` updates the API with any changes to the Slash Commands. - Finishing up with the **Client** subclass, we create an instance of the subclassed Client class which here has been named as `SlashClient` with `client = SlashClient()`. - Then using the `command` method of the `CommandTree` we decorate a function with it as `client.tree` is an instance of `CommandTree` for the current application. The command function takes a default argument as said, which acts as the interaction that took place. Catching up is `await interaction.response.send_message("pong")` which sends back a message to the slash command invoker. - And the classic old `client.run("token")` is used to connect the client to the discord gateway. -- Note that the `send_message` is a method of the `InteractionResponse` class and `interaction.response` in this case is an instance of the `InteractionResponse` object. The `send_message` method will not function if the response is not sent within 3 seconds of command invocation. We will discuss how to handle this issue later following the gist. +- Note that the `send_message` is a method of the `InteractionResponse` class and `interaction.response` in this case is an instance of the `InteractionResponse` object. The `send_message` method will not function if the response is not sent within 3 seconds of command invocation. We will discuss how to handle this issue later following the Gist. -## Slash Command Application with a Bot +## Slash Command application with the Bot class ```python import discord @@ -131,7 +132,7 @@ The above example shows a basic Slash Commands within discord.py using the Bot c __**EXPLANATION**__ -Most of the explanation is the same as the prior example which featured `SlashClient` which was a subclass of **discord.Client**. Though some minor changes are discussed below. +Most of the explanation is the same as the prior example that featured `SlashClient` which was a subclass of **discord.Client**. Though some minor changes are discussed below. - The `SlashBot` class now subclasses `discord.ext.commands.Bot` following the passing in of the required arguments to its `__init__` method. - `discord.ext.commands.Bot` already consists of an instance of the `CommandTree` class which can be accessed using the `tree` property. @@ -173,7 +174,7 @@ bot.run("token") __**EXPLANATION**__ -- Firstly, `import discord` imports the **discord.py** package. `from discord import app_commands` imports the `app_commands` directory from the **discord.py** root directory. `from discord.ext import commands` imports the commands extension. +- Firstly, `import discord` imports the **discord.py** package. `from discord import app_commands` imports the `app_commands` module from the **discord.py** root module. `from discord.ext import commands` imports the commands extension. - Further up, `class MySlashCog(commands.Cog)` is a class subclassing the `Cog` class. You can read more about this [here](https://discordpy.readthedocs.io/en/latest/ext/commands/cogs.html#ext-commands-cogs). - `def __init__(self, bot: commands.Bot): self.bot = bot` is the constructor method of the class that is always run when the class is instantiated and that is why we pass in a **Bot** object whenever we create an instance of the cog class. - Following up is the `@app_commands.command(name="ping", description="...")` decorator. This decorator basically functions the same as a `bot.tree.command` but since the cog currently does not have a **bot**, the `app_commands.command` decorator is used instead. The next two lines follow the same structure for Slash Commands with **self** added as the first parameter to the function as it is a method of a class. @@ -223,7 +224,7 @@ bot.run("token") ``` __**EXPLANATION**__ -- The only difference used here is `group = app_commands.Group(name="uwu", description="...")` and `group.command`. `app_commands.Group` is used to initiate a group while `group.command` registers a command under a group. For example, the ping command can be run using **/ping** but this is not the case for group commands. They are registered with the format of `group_name command_name`. So here, the **command** command of the **uwu** group would be run using **/uwu command**. Note that only group commands can have a single space between them. +- The only difference used here is `group = app_commands.Group(name="uwu", description="...")` and `group.command`. `app_commands.Group` is used to initiate a group while `group.command` reGisters a command under a group. For example, the ping command can be run using **/ping** but this is not the case for group commands. They are reGistered with the format of `group_name command_name`. So here, the **command** command of the **uwu** group would be run using **/uwu command**. Note that only group commands can have a single space between them. --- @@ -262,7 +263,7 @@ bot.run("token") ``` __**EXPLANATION**__ -- The only difference here too is that the `MySlashGroup` class directly subclasses the **Group** class from discord.app_commands which automatically registers all the methods within the group class to be commands of that specific group. So now, the commands such as `ping` can be run using **/uwu ping** and `command` using **/uwu command**. +- The only difference here too is that the `MySlashGroup` class directly subclasses the **Group** class from discord.app_commands which automatically reGisters all the methods within the group class to be commands of that specific group. So now, the commands such as `ping` can be run using **/uwu ping** and `command` using **/uwu command**. # Some common methods and features used for Slash Commands. @@ -282,7 +283,7 @@ bot = commands.Bot(command_prefix=".", intents=discord.Intents.default()) @bot.tree.command(name="echo", description="...") @app_commands.describe(text="The text to send!", channel="The channel to send the message in!") async def _echo(interaction: discord.Interaction, text: str, channel: discord.TextChannel=None): - channel = interaction.channel or channel + channel = channel or interaction.channel await channel.send(text) ``` @@ -327,7 +328,7 @@ async def _ping(interaction: discord.Interaction): ``` -If the check fails, it will raise a `MissingPermissions` error which can be handled within an app commands error handler! We will discuss making an error handler later in the gist. All the permissions can be found [here](https://discordpy.readthedocs.io/en/latest/api.html?highlight=discord%20permissions#discord.Permissions). +If the check fails, it will raise a `MissingPermissions` error which can be handled within an app commands error handler! We will discuss making an error handler later in the Gist. All the permissions can be found [here](https://discordpy.readthedocs.io/en/latest/api.html?highlight=discord%20permissions#discord.Permissions). Other methods that you can decorate the commands with are - - `bot_has_permissions` | This checks if the bot has the required permissions for executing the slash command. This raises a [BotMissingPermissions](https://discordpy.readthedocs.io/en/latest/interactions/api.html?highlight=app_commands%20checks%20has_role#discord.app_commands.BotMissingPermissions) exception. @@ -339,7 +340,7 @@ Other methods that you can decorate the commands with are - --- -Slash Commands within discord.py can be applied cooldowns to in order to prevent spamming of the commands. This can be done through the `discord.app_commands.checks.cooldown` method which can be used to decorate a slash command function and register a cooldown to the function. This raises a [CommandOnCooldown](https://discordpy.readthedocs.io/en/latest/interactions/api.html?highlight=checks%20cooldown#discord.app_commands.CommandOnCooldown) exception if the command is currently on cooldown. +Slash Commands within discord.py can be applied cooldowns to in order to prevent spamming of the commands. This can be done through the `discord.app_commands.checks.cooldown` method which can be used to decorate a slash command function and reGister a cooldown to the function. This raises a [CommandOnCooldown](https://discordpy.readthedocs.io/en/latest/interactions/api.html?highlight=checks%20cooldown#discord.app_commands.CommandOnCooldown) exception if the command is currently on cooldown. An example is as follows. ```python @@ -369,9 +370,9 @@ bot.run("token") ``` __**EXPLANATION**__ -- The first argument the `cooldown` method takes is the number of times this command can be invoked in a particular unit of time (Which will be defined in the following argument). +- The first argument is the number of times this command can be invoked before the cooldown is triggered. - The second argument it takes is the period of time in which the command can be run the specified number of times. -- The `CommandOnCooldown` exception can be handled using an error handler. We will discuss making an error handler for Slash Commands later in the gist. +- The `CommandOnCooldown` exception can be handled using an error handler. We will discuss making an error handler for Slash Commands later in the Gist. # Handling errors for Slash Commands! -- cgit v1.2.3