Dovahzul Bot in Python

Welcome to the second post on the Dovahzul bot! This post will showcase my journey developing a bot with Python and discord.py. I used the latest version of Python at the time of this post, version 3.9. Other python 3 versions may or may not work. Python 2.x, which is now deprecated, certainly does not work. Before getting into the coding, like with Node, I need to setup a workspace.  If you are only interested in my thoughts on the difference between Node and Python, please skip to the last two sections of this post.

Python: Workspace

file tree


Visual Studio Code functions just as well with Python as it did with Node. There are a few key steps to create a Python project, some of which are similar to Node's set-up process. Since we do not want to install required Python modules globally, we need to instantiate a virtual environment (venv).We can create a venv following the documentation at https://docs.python.org/3/library/venv.html. Once a virtual environment is created in your root project directory, you then need to activate it by executing the activate file in venv/Scripts

activate virtual environment

In the Visual Studio Code terminal, you should be able to see the indicator that your are now working inside the venv

python vsc extension


You may want to install the Python extension if it is not installed already at this point within visual studio code. Since I was using the extension for the bot, I feel obligated to inform people of its existence.  I am not sure whether this extension is necessary to write Python scripts in Visual Studio Code. 

When working on a Python project, you typically should create a requirements.txt file to specify required modules. I have created a pastebin of this file which can be downloaded at https://pastebin.com/dl/cjHm2xpZ for your convivence. If you think I should include more pastebins or even a GitHub repo with all the bots let me know in the comments below. 


requirements.txt


install dependencies in virtual environment


After the requirements file is good to go, I installed the modules within the venv using the command py -3 -m pip install -r requirements.txt. As a sanity check you can run the command py -3 -m pip list to verify all your installed modules. 

Same as before with Node, please create a .env file in the root directory and enter any environment variables you need. The .env file will always remain in the root directory and be used for all bots I develop.

constants.py

One file lacking from the Node version was a file to store constants. This time around, I decided to create a constants.py file to store the prefix and URL for the translator API. Additionally, I created the main.py in the project root directory to begin writing the bulk of our bot.

lines 1-9, main.py


Using os and dotenv, I can load in the environment variables and store them directly into variables in Python.

Python: discord.py


Initially I define the intents using the factory method Intents.default(). Intents are needed to specify the permissions of the bot, and discord.py offers a selection of factory methods to generate it. We then pass the intents into the discord.py client factory method to create the client object. 

lines 11-13, main.py

While discord.js uses JavaScript event emitters, discord.py uses coroutine to handle events. Using the new keyword async and a @client.event decorator, I can define a client executable coroutine. Be careful not to confuse the Decorator design pattern with Python decorators. Visit https://wiki.python.org/moin/PythonDecorators if you desire a better understanding. 

lines 16-17, main.py

The names of the decorated client even methods must be exact. As depicted above I use discord.py's on_message (see https://discordpy.readthedocs.io/en/stable/api.html#discord.on_message) to process commands.  

lines 30-31, main.py

Using the await keyword (which functions similar to Java's yield), we can send a reply.  Before moving on to parsing commands, I went ahead and called the client.run method in the last line of code to start the client. I did this to ensure everything worked thus far. 

line 43, main.py

Python: Parsing Commands

We are nearly finished using discord.py! We just need to parse the commands, call the translator API, and send a reply.  Thankfully, parsing a string in Python is an easy task. Using the split() and str() function I can form an array which includes the command and arguments. From here I separate the command and arguments into their own variables.  


lines 16-29, main.py

Note: In line 28 I test whether the message was authored by itself or another bot to avoid infinite recursion! 


test command

Python: POST Request


Before making the request, I need to join the command arguments into a single string. The translation API will translate the given string. Using the requests module, I can make a POST request to the translation API without any hassle. 

lines 32-35, main.py


After providing the correct parameters, the request is returned as a JSON. Parsing the JSON in Python can be done in two lines of code. The JSON value we need is mapped to the key, "translated".

lines 36-39, main.py

Python: Results

basic translation


I can now successfully run the bot! Using the command py -3 -m main.py executes the main.py scripts we created. I did not test larger messages like with Node, however every message I sent worked flawlessly. 

Dovahzul: Python Vs. Node

As for my final thoughts on Python, I do not have much to share. Creating the workspace was a bit more tedious than Node, however writing the bot was about the same code-length wise. I think Node and Python are both solid choices for developing bots that require HTTP requests, but I believe Python to be slightly better. There is no need for knowledge of promises or convoluted axios parameter/header objects with Python. Despite the extra step with the virtual environment, I personally find Python superior for the development of bots that specifically need quick and simple HTTP requests. Perhaps using the fetch API rather than axios would have made NodeJS more or less equivalent. 

Future Plans

Next week I will create Dovahzul for the last time. We will see whether Java outmatches Python in the realm of bots! Originally I planned for every other post to cover multiple languages. I was unable to achieve this goal with Dovahzul due to significant "setting things up" portions. Hopefully Pokemon-TRPS will not consume 3 posts worth of information so I have time to work on the third bot. 

Comments