How To Register My Discord Bot
Lookout Now This tutorial has a related video course created by the Real Python team. Lookout it together with the written tutorial to deepen your understanding: Creating a Discord Bot in Python
In a globe where video games are so important to then many people, communication and community around games are vital. Discord offers both of those and more in one well-designed packet. In this tutorial, you'll learn how to brand a Discord bot in Python so that y'all tin make the most of this fantastic platform.
By the terminate of this article you'll learn:
- What Discord is and why it's and so valuable
- How to make a Discord bot through the Programmer Portal
- How to create Discord connections
- How to handle events
- How to take commands and validate assumptions
- How to interact with various Discord APIs
You'll begin by learning what Discord is and why it'south valuable.
What Is Discord?
Discord is a vocalism and text communication platform for gamers.
Players, streamers, and developers use Discord to discuss games, respond questions, chat while they play, and much more. It even has a game shop, complete with disquisitional reviews and a subscription service. It is almost a 1-stop shop for gaming communities.
While at that place are many things you lot can build using Discord'southward APIs, this tutorial will focus on a item learning effect: how to make a Discord bot in Python.
What Is a Bot?
Discord is growing in popularity. Equally such, automated processes, such every bit banning inappropriate users and reacting to user requests are vital for a community to thrive and grow.
Automatic programs that expect and act like users and automatically respond to events and commands on Discord are called bot users. Discord bot users (or just bots) take well-nigh unlimited applications.
For example, let's say you lot're managing a new Discord guild and a user joins for the very first fourth dimension. Excited, yous may personally attain out to that user and welcome them to your customs. You might as well tell them about your channels or ask them to introduce themselves.
The user feels welcomed and enjoys the discussions that happen in your social club and they, in plough, invite friends.
Over fourth dimension, your community grows so large that information technology'southward no longer feasible to personally attain out to each new member, but you all the same want to send them something to recognize them equally a new member of the social club.
With a bot, it's possible to automatically react to the new member joining your gild. You can even customize its behavior based on context and control how it interacts with each new user.
This is great, only information technology'south simply one pocket-sized example of how a bot can be useful. At that place are so many opportunities for you lot to exist artistic with bots, once you know how to make them.
At that place are two key steps when y'all're creating a bot:
- Create the bot user on Discord and annals it with a guild.
- Write code that uses Discord'southward APIs and implements your bot's behaviors.
In the next section, you'll learn how to brand a Discord bot in Discord's Developer Portal.
How to Make a Discord Bot in the Developer Portal
Before you can dive into any Python code to handle events and create heady automations, you need to starting time create a few Discord components:
- An account
- An application
- A bot
- A social club
You'll larn more almost each piece in the post-obit sections.
Once you've created all of these components, you'll tie them together by registering your bot with your gild.
You tin become started past heading to Discord'south Developer Portal.
Creating a Discord Account
The first matter you'll meet is a landing folio where yous'll demand to either login, if yous have an existing account, or create a new business relationship:
If you lot need to create a new business relationship, then click on the Annals button below Login and enter your business relationship information.
One time you're finished, you'll be redirected to the Developer Portal habitation page, where you'll create your application.
Creating an Application
An application allows you lot to interact with Discord'southward APIs by providing authentication tokens, designating permissions, and so on.
To create a new awarding, select New Application:
Next, yous'll be prompted to proper name your awarding. Select a name and click Create:
Congratulations! You made a Discord application. On the resulting screen, y'all tin can encounter information almost your application:
Keep in listen that any program that interacts with Discord APIs requires a Discord application, non just bots. Bot-related APIs are only a subset of Discord's total interface.
However, since this tutorial is well-nigh how to make a Discord bot, navigate to the Bot tab on the left-hand navigation list.
Creating a Bot
Equally you lot learned in the previous sections, a bot user is one that listens to and automatically reacts to certain events and commands on Discord.
For your code to actually be manifested on Discord, you'll need to create a bot user. To do so, select Add Bot:
Once you confirm that you want to add the bot to your application, y'all'll see the new bot user in the portal:
Notice that, by default, your bot user will inherit the name of your application. Instead, update the username to something more than bot-like, such as RealPythonTutorialBot, and Salvage Changes:
Now, the bot'south all gear up and ready to go, merely to where?
A bot user is not useful if it's not interacting with other users. Adjacent, you lot'll create a guild so that your bot can interact with other users.
Creating a Club
A guild (or a server, as it is oftentimes chosen in Discord's user interface) is a specific group of channels where users congregate to chat.
For example, say you want to create a space where users can come together and talk almost your latest game. You'd start by creating a lodge. Then, in your guild, you lot could have multiple channels, such equally:
- Full general Discussion: A channel for users to talk about whatsoever they want
- Spoilers, Beware: A channel for users who have finished your game to talk virtually all the terminate game reveals
- Announcements: A channel for you to announce game updates and for users to discuss them
Once you've created your gild, you'd invite other users to populate it.
And then, to create a order, head to your Discord abode page:
From this home page, you can view and add friends, direct messages, and guilds. From here, select the + icon on the left-manus side of the web page to Add a Server:
This will present ii options, Create a server and Join a Server. In this case, select Create a server and enter a name for your guild:
Once you lot've finished creating your society, you'll be able to see the users on the right-manus side and the channels on the left:
The last step on Discord is to register your bot with your new guild.
Adding a Bot to a Social club
A bot can't accept invites similar a normal user can. Instead, you lot'll add your bot using the OAuth2 protocol.
To do so, head dorsum to the Developer Portal and select the OAuth2 page from the left-hand navigation:
From this window, you'll see the OAuth2 URL Generator.
This tool generates an authorization URL that hits Discord's OAuth2 API and authorizes API admission using your application's credentials.
In this instance, yous'll desire to grant your application's bot user access to Discord APIs using your awarding'due south OAuth2 credentials.
To do this, roll down and select bot from the SCOPES options and Ambassador from BOT PERMISSIONS:
Now, Discord has generated your awarding's authorization URL with the selected scope and permissions.
Select Re-create abreast the URL that was generated for you, paste it into your browser, and select your guild from the dropdown options:
Click Authorize, and you're done!
If y'all go back to your society, then you'll meet that the bot has been added:
In summary, you've created:
- An application that your bot will use to authenticate with Discord's APIs
- A bot user that yous'll apply to interact with other users and events in your gild
- A guild in which your user account and your bot user will be active
- A Discord account with which you created everything else and that you lot'll use to interact with your bot
Now, you know how to make a Discord bot using the Developer Portal. Side by side comes the fun stuff: implementing your bot in Python!
How to Make a Discord Bot in Python
Since you're learning how to make a Discord bot with Python, you lot'll be using discord.py.
discord.py is a Python library that exhaustively implements Discord's APIs in an efficient and Pythonic style. This includes utilizing Python'due south implementation of Async IO.
Brainstorm by installing discord.py with pip:
$ pip install -U discord.py Now that you've installed discord.py, you'll use it to create your first connection to Discord!
Creating a Discord Connectedness
The first stride in implementing your bot user is to create a connection to Discord. With discord.py, you lot do this past creating an instance of Client:
# bot.py import os import discord from dotenv import load_dotenv load_dotenv () TOKEN = bone . getenv ( 'DISCORD_TOKEN' ) client = discord . Client () @customer . effect async def on_ready (): impress ( f ' { client . user } has connected to Discord!' ) client . run ( TOKEN ) A Client is an object that represents a connection to Discord. A Client handles events, tracks state, and generally interacts with Discord APIs.
Here, yous've created a Customer and implemented its on_ready() upshot handler, which handles the event when the Client has established a connectedness to Discord and it has finished preparing the data that Discord has sent, such as login state, lodge and channel data, and more.
In other words, on_ready() will be chosen (and your message volition be printed) once customer is ready for further action. You'll learn more than about event handlers subsequently in this article.
When you're working with secrets such every bit your Discord token, it's good practice to read it into your program from an environment variable. Using environment variables helps you lot:
- Avoid putting the secrets into source control
- Use different variables for development and product environments without irresolute your code
While you could export DISCORD_TOKEN={your-bot-token}, an easier solution is to save a .env file on all machines that will be running this code. This is non only easier, since y'all won't have to export your token every fourth dimension you clear your shell, just it as well protects you lot from storing your secrets in your shell'due south history.
Create a file named .env in the same directory as bot.py:
# .env DISCORD_TOKEN={your-bot-token} You'll need to supercede {your-bot-token} with your bot's token, which you can become past going dorsum to the Bot page on the Developer Portal and clicking Re-create under the TOKEN section:
Looking back at the bot.py lawmaking, you'll notice a library called dotenv. This library is handy for working with .env files. load_dotenv() loads environs variables from a .env file into your shell's environment variables so that y'all can apply them in your code.
Install dotenv with pip:
$ pip install -U python-dotenv Finally, client.run() runs your Client using your bot'south token.
Now that you've set both bot.py and .env, you lot can run your lawmaking:
$ python bot.py RealPythonTutorialBot#9643 has connected to Discord! Great! Your Customer has continued to Discord using your bot's token. In the next department, you'll build on this Customer by interacting with more Discord APIs.
Interacting With Discord APIs
Using a Client, you take access to a broad range of Discord APIs.
For instance, let's say you wanted to write the name and identifier of the guild that you registered your bot user with to the console.
First, you lot'll need to add together a new environment variable:
# .env DISCORD_TOKEN={your-bot-token} DISCORD_GUILD={your-order-name} Don't forget that you lot'll need to supercede the 2 placeholders with actual values:
-
{your-bot-token} -
{your-guild-name}
Retrieve that Discord calls on_ready(), which y'all used earlier, in one case the Client has fabricated the connection and prepared the information. So, you can rely on the club information being bachelor inside on_ready():
# bot.py import os import discord from dotenv import load_dotenv load_dotenv () TOKEN = os . getenv ( 'DISCORD_TOKEN' ) Social club = bone . getenv ( 'DISCORD_GUILD' ) client = discord . Client () @customer . event async def on_ready (): for society in client . guilds : if order . proper noun == Gild : break print ( f ' { client . user } is connected to the following lodge: \north ' f ' { club . name } (id: { guild . id } )' ) client . run ( TOKEN ) Here, you looped through the social club data that Discord has sent client, namely client.guilds. And so, you found the guild with the matching proper noun and printed a formatted string to stdout.
Run the program to see the results:
$ python bot.py RealPythonTutorialBot#9643 is connected to the following society: RealPythonTutorialServer(id: 571759877328732195) Great! Yous can encounter the proper noun of your bot, the proper noun of your server, and the server's identification number.
Some other interesting chip of data you lot tin pull from a club is the list of users who are members of the gild:
# bot.py import bone import discord from dotenv import load_dotenv load_dotenv () TOKEN = os . getenv ( 'DISCORD_TOKEN' ) GUILD = os . getenv ( 'DISCORD_GUILD' ) client = discord . Client () @customer . event async def on_ready (): for gild in customer . guilds : if gild . name == Guild : break print ( f ' { client . user } is continued to the post-obit guild: \n ' f ' { guild . proper noun } (id: { society . id } ) \n ' ) members = ' \n - ' . join ([ fellow member . name for member in guild . members ]) print ( f 'Guild Members: \due north - { members } ' ) client . run ( TOKEN ) By looping through guild.members, you pulled the names of all of the members of the guild and printed them with a formatted cord.
When yous run the plan, you should see at to the lowest degree the name of the business relationship yous created the guild with and the name of the bot user itself:
$ python bot.py RealPythonTutorialBot#9643 is connected to the following guild: RealPythonTutorialServer(id: 571759877328732195) Lodge Members: - aronq2 - RealPythonTutorialBot These examples barely scratch the surface of the APIs available on Discord, exist sure to cheque out their documentation to see all that they have to offering.
Next, you'll learn about some utility functions and how they tin can simplify these examples.
Using Utility Functions
Let's take another look at the example from the last section where you printed the proper name and identifier of the bot's social club:
# bot.py import os import discord from dotenv import load_dotenv load_dotenv () TOKEN = bone . getenv ( 'DISCORD_TOKEN' ) GUILD = bone . getenv ( 'DISCORD_GUILD' ) client = discord . Client () @client . result async def on_ready (): for club in client . guilds : if club . name == Club : suspension print ( f ' { customer . user } is connected to the following guild: \northward ' f ' { guild . name } (id: { guild . id } )' ) client . run ( TOKEN ) You could clean up this code past using some of the utility functions bachelor in discord.py.
discord.utils.find() is one utility that can meliorate the simplicity and readability of this code by replacing the for loop with an intuitive, abstracted function:
# bot.py import os import discord from dotenv import load_dotenv load_dotenv () TOKEN = os . getenv ( 'DISCORD_TOKEN' ) GUILD = os . getenv ( 'DISCORD_GUILD' ) client = discord . Client () @client . event async def on_ready (): gild = discord . utils . notice ( lambda 1000 : grand . name == Order , client . guilds ) print ( f ' { client . user } is continued to the post-obit society: \n ' f ' { guild . name } (id: { guild . id } )' ) client . run ( TOKEN ) discover() takes a function, called a predicate, which identifies some characteristic of the element in the iterable that you're looking for. Here, y'all used a particular type of anonymous part, called a lambda, as the predicate.
In this case, you're trying to discover the guild with the same name equally the i you lot stored in the DISCORD_GUILD environment variable. In one case find() locates an chemical element in the iterable that satisfies the predicate, information technology volition return the element. This is substantially equivalent to the break argument in the previous example, but cleaner.
discord.py has fifty-fifty bathetic this concept i step further with the become() utility:
# bot.py import os import discord from dotenv import load_dotenv load_dotenv () TOKEN = bone . getenv ( 'DISCORD_TOKEN' ) GUILD = os . getenv ( 'DISCORD_GUILD' ) client = discord . Client () @client . event async def on_ready (): guild = discord . utils . go ( client . guilds , name = Lodge ) print ( f ' { client . user } is connected to the following guild: \n ' f ' { guild . name } (id: { guild . id } )' ) customer . run ( TOKEN ) get() takes the iterable and some keyword arguments. The keyword arguments represent attributes of the elements in the iterable that must all be satisfied for get() to render the element.
In this example, you've identified name=Order equally the attribute that must be satisfied.
Now that you've learned the basics of interacting with APIs, you'll dive a petty deeper into the function that you lot've been using to access them: on_ready().
Responding to Events
You already learned that on_ready() is an result. In fact, you might have noticed that it is identified as such in the code past the client.event decorator.
Just what is an outcome?
An issue is something that happens on Discord that you tin can use to trigger a reaction in your lawmaking. Your code will listen for and so respond to events.
Using the example you've seen already, the on_ready() event handler handles the result that the Client has fabricated a connection to Discord and prepared its response information.
So, when Discord fires an event, discord.py will route the event data to the corresponding event handler on your continued Customer.
There are two means in discord.py to implement an consequence handler:
- Using the
client.outcomedecorator - Creating a subclass of
Customerand overriding its handler methods
You already saw the implementation using the decorator. Adjacent, take a look at how to subclass Client:
# bot.py import os import discord from dotenv import load_dotenv load_dotenv () TOKEN = os . getenv ( 'DISCORD_TOKEN' ) class CustomClient ( discord . Client ): async def on_ready ( cocky ): print ( f ' { self . user } has connected to Discord!' ) client = CustomClient () customer . run ( TOKEN ) Here, just like before, yous've created a client variable and chosen .run() with your Discord token. The actual Client is unlike, however. Instead of using the normal base of operations class, client is an example of CustomClient, which has an overridden on_ready() part.
At that place is no difference between the 2 implementation styles of events, just this tutorial will primarily employ the decorator version because it looks similar to how you implement Bot commands, which is a topic you'll cover in a bit.
Now that you've learned how to create an event handler, let's walk through some different examples of handlers you can create.
Welcoming New Members
Previously, you saw the example of responding to the event where a member joins a guild. In that instance, your bot user could send them a bulletin, welcoming them to your Discord community.
At present, yous'll implement that behavior in your Client, using event handlers, and verify its behavior in Discord:
# bot.py import bone import discord from dotenv import load_dotenv load_dotenv () TOKEN = os . getenv ( 'DISCORD_TOKEN' ) client = discord . Client () @customer . event async def on_ready (): impress ( f ' { client . user . name } has continued to Discord!' ) @customer . effect async def on_member_join ( member ): expect fellow member . create_dm () await fellow member . dm_channel . send ( f 'Hi { fellow member . name } , welcome to my Discord server!' ) customer . run ( TOKEN ) Like before, you handled the on_ready() event past printing the bot user's proper noun in a formatted cord. New, however, is the implementation of the on_member_join() event handler.
on_member_join(), as its name suggests, handles the result of a new member joining a guild.
In this example, you used member.create_dm() to create a direct message channel. Then, you used that channel to .send() a direct message to that new member.
Now, let's examination out your bot's new behavior.
First, run your new version of bot.py and wait for the on_ready() event to fire, logging your bulletin to stdout:
$ python bot.py RealPythonTutorialBot has continued to Discord! Now, head over to Discord, log in, and navigate to your guild by selecting it from the left-hand side of the screen:
Select Invite People just beside the guild list where y'all selected your guild. Check the box that says Set this link to never expire and copy the link:
Now, with the invite link copied, create a new account and join the guild using your invite link:
Beginning, you'll come across that Discord introduced you to the guild by default with an automated message. More importantly though, discover the badge on the left-hand side of the screen that notifies you of a new message:
When you select it, yous'll encounter a private message from your bot user:
Perfect! Your bot user is now interacting with other users with minimal code.
Next, you lot'll learn how to respond to specific user messages in the chat.
Responding to Letters
Permit'southward add on to the previous functionality of your bot by handling the on_message() event.
on_message() occurs when a bulletin is posted in a channel that your bot has access to. In this example, yous'll answer to the bulletin '99!' with a one-liner from the television show Brooklyn Ix-Nine:
@client . event async def on_message ( message ): if message . author == client . user : return brooklyn_99_quotes = [ 'I \' m the human being grade of the 💯 emoji.' , 'Bingpot!' , ( 'Absurd. Cool cool cool cool cool cool absurd, ' 'no dubiousness no doubt no doubtfulness no doubt.' ), ] if message . content == '99!' : response = random . choice ( brooklyn_99_quotes ) await message . aqueduct . send ( response ) The majority of this event handler looks at the bulletin.content, checks to see if it's equal to '99!', and responds by sending a random quote to the message'due south aqueduct if it is.
The other piece is an important i:
if message . writer == customer . user : render Because a Client can't tell the difference between a bot user and a normal user business relationship, your on_message() handler should protect against a potentially recursive case where the bot sends a message that information technology might, itself, handle.
To illustrate, allow'south say you want your bot to listen for users telling each other 'Happy Birthday'. You could implement your on_message() handler like this:
@client . effect async def on_message ( bulletin ): if 'happy birthday' in bulletin . content . lower (): look message . aqueduct . send ( 'Happy Birthday! 🎈🎉' ) Bated from the potentially spammy nature of this result handler, it also has a devastating side effect. The message that the bot responds with contains the same message it'south going to handle!
Then, if 1 person in the channel tells another "Happy Birthday," so the bot will also chime in… again… and again… and again:
That's why it's important to compare the message.author to the client.user (your bot user), and ignore whatsoever of its own messages.
And then, permit's set up bot.py:
# bot.py import bone import random import discord from dotenv import load_dotenv load_dotenv () TOKEN = os . getenv ( 'DISCORD_TOKEN' ) client = discord . Client () @customer . event async def on_ready (): print ( f ' { customer . user . name } has connected to Discord!' ) @client . outcome async def on_member_join ( member ): look member . create_dm () await member . dm_channel . send ( f 'Hi { fellow member . name } , welcome to my Discord server!' ) @client . consequence async def on_message ( message ): if message . author == customer . user : render brooklyn_99_quotes = [ 'I \' m the man form of the 💯 emoji.' , 'Bingpot!' , ( 'Cool. Absurd cool cool cool cool cool cool, ' 'no incertitude no doubt no doubt no dubiousness.' ), ] if message . content == '99!' : response = random . choice ( brooklyn_99_quotes ) wait message . channel . send ( response ) customer . run ( TOKEN ) Don't forget to import random at the top of the module, since the on_message() handler utilizes random.pick().
Run the program:
$ python bot.py RealPythonTutorialBot has connected to Discord! Finally, head over to Discord to examination it out:
Bully! At present that you've seen a few different means to handle some common Discord events, you lot'll acquire how to deal with errors that event handlers may raise.
Handling Exceptions
As you've seen already, discord.py is an effect-driven system. This focus on events extends even to exceptions. When i event handler raises an Exception, Discord calls on_error().
The default behavior of on_error() is to write the error message and stack trace to stderr. To exam this, add a special bulletin handler to on_message():
# bot.py import os import random import discord from dotenv import load_dotenv load_dotenv () TOKEN = os . getenv ( 'DISCORD_TOKEN' ) client = discord . Client () @customer . event async def on_ready (): impress ( f ' { customer . user . proper noun } has connected to Discord!' ) @client . outcome async def on_member_join ( member ): await member . create_dm () wait member . dm_channel . send ( f 'Howdy { member . name } , welcome to my Discord server!' ) @client . event async def on_message ( message ): if bulletin . author == customer . user : return brooklyn_99_quotes = [ 'I \' m the human form of the 💯 emoji.' , 'Bingpot!' , ( 'Cool. Cool cool absurd cool cool absurd cool, ' 'no dubiety no dubiousness no doubt no doubt.' ), ] if message . content == '99!' : response = random . choice ( brooklyn_99_quotes ) await bulletin . channel . ship ( response ) elif message . content == 'raise-exception' : raise discord . DiscordException client . run ( TOKEN ) The new heighten-exception message handler allows you to raise a DiscordException on command.
Run the programme and blazon raise-exception into the Discord channel:
You should now see the Exception that was raised by your on_message() handler in the console:
$ python bot.py RealPythonTutorialBot has connected to Discord! Ignoring exception in on_message Traceback (near recent phone call final): File "/Users/alex.ronquillo/.pyenv/versions/discord-venv/lib/python3.vii/site-packages/discord/client.py", line 255, in _run_event await coro(*args, **kwargs) File "bot.py", line 42, in on_message raise discord.DiscordException discord.errors.DiscordException The exception was caught by the default error handler, and then the output contains the message Ignoring exception in on_message. Let'due south set that by treatment that particular mistake. To practice so, you'll catch the DiscordException and write it to a file instead.
The on_error() event handler takes the event as the first statement. In this instance, nosotros wait the outcome to be 'on_message'. It too accepts *args and **kwargs equally flexible, positional and keyword arguments passed to the original event handler.
So, since on_message() takes a single argument, message, we expect args[0] to be the message that the user sent in the Discord channel:
@client . outcome async def on_error ( event , * args , ** kwargs ): with open ( 'err.log' , 'a' ) as f : if upshot == 'on_message' : f . write ( f 'Unhandled message: { args [ 0 ] } \n ' ) else : raise If the Exception originated in the on_message() result handler, you .write() a formatted string to the file err.log. If some other consequence raises an Exception, then we but want our handler to re-raise the exception to invoke the default behavior.
Run bot.py and send the raise-exception message again to view the output in err.log:
$ cat err.log Unhandled message: <Message id=573845548923224084 pinned=False author=<Member id=543612676807327754 name='alexronquillo' discriminator='0933' bot=False nick=None guild=<Guild id=571759877328732195 name='RealPythonTutorialServer' chunked=True>>> Instead of only a stack trace, y'all take a more informative error, showing the message that acquired on_message() to raise the DiscordException, saved to a file for longer persistence.
Now that yous have some experience handling different events and interacting with Discord APIs, you'll learn about a bracket of Client chosen Bot, which implements some handy, bot-specific functionality.
Connecting a Bot
A Bot is a subclass of Customer that adds a fiddling scrap of actress functionality that is useful when you lot're creating bot users. For example, a Bot tin can handle events and commands, invoke validation checks, and more.
Before yous get into the features specific to Bot, convert bot.py to use a Bot instead of a Customer:
# bot.py import bone import random from dotenv import load_dotenv # ane from discord.ext import commands load_dotenv () TOKEN = bone . getenv ( 'DISCORD_TOKEN' ) # 2 bot = commands . Bot ( command_prefix = '!' ) @bot . event async def on_ready (): print ( f ' { bot . user . proper name } has connected to Discord!' ) bot . run ( TOKEN ) As yous tin see, Bot can handle events the same way that Customer does. All the same, detect the differences between Customer and Bot:
-
Botis imported from thediscord.ext.commandsmodule. - The
Botinitializer requires acommand_prefix, which you'll learn more than near in the next section.
The extensions library, ext, offers several interesting components to assistance you create a Discord Bot. 1 such component is the Command.
Using Bot Commands
In general terms, a control is an order that a user gives to a bot and so that it will do something. Commands are different from events because they are:
- Arbitrarily defined
- Directly called by the user
- Flexible, in terms of their interface
In technical terms, a Control is an object that wraps a function that is invoked by a text command in Discord. The text control must start with the command_prefix, divers by the Bot object.
Let's take a wait at an old issue to better understand what this looks like:
# bot.py import os import random import discord from dotenv import load_dotenv load_dotenv () TOKEN = os . getenv ( 'DISCORD_TOKEN' ) customer = discord . Client () @client . event async def on_message ( message ): if message . author == client . user : return brooklyn_99_quotes = [ 'I \' k the homo form of the 💯 emoji.' , 'Bingpot!' , ( 'Cool. Cool cool cool absurd cool cool cool, ' 'no doubt no doubt no doubt no doubt.' ), ] if message . content == '99!' : response = random . choice ( brooklyn_99_quotes ) wait message . channel . send ( response ) client . run ( TOKEN ) Hither, you created an on_message() outcome handler, which receives the message string and compares it to a pre-defined option: '99!'.
Using a Command, you can convert this example to be more specific:
# bot.py import os import random from discord.ext import commands from dotenv import load_dotenv load_dotenv () TOKEN = os . getenv ( 'DISCORD_TOKEN' ) bot = commands . Bot ( command_prefix = '!' ) @bot . command ( name = '99' ) async def nine_nine ( ctx ): brooklyn_99_quotes = [ 'I \' thou the human form of the 💯 emoji.' , 'Bingpot!' , ( 'Cool. Absurd cool absurd absurd cool cool cool, ' 'no doubt no doubt no doubt no doubt.' ), ] response = random . choice ( brooklyn_99_quotes ) await ctx . send ( response ) bot . run ( TOKEN ) There are several important characteristics to understand near using Command:
-
Instead of using
bot.effectlike earlier, yous employbot.control(), passing the invocation command (name) as its argument. -
The function will now only be chosen when
!99is mentioned in chat. This is different than theon_message()event, which was executed any time a user sent a bulletin, regardless of the content. -
The command must be prefixed with the assertion betoken (
!) because that'south thecommand_prefixthat you defined in the initializer for yourBot. -
Any
Commandfunction (technically chosen acallback) must accept at least one parameter, calledctx, which is theContextsurrounding the invokedCommand.
A Context holds data such as the channel and guild that the user called the Control from.
Run the program:
With your bot running, you can now head to Discord to effort out your new command:
From the user's point of view, the applied difference is that the prefix helps formalize the command, rather than merely reacting to a particular on_message() event.
This comes with other great benefits every bit well. For example, you can invoke the !help control to see all the commands that your Bot handles:
If yous want to add a description to your command so that the assist message is more than informative, simply pass a assist clarification to the .command() decorator:
# bot.py import bone import random from discord.ext import commands from dotenv import load_dotenv load_dotenv () TOKEN = os . getenv ( 'DISCORD_TOKEN' ) bot = commands . Bot ( command_prefix = '!' ) @bot . command ( proper noun = '99' , help = 'Responds with a random quote from Brooklyn 99' ) async def nine_nine ( ctx ): brooklyn_99_quotes = [ 'I \' grand the homo grade of the 💯 emoji.' , 'Bingpot!' , ( 'Cool. Cool cool cool cool cool cool cool, ' 'no uncertainty no doubtfulness no incertitude no doubt.' ), ] response = random . pick ( brooklyn_99_quotes ) look ctx . send ( response ) bot . run ( TOKEN ) At present, when the user invokes the !help control, your bot volition present a description of your control:
Keep in heed that all of this functionality exists only for the Bot bracket, not the Customer superclass.
Command has another useful functionality: the ability to use a Converter to alter the types of its arguments.
Converting Parameters Automatically
Some other benefit of using commands is the ability to convert parameters.
Sometimes, you require a parameter to be a sure type, only arguments to a Control function are, by default, strings. A Converter lets you catechumen those parameters to the blazon that y'all expect.
For example, if you want to build a Command for your bot user to simulate rolling some dice (knowing what you've learned so far), y'all might define it like this:
@bot . command ( name = 'roll_dice' , help = 'Simulates rolling dice.' ) async def roll ( ctx , number_of_dice , number_of_sides ): dice = [ str ( random . choice ( range ( one , number_of_sides + 1 ))) for _ in range ( number_of_dice ) ] await ctx . transport ( ', ' . join ( dice )) You divers roll to take two parameters:
- The number of dice to roll
- The number of sides per dice
Then, you lot decorated information technology with .command() so that yous can invoke information technology with the !roll_dice command. Finally, you .send() the results in a bulletin back to the channel.
While this looks right, it isn't. Unfortunately, if you run bot.py, and invoke the !roll_dice command in your Discord aqueduct, you'll come across the post-obit mistake:
$ python bot.py Ignoring exception in control roll_dice: Traceback (well-nigh contempo call last): File "/Users/alex.ronquillo/.pyenv/versions/discord-venv/lib/python3.7/site-packages/discord/ext/commands/core.py", line 63, in wrapped ret = await coro(*args, **kwargs) File "bot.py", line 40, in coil for _ in range(number_of_dice) TypeError: 'str' object cannot exist interpreted as an integer The higher up exception was the direct cause of the following exception: Traceback (most contempo call last): File "/Users/alex.ronquillo/.pyenv/versions/discord-venv/lib/python3.7/site-packages/discord/ext/commands/bot.py", line 860, in invoke await ctx.command.invoke(ctx) File "/Users/alex.ronquillo/.pyenv/versions/discord-venv/lib/python3.7/site-packages/discord/ext/commands/core.py", line 698, in invoke await injected(*ctx.args, **ctx.kwargs) File "/Users/alex.ronquillo/.pyenv/versions/discord-venv/lib/python3.seven/site-packages/discord/ext/commands/core.py", line 72, in wrapped heighten CommandInvokeError(exc) from exc discord.ext.commands.errors.CommandInvokeError: Command raised an exception: TypeError: 'str' object cannot be interpreted as an integer In other words, range() tin't accept a str as an argument. Instead, information technology must be an int. While you could cast each value to an int, at that place is a better way: you tin can apply a Converter .
In discord.py, a Converter is defined using Python three's role annotations:
@bot . command ( name = 'roll_dice' , assistance = 'Simulates rolling dice.' ) async def roll ( ctx , number_of_dice : int , number_of_sides : int ): dice = [ str ( random . choice ( range ( 1 , number_of_sides + 1 ))) for _ in range ( number_of_dice ) ] await ctx . send ( ', ' . bring together ( dice )) You added : int annotations to the two parameters that you look to be of blazon int. Try the command again:
With that niggling alter, your command works! The difference is that you're now converting the command arguments to int, which makes them compatible with your function's logic.
Next, you'll larn nigh the Cheque object and how it tin can improve your commands.
Checking Command Predicates
A Cheque is a predicate that is evaluated before a Control is executed to ensure that the Context surrounding the Control invocation is valid.
In an before case, you did something similar to verify that the user who sent a bulletin that the bot handles was not the bot user, itself:
if message . author == customer . user : return The commands extension provides a cleaner and more usable mechanism for performing this kind of cheque, namely using Check objects.
To demonstrate how this works, presume y'all desire to support a control !create-channel <channel_name> that creates a new channel. Even so, you lot only desire to allow administrators the ability to create new channels with this control.
Showtime, you'll need to create a new member part in the admin. Go into the Discord guild and select the {Server Proper noun} → Server Settings menu:
So, select Roles from the left-hand navigation list:
Finally select the + sign next to ROLES and enter the proper name admin and select Save Changes:
At present, y'all've created an admin role that yous can assign to detail users. Adjacent, you'll update bot.py to Check the user'south function before allowing them to initiate the control:
# bot.py import bone import discord from discord.ext import commands from dotenv import load_dotenv load_dotenv () TOKEN = os . getenv ( 'DISCORD_TOKEN' ) bot = commands . Bot ( command_prefix = '!' ) @bot . command ( proper noun = 'create-channel' ) @commands . has_role ( 'admin' ) async def create_channel ( ctx , channel_name = 'real-python' ): order = ctx . guild existing_channel = discord . utils . get ( order . channels , proper noun = channel_name ) if not existing_channel : impress ( f 'Creating a new aqueduct: { channel_name } ' ) look guild . create_text_channel ( channel_name ) bot . run ( TOKEN ) In bot.py, you have a new Control function, called create_channel() which takes an optional channel_name and creates that channel. create_channel() is too decorated with a Cheque called has_role().
Y'all as well use discord.utils.get() to ensure that you don't create a channel with the same proper noun equally an existing channel.
If y'all run this program as information technology is and type !create-channel into your Discord channel, and so yous'll see the following mistake message:
$ python bot.py Ignoring exception in command create-channel: Traceback (nigh recent call last): File "/Users/alex.ronquillo/.pyenv/versions/discord-venv/lib/python3.7/site-packages/discord/ext/commands/bot.py", line 860, in invoke wait ctx.command.invoke(ctx) File "/Users/alex.ronquillo/.pyenv/versions/discord-venv/lib/python3.7/site-packages/discord/ext/commands/core.py", line 691, in invoke await cocky.gear up(ctx) File "/Users/alex.ronquillo/.pyenv/versions/discord-venv/lib/python3.vii/site-packages/discord/ext/commands/core.py", line 648, in fix await self._verify_checks(ctx) File "/Users/alex.ronquillo/.pyenv/versions/discord-venv/lib/python3.vii/site-packages/discord/ext/commands/core.py", line 598, in _verify_checks raise CheckFailure('The check functions for command {0.qualified_name} failed.'.format(self)) discord.ext.commands.errors.CheckFailure: The check functions for command create-channel failed. This CheckFailure says that has_role('admin') failed. Unfortunately, this error only prints to stdout. It would exist better to written report this to the user in the aqueduct. To practice so, add the following upshot:
@bot . event async def on_command_error ( ctx , error ): if isinstance ( mistake , commands . errors . CheckFailure ): await ctx . send ( 'Y'all practise non have the right part for this command.' ) This event handles an mistake event from the command and sends an informative error message back to the original Context of the invoked Control.
Try it all once more, and yous should run into an mistake in the Discord channel:
Bully! Now, to resolve the consequence, you'll need to requite yourself the admin function:
With the admin office, your user will pass the Check and will exist able to create channels using the command.
When you type !create-channel once more, yous'll successfully create the channel real-python:
Also, note that you tin pass the optional channel_name statement to name the channel to whatever you want!
With this terminal example, you combined a Command, an event, a Check, and even the get() utility to create a useful Discord bot!
Conclusion
Congratulations! Now, you've learned how to make a Discord bot in Python. Y'all're able to build bots for interacting with users in guilds that y'all create or fifty-fifty bots that other users can invite to interact with their communities. Your bots will exist able to answer to letters and commands and numerous other events.
In this tutorial, you learned the basics of creating your own Discord bot. Y'all now know:
- What Discord is
- Why
discord.pyis and so valuable - How to make a Discord bot in the Programmer Portal
- How to create a Discord connection in Python
- How to handle events
- How to create a
Botconnection - How to utilise bot commands, checks, and converters
To read more about the powerful discord.py library and take your bots to the next level, read through their extensive documentation. Also, now that you lot're familiar with Discord APIs in general, you have a better foundation for building other types of Discord applications.
Scout Now This tutorial has a related video course created by the Real Python team. Watch it together with the written tutorial to deepen your agreement: Creating a Discord Bot in Python
How To Register My Discord Bot,
Source: https://realpython.com/how-to-make-a-discord-bot-python/
Posted by: walterssweas1972.blogspot.com

0 Response to "How To Register My Discord Bot"
Post a Comment