Andrew Hannon - Software Development Portfolio

Discord Bot

Links:

Github Repositiory

Languages/Tools Used:

Python
discord.py library
VS Code

Quick Summary

Developed a dynamic Discord bot using Python and the discord.py library, integrating multiple features to enhance user interaction and gameplay. Leveraged JSON databases for user and game data storage, and utilized environment variables for secure bot authentication and configuration.

Key Features

  • Event Handling: Automatically sends messages on user join/leave events, while updating JSON-based databases.
  • Commands: Developed interactive commands and command cooldown mechanism to limit spamming.
  • Trading System: Built a trade mechanism allowing users to offer and exchange characters through a secure, handshake-style interaction.
  • Battle Command: Designed a battle system where users engage in character battles based on random rolls and respective stats, with a points-based reward system that encourages strategic gameplay.
  • Profile System: Created a profile command that displays user information, including owned characters and points, with pagination support for large character collections.
The Goal

For this project I wanted to build an interactive Discord bot to exercise and grow my Python skills. Something with a satisfying list of features that would keep people engaged for a number of reasons. I ended up decided to make what is essentially a Seinfeld Trading Card Game bot. It included features such as randomly collecting characters from the show, trading them with other users on the server, battling them with other users, collecting points to buy more random characters, and being able to randomly generate a quote from the show.

What I learned

This project helped me gain deeper insights into the complexities of real-time systems and concurrent data handling, especially when multiple users are interacting with the bot at the same time. In a live environment, this bot would ideally be receiving different commands from multiple users in a short span of time, so I had to ensure data integrity with the user and character databases as multiple commands come in by utilizing asynchronous programming and data validation to make sure multiple commands could be handled at once. It also encouraged me to consider design decisions to help with this challenge such as cooldowns for commands to control command frequency and avoid user spamming.

How it was Built

To implement this bot I used Python. I also used the Discord.py library for setting up commands. I started with creating a bot application in Discord and adding it to a test server and giving it the proper permissions so that it isn’t restricted when performing commands. Then I used the bot’s token that is generated by discord to allow my python code to connect to it. I did this by storing two environment variables in a .env file, one for the token and one for the guild (discord server), then my code loads the .env file and uses these variables to connect.

The first feature I implemented was having the bot send a message when an event is triggered. For example, if a member joins or leaves the server, the bot will send a message stating as such. These events will also add and remove the user data from JSON databases.

The next feature I implemented was a simple command, so when a user types “!quote” it will generate a random quote from Seinfeld. I created a simple JSON database that stores a list of quotes and when a user sends the command the bot will spit back a message with one of these quotes randomly. The next command I created was the “roll” command. This will allow a user to type “!rs” and the bot will send a message with a random Seinfeld character from another JSON database file. The message will display the character name, some information about them, a battle stat, a picture, and if the character was claimed by a user in the server already. This command uses a cooldown so a user can only use it once every hour. This is to control spamming and to allow the bot to have more life and not have every character be claimed right away. The command also waits for a reaction for 10 seconds to allow any user to react with an emoji on the bot’s message to claim it. Once claimed it will store the character to the user’s list of characters in the users JSON database and also enter this information in the Seinfeld character database. There is another “roll” command that the user can utilize that doesn’t have a cooldown, but it will require 100 points to use. These points can be obtained from battling.

I then implemented the trade command. This one was tricky as it needed to utilize a handshake style interaction where one user initiates a trade offering a character for another and the user with the wanted character needs to respond for the trade to occur. So the initiating user types the command name (!trade) then follows it with the character they are offering in quotations then a space and then the character they are wanting in quotations (ex: !trade “Jerry Seinfeld” “Elaine Benes”), the bot then checks if the character being offered is indeed owned by the initiating user, if it’s not the bot will send a message and kill the command, if it is, then the bot will send a message saying the trade was initiated and wait for a reaction to that message from another user. There’s a 30 second timer on this so if no one reacts in that time the command will fail. If a user does react in that time the bot proceeds to check if that user owns the wanted character and sends a message and kills the command if they don’t, or sends a message saying the trade was successfully accepted if they do and then updates the appropriate databases to switch the ownership of the characters involved.

The battle command utilizes a similar technique to the trade command; someone initiates a battle with a character, bot checks if the user owns the character before proceeding, then another user needs to respond to have the battle occur. The difference here is the user that accepts the battle has to respond with a message detailing the character of theirs they are accepting the battle with. When a battle successfully occurs, the bot will randomly roll a number between 0 and the number of the characters’ respective battle stat. Whoever rolls the higher number wins the battle and points are awarded. If a user with a lower battle stat wins the battle they will gain more points, this was to curb users just selecting their most powerful character every battle.

The final command was the profile command that allows the user to view their profile (name, profile pic, list of characters and their points). If a player has more than 10 characters then there will be left arrow and right arrow buttons on the profile message that the user can click to cycle through the pages of characters they own. This command simply accesses the user database to obtain and display this information and continuously waits for a user to click the arrow buttons if they have more than 10 characters. And with that I have a fun trading card game bot!