Skip to content

Project Summary

Mihai Stavila (stavilam) edited this page Nov 28, 2018 · 1 revision

Project Summary

For this Chat Bot project, we decided to create a fully functional multitasking Discord Bot that can perform various useful functions in multiple servers and channels for different users at the same time. For this to be possible, and our project result to be called a “true” Discord Bot, we started researching the Python asyncio library and coroutine functions work. While this took us some time, it was only the first step: programming for Discord is mainly done with JavaScript and C#, but we needed to write our code in Python.

Fortunately, there was a solution: discord.py, “an API wrapper for Discord written in Python” made by GitHub user Rapptz. This made our project more daunting, as now we had to learn how to code not only in asynchronous programming and have a good understanding of the Discord API, but also learn the discord.py documentation and constantly keep our code up to date with every new release while making sure Python and other libraries versions are compatible with it. After a few days of writing a few hundred lines of code, the new stable version for discord.py released, and we switched from 0.16 to 1.0 Rewrite (“v1.0 is one of the biggest breaking changes in the library due to a complete redesign. The amount of changes are so massive and long that for all intents and purposes, it is a completely new library.”). It was another obstacle we had to overcome, and this time there were no “tutorials” to learn from, only the documentation and help of other people on the discord.py server. After some time and effort, we became accustomed to this new version and could continue our progress.

After we switched all the @client.event to @commands.command decorators for improved performance and utility and converted all the code to v1.0 rewrite, we were ready to start the making of our “super bot” using new gained knowledge. However, we also needed a way to organise the code so that it’s easier to read, merge and work on the code at the same time. Splitting event coroutine functions into files and then calling them would be easy, however it wasn’t possible to do when it has a command decorator. Because of the added benefits of functions being commands, we couldn’t go back, and instead we focused on implementing Classes and import them into the main file as Extensions with the use of Cogs. This took us, once more, a good amount of time to learn how to use, but the feeling of success at the end was worth the effort.

Now we could have our main module contain only the important code which makes the bot run while importing extensions from the other modules, and another module which contains all the authentication tools and keys required for full functionality, for example the Bot Token, MySQL database credentials, API access keys etc. Functions were also separated in different modules by category, such as Games, Image Search, API Functions, Basic Functions and so on.

After making some basic functions such as repeating the user’s message, returning a random number, flipping a coin and rolling one or multiple dices, I also made a more complex letter guessing game in which the user attempts to find a random letter chosen by the bot by using the hints given. The user interacts with the bot in real time trying to guess correctly, and the results of each game are saved and can be viewed by the user, and it goes without saying that after thorough testing the game is bug-free and results can’t be exploited.

After finishing the Letter Guessing Game and gaining some good practice in the process, I wanted to use the Discord API more: functions which return information about any mentioned user in a Discord server (such as client ID, server join date, account creation date, top roles etc.) and server information (server creation date, total members, online members, admin etc.). This is also where I learned how to use Discord embeds, table-like objects which are used in most functions and are designed to help with formatting and readability.

With the basic Discord API functions implemented, it was time for that which I wanted to do ever since I started the project (but at that time, I didn’t know how): functions that use a website’s API to gain real-time information. Most guides for this would be in the Python library requests, but this wasn’t good enough for us because it was blocking, meaning that it isn’t compatible with asynchronous tasks, so it was immediately out of the question. Instead, learnt how to use aiohttp (an asynchronous HTTP Client/Server for asyncio and Python) to fetch data, and JSON (JavaScript Object Notation) to format the data and input it into Discord embeds.

The first command which I made using aiohttp and JSON was a simple IP function, which received information about the address, service provider and their closest location and other information about the internet service. This was later changed to be an admin-only command.

After that, I started working on the Weather and Time by city commands, which would return detailed information about the current weather or time in any city requested by the user. Following this was the dictionary command which could return the meaning for any word present in the Oxford Dictionaries database and find similar words if a typo is detected. Besides the definition in different contexts, you can also get synonyms and antonyms for a word, as well as example sentences in which the desired word is used, for multiple word classes. Formatting and embed building proved to be quite challenging when making the dictionary functions, since some words aren’t as documented as others.

The most recent function added was the Image Search command, which gets a picture from an image board such as Konachan.net (an anime wallpaper site) and sends it to the user through a Discord embed, along with the tags, rating, direct image and site post link. The user can choose the tags of the picture, and the bot will choose a random image from the board which contains those tags, e.g. “Nier:_Automata” or “Persona”. If no tags are given, a random image from the most recent posts is chosen. The function also includes a filter to prevent NSFW/Questionable content from appearing on SFW channels, however there still is a very small chance of posts being wrongly rated, but this is out of our control. Lastly, I’ve added a Command Error Handler which saves the important errors that occurred while the bot was running, while leaving out the unnecessary ones such as user input errors.

While I didn’t have time to fully implement the MySQL DB and YouTube/Soundcloud music functionality, I will keep working on it, as I’ve already added Simon to my Discord server, so while the project might be nearing its end, the development of this bot certainly hasn’t. I must also thank my friends on Discord for helping me test the bot (even when spamming the commands, which by the way is the reason I added cooldowns).

Overall, while this project proved to be very challenging, I truly believe that we have learned a lot in the process, not only the technical knowledge but also the mindset of overcoming obstacles which at first seem impossible to scale. With enough time and effort, and most importantly the right attitude, we have proven that even beginners like us can create something amazing if we put our minds to it.