Patrick Desjardins Blog

Patrick Desjardins picture from a conference

The Evolution of my Gaming Discord Bot Using Python

Posted on: 2025-01-02

I have been coding a Discord bot for about 6 months now in Python (see this introduction here). I have learned a lot about the Discord API, Python, and how to manage a bot. I wanted to share my experience with you. This post will cover few features with a glimpse of the code.

The Discord Bot Evolution

Inception

The bot's initial goal was to send a daily message and have people vote on the time they expected to play. For example, early every day, the bot creates a new message with one emoji per time, and users, throughout the day, vote for the hours they are available.

The First Iteration: Automate the User Schedule

Soon, I realized that many people do not plan, but I wanted to channel all the posts to reflect the server activity. Thus, I added a feature that checks the voice channels, collects who is playing, and automatically adds them to the time frame.

Discord Bot

The feature relies mostly on the Discord API, which allows for recurrent tasks.

HOUR_SEND_DAILY_MESSAGE = 7
local_tz = pytz.timezone("America/Los_Angeles")
time_send_daily_message = time(hour=HOUR_SEND_DAILY_MESSAGE, minute=0, second=0, tzinfo=local_tz)
#...
@tasks.loop(time=time_send_daily_message)
async def send_daily_question_to_all_guild_task(self):
    """
 Send only once every day the question for each guild who has the bot
 """
    print_log(f"Sending daily schedule message, current time {datetime.now()}")
    for guild in self.bot.guilds:
        await send_daily_question_to_a_guild(self.bot, guild)

Using the @task.loop removes a lot of headaches of managing recurrent tasks instead of using another asynchronous library.

Getting Statistic

The next natural step was to get a sense of who was playing, who was reducing their time, and other statistical information. I could understand better who to reach out to get some news or understand some dynamics in the group better. It was especially useful once the group reached above 100 members. I started saving the information into a SQLite database. Then, using Panda, I could load the data from a data range and start computing some statistics.

Most of the code looks like this one:

# Some fetching code:
data_user_activity: list[UserActivity] = fetch_all_user_activities(from_day, to_day)
data_user_id_name: Dict[int, UserInfo] = fetch_user_info()
users_by_weekday_dict: Dict[int, list[UserInfoWithCount]] = users_by_weekday(data_user_activity, data_user_id_name)
# Some matplotlib code here:
# ...

Admin Tools

Getting the latest database from the Raspberry PI to my local machine or updating the service running on my Raspberry PI was a pain. I added a few commands to the bot to help me with that. Then, the unit tests, coverage, and integration tests required other commands. Then, more statistic visualization required more commands. Thus, I created this admin tool that I could use to manage the bot.