Making a Cool Discord Bot in Python 3

Paul Jerome
Bad Programming
Published in
8 min readMar 25, 2018

--

Discord has a wonderful API that allows you to creates bots that can join Discord servers and channels and help manage as well as add extra functionality for it’s users.

In this tutorial I will show you how to make a basic Discord bot written in Python 3 that will be able to take handle custom commands using the discord.py package available through pip.

Step 1: Getting Setup

Having a good editor can make the process of writing and debugging code in any language much easier. Some good free editors that I have personally used are PyCharm Community Edition and Sublime Text 3.

You will also need to make sure that you have Python 3 installed on you computer. If you are on Windows you can download an installer from the following link.

You will also need to go to the Discord website and create your bot, add it to a server, and grant it permissions. This can be done at the following link.

The following eight pictures will guide you through setting up you bot and adding it to your Discord server.

Navigate to the link above and click on “My Apps”
Click on “New App”
Give you bot a name, a description, and an icon. These are what will be seen in Discord.
Make your new app a bot by clicking on “Create Bot User”
Make your bot public. You can also see you bot token here, we will need to copy this later.
Click on “Generate OAuth2 URL”
Check the “bot” box, Check the “Administrator” box, and then go the the link generated.
Finally, select the server that you would like to connect it to and click “Authorize”.

You should now be able to see your bot in the Discord server you added it too and it should have a little tag that says “Bot” next to it’s name.

Step 2: Starting the Code

Create a folder that you will use for bot and in it create a file called bot.py. We are going to start by adding the boilerplate code that is required.

But first we need to install discord.py with Python’s package manager called pip. You can do this by navigating to you Command Prompt in Windows and entering the following.

pip install discord.py

After this has completed successfully we can open our bot.py and begin. The code below imports the discord.py package that we just installed as well as creates our Discord client object that we will use to interact with the API. The token variable has our bot’s token that we copied earlier from the Discord developers page.

The client variable seen on line 4 is a Discord client object and will facilitate all the communication of the bot.

The on_ready() function above will be called when the bot starts and is connects to the API and will print the bot’s username, client ID, and the version of discord.py that is being used as seen beneath the try on line 12, 13, 14.

The on_message() function above will be called when ever a new message is posted in the Discord server and the message will be passed as the message variable seen entered as it’s only argument. As we have the function right now it will print that message to the console when received.

Try running this code, if it works you should see your bot’s username and client id printed in the console. If you go to the Discord channel that bot was added to and type a message you should see it appear in the console where you bot is running, you might also get an error directly after it which you can ignore for now.

Step 3: Building a Command Handler

So at this point our bot is able to read every message that is posted in it’s Discord server. To make this useful we need to implement some kind function that evaluates the messages that are posted. We can do this by making a command handler which will read each message, determine if a command is being called, and relay the appropriate response.

Although, before we make our command handler we have to decide on how we are going to organize our commands to make them easy to implement and visualize. My favorite way to do this in Python is by using dictionaries. Dictionaries allow us to define multiple labeled properties to a variable. An example is shown below.

The function above starting on line 2 will take in the parameters message, clients, and args. The variable message is an object with the details of the message, the client variable is also an object we need in the function to send messages with, the args variable is and array that will contain the arguments for function. This function will be used as a variable in our dictionary.

The Command Dictionary Parts

  1. trigger: is a string that will be what the command handler will look for.
  2. function: is a function that will be executed when it’s trigger is found.
  3. args_num: is an integer that marks the amount of args the function uses.
  4. args_name: is an array of strings that name the args for feedback purposes.
  5. description: is a string that describes what the command does.

We could just write an independent function that would handle these commands but there is a better way to do it, creating a class. This class will contain methods to add commands, store commands, and evaluate commands. The class would look like this…

The __init__(self, client) method will be called when the class is instantiated and will bind the client object to itself and create an array, self.commands, to store the commands.

The add_command(self, command) method simply adds the command dictionary that we designed earlier to the self.commands array.

The command_handler(self, message) method will be used to evaluate each message that is sent on the Discord server. It basically just sees if the message starts with a command trigger and if it does it executes it’s corresponding function. The following is a pseudo code breakdown of what the command handler is doing for each message posted in the server.

  1. Checks if the message starts with a command trigger, if it doesn’t it stops.
  2. If the message does start with a trigger if makes sure that the trigger is valid by comparing it to the command dictionary's trigger value, if it’s not it stops.
  3. If the trigger is valid it removes the trigger from the message string and splits it at the spaces making an array named args.
  4. Then it checks to see how many args the command’s function takes using the command dictionary's args_num value, if it’s zero it simply executes the function in the command dictionary’s function value. If the command needs more than zero args it makes sure that there are at least the required amount and it passes them to the command dictionary’s function.

Step 4: Bringing it all together

Below is what all this code would look like together and should be completely functional.

This bot should have a fully functioning !hello command that takes in one argument.

Step 5: Adding useful Functions & Examples

So what we have now is a functional “platform” to expand on. In this step I will demonstrate some of the more advanced things you could do with this setup and some ways to make it more user friendly.

Note: I removed the !hello command from earlier because it useless.

In this example I added two new commands, !commands and !ip.

The !commands command will list all the available commands and there descriptions.

The !ip command will take in an argument called IP/Domain and it uses the Free IP-API and the Python 3 requests package to query the API with the given Domain or IP and returns information from the API response. The Python 3 json package is also needed to turn the API response into a Python dictionary which we can work with.

Also if you notice, you also can use the Discord formatting markdown shown in the link below to style your outputs, the **text** will show up as bold in Discord. You can also use Unicode Symbols to mark new lines (\n).

At this point you can do allot. Any information you can get into Python (which is allot) you can style and print to the users. You can add allot of cool features just from using different API’s. Below are a couple other API’s that I have made commands with.

I was also able to make and !sql command using this setup that you could use to query a remote MySQL database with which I plan to make a guide on in the future.

Resources

All the code featured in this guide is available at my GitHub.

I highly recommenced reading more of the documentation on discord.py because it has allot more features than are touched on in this guide.

This is the documentation for the requests package that I used in the last example. You can read about making requests with custom headers which is required for some API’s (really simple).

This is a link to the API that I featured in the last example, the IP-API. This API is really useful, cool, and super easy to use but best of all free :)

Thanks for reading!

--

--