Creating a Python Discord Bot With MVC

By Apollo-Roboto | Published ()

Tutorial Python Discord Bot MVC Design Pattern Organization

This tutorial focuses on the MVC pattern and how you can apply it to your own bot. I’ll be presenting it with a simple dice roll command.

I am assuming that you already got your token. If not, get it on the Discord Developer Portal.

What is MVC

MVC is a design pattern commonly used for developing user interfaces. It’s a great way to properly organize your code.

  • The Model is the component that defines, hold and manages data.
  • A View takes data to create a visual representation of it.
  • The Controller manages user input to build and return the request

Setting the Directory Structure

Here is the basic directory structure we will be following.

.env
requirements.txt
src/
├─ controllers/
├─ models/
├─ views/
╰─ main.py

This is the content of .env, you’ll have to place your token in this file:

DISCORD_BOT_TOKEN={TokenHere}

The content of requirements.txt:

python-dotenv
discord.py

Install the dependencies with python -m pip install -r ./requirements.txt.

Creating a Model

Create a new file under src/models/ named DiceRoll.py.

The model will be a very simple class, its only purpose is to define and represent information.

from dataclasses import dataclass

@dataclass
class DiceRoll:
	result: int
	maximum: int

Notice the @dataclass decorator, it’s a built in utility that generates common methods such as __repr__() and __init__(). More on the dataclasses documentation.

Creating a View

Create a new file under src/views/ named DiceRollView.py.

Now it’s time to think about how we want to display this information! A discord bot mostly reply in plain text, but we can use the fancier embed messages that allow you to add a little bit more personality to your messages.

from discord import Embed, Color
from models.DiceRoll import DiceRoll

class DiceRollEmbed(Embed):
	def __init__(self, diceRoll: DiceRoll):
		super().__init__()

		self.color = Color.from_str('#5865f2')
		self.title = f"🎲 Rolled {diceRoll.result}!"
		self.description = f"With a d{diceRoll.dice}"

Here is what this should look like:

Preview of an embed message

Embeds messages have a lot of options like descriptions, fields, author and timestamps. Check out all the features on the Embed class documentation.

Creating the Controller

Create a new file under src/controllers/ named DiceRollController.py.

The controller will be in charge of handling a roll request. Or in other words, what happens when the user types !roll? This is where we build the model and the view before returning the result to the user.

from discord.ext import commands
import random
from models.DiceRoll import DiceRoll

class DiceRollController(commands.Cog):

	def __init__(self, bot):
		self.bot = bot

	@commands.command(
		name="roll",
		description="Roll a dice!",
	)
	def rollCommand(self, ctx, dice: int = 6):
		diceRoll = DiceRoll(
			result=random.randint(1, dice),
			dice=dice,
		)

		embed = DiceRollView.DiceRollEmbed(diceRoll)

		await ctx.send(embed=embed)

command.Cog is the parent class used to declare a group of commands. Find more on the Cogs documentation.

We now have the full MVC pattern in place!

Main.py

The only part missing is the main file where we configure and run the bot.

import asyncio
import os
from dotenv import load_dotenv
from discord import Intents
from discord.ext import commands
from controllers.DiceRollController import DiceRollController

async def main():
	load_dotenv()

	bot = commands.Bot(
		command_prefix='!',
		intents=Intents.all(),
	)

	await bot.add_cog(DiceRollController(bot))

	bot.run(os.environ['DISCORD_BOT_TOKEN'])

if(__name__ == '__main__'):
	asyncio.run(main())

Note that we need to add our controller to the bot using the add_cog() method.

Trying it Out

Run the bot by executing the main file.

python ./src/main.py

In Discord, write !roll. You should see your view with all the information from the DiceRoll model! You can also change the dice by using a different number !roll 20.

Template Code

MVC is used in my personal discord bot template. It’s totally free to use and available on my GitHub. That template will differ and be more advanced than what is presented here, but could be very helpful.

GitHub Icon

Copyright © 2024 | Apollo-Roboto

Powered by Github Pages, Hugo and Tailwindcss