-
Notifications
You must be signed in to change notification settings - Fork 19
Discord.py Features and Functionalities
- Loading Commands
- How Help Messages are deleted
- How autocomplete functions work
- Slash Commands vs Text Commands
- Why no testing guild?
To start off, there is 2 different kinds of discord bot commands. text commands and slash commands
text commands mean command that is called with a prefix [or a character]. With the WALL_E command, this is a .
[aka dot commands]. The prefix is determined by the parameter command_prefix
this line
super().__init__(command_prefix='.', intents=intents, help_command=EmbedHelpCommand())
located here
When loading a text command, the text command is loaded into the discord.py framework only. Only your local discord.py that is running your bot knows what text commands you have loaded into it and subsequently are available in any discord guilds your bot is plugged into. None of the other running bots on the same guilds know what commands you have personally loaded, even if they are using the same Bot application's API token.
With a text commands, how they are loaded is like this:
- When you start up the bot, all the cogs [for example the class
Misc
in wall_e/extensions/misc.py] are loaded into the bot via this blob of code and this blob of code whereextension
is the python file wall_e/extensions/misc.py andcog
is the classMisc
itself. Furthermore, the text commands have this@commands.command
annotation and discord.py picks up on that when scanning the cog and as a result, it loads the text command. - when the bot is connected to the discord servers, all messages on all guilds that it is connected to [assuming it is given access to them] are received by the discord.py framework. What the discord.py framework then does, is it checks each message it receives from the guild and sees if it matches a loaded text command. For example sake, if you type in
.hello
, that will be parsed by the framework because it begins with.
but because there is no commandhello
, that will end up going throwing an error ofcommands.errors.CommandNotFound
which is just ignored here - So finally, let's say that
.poll
is invoked, your locally loaded discord.py framework recognizes it as a legit command so it tries to invoke the command. Now this might result in other errors, such as permissions missing [if the command is restricted to certain users] or arguments not being correct [if user called it wrong]. But that's basically how a text command works.
As opposed to text commands where only your local bot has any idea what commands it has made available, slash commands are different, they have a CommandTree
concept. How this shows itself is in 2 ways:
When a slash command is synced to the global CommandTree
[which will be explained below how that happens], that command is available in your personal DM with that bot. It's not guaranteed to act the same in the DM as it would in the guild since some commands may have guild specific code but it can at least be detected and invoked from your personal DM with the bot.
In addition, there is a guild command. A guild command is a command that a bot has synced with a specific guild's CommandTree
, it is not available on any other guild nor is it available in your personal DM with that bot.
All of WALL_e's slash commands are guild command synced specifically to the CSSS Discord Guild, this line is what is making all the slash commands into guild commands.
I made the decision to sync just to the guild and not also do global because I didn't have the time or patience to make sure all the commands are global compatible, meaning they can be invoked in DMs. Also, there was really no demand for that.
With both guild and global commands, the discord server is aware of those slash commands, just in different contexts. you can test to see which commands are registered by doing /
and the menu that comes up shows what slash commands are registered.
With syncing an application command, there are 2 steps:
- Loading the command into the bot itself.
- registering loaded command with discord
-
override the default
add_cog
command so that the guild_id is added in one centralized place rather than having to specify it in each class - sync the locally created
CommandTree
to a specific discord guild
in your cog class
async def setup(bot):
await bot.add_cog(Misc())
and have a text command that executes
await bot.tree.sync()
that you can run once the bot is up
in your cog class
async def setup(bot):
await bot.add_cog(Misc(guild = discord.Object(id=<guild_id>)))
and have a text command that executes
await bot.tree.sync(guild = discord.Object(id=<guild_id>))
that you can run once the bot is up
in your cog class
async def setup(bot):
await bot.add_cog(Misc())
and have a text command that executes
bot.tree.copy_global_to(guild=<GUILD_ID>)
await bot.tree.sync()
await bot.tree.sync(guild = discord.Object(id=<guild_id>))
that you can run once the bot is up