DEV Community

BiasedKiwi
BiasedKiwi

Posted on

Chapter 2. A closer look at the code.

Now that we have prepared our virtual environment, we are ready to start developing our Discord bot.

First, clone a template I have made with git. In the same directory as our virtual environment, run the following commands:

git init .
git remote add origin https://github.com/BiasedKiwi/discordpy-template.git
git pull origin main
Enter fullscreen mode Exit fullscreen mode

Let's take a look at what these commands are doing.

  • git init . creates a Git repository in the current directory.
  • git remote add origin sets https://github.com/BiasedKiwi/discordpy-template.git as the remote server.
  • git pull origin main fetches all the commits on the main branch

Now, these command don't show any output to the console, to check that the remote has been properly registered, let's execute git remote -v. You should see this output:

origin  https://github.com/BiasedKiwi/discordpy-template.git (fetch)
origin  https://github.com/BiasedKiwi/discordpy-template.git (push)
Enter fullscreen mode Exit fullscreen mode

After you've executed all of these command, your directory structure should look like this:

├── LICENSE
├── README.md
├── launcher.py
├── requirements.txt
└── src
    ├── __init__.py
    ├── bot.py
    └── cogs
        └── miscellaneous.py
Enter fullscreen mode Exit fullscreen mode

A look at the code.

Let's take a look at src/bot.py. First, we can see a class declaration:

class MinimalBot(commands.Bot):
    """Constructor class for the bot."""

    def __init__(self, *args, **kwargs):
        self.prefix = kwargs["command_prefix"]
        super().__init__(
            *args, **kwargs
        )  # Initialise a `Bot` instance with the parameters passed in the constructor.
Enter fullscreen mode Exit fullscreen mode

This code declares a class named MinimalBot which inherits properties from discord.ext.commands.Bot. In MinimalBot's __init__ function, it creates an instance of it's parent class, a.k.a. commands.Bot, with the parameters suupplied (*args, **kwargs).

If we continue reading, we can see a function definition:

async def setup_hook(self):
        await self.load_cogs(client=self, directory="./src/cogs")
Enter fullscreen mode Exit fullscreen mode

setup_hook() is a special function called when the bot is being set up. It can be used to perform async operations when the bot first starts, without having to mess with __init__().Inside we can see a call to another function: self.load_cogs()

async def load_cogs(self, client, directory: str, subdir: str = "") -> None:
        """Load all cogs in a given directory in a recursive fashion."""
        os.chdir(directory)
        base = os.getcwd()
        for file in os.listdir():  # Iterate through all the files in a directory
            if file.endswith(".py"):
                if subdir != "":
                    await client.load_extension(
                        f"src.cogs.{subdir}.{file[:-3]}"
                    )  # As of Discord.py 2.0, `load_extension` is a coroutine.
                else:
                    await client.load_extension(
                        f"src.cogs.{file[:-3]}"
                    )  # Refer to comment on line 61.
            elif os.path.isdir(os.path.join(base, file)):
                os.chdir(os.path.join(base, file))
                await self.load_cogs(client, os.getcwd(), subdir=file)  # Recursive call
                os.chdir(base)
Enter fullscreen mode Exit fullscreen mode

Unlike setup_hook(), self.load_cogs() isn't a special function of commands.Bot, it has been defined by us. This function loads all the cogs in a directory. For now, just know that cogs are "extensions" of the bot that can contain commands and other interesting things.

Further down, we can see another function definition: on_ready(). on_ready() is an event that is called when the bot has connected to Discord servers and is done preparing the data sent by Discord.

Events are special functions called when a specific event has been dispatched from Discord (duh!), in this example, on_ready is called when the bot is ready to send and receive data to Discord. Other events also exist like on_message() which is an event that is called whenever a message has been sent in a guild in which the bot is in. For a list of all events, take a look at the link to the Discord.py event reference in the Further Reading section at the end of this article.

Now, let's take a look at another file: launcher.py. This file is very simple, it contains a single main function.

def main():
    intents = discord.Intents.default()
    intents.message_content = True
    bot = MinimalBot(
        intents=intents,
        command_prefix=os.environ.get("BOT_CMD_PREFIX"),
    )
    bot.run(os.environ.get("BOT_DISCORD_TOKEN"))
Enter fullscreen mode Exit fullscreen mode

The first thing that this command does is set the intents, these are very important in Discord bot development, and we will talk about them in the next section of this article. Then, it creates an instance of MinimalBot inside a variable named bot. Finally, it runs the bot using an environment variable to get the token of the bot. (More on that later.)

Intents

Intents were implemented by Discord to regulate the amount of data your bot has access to, for example, we've mentionned the on_message event before. To get this event working, we have to set the message_content intent to True. This will allow your bot to read the contents of all messages the bot can read. But there's a catch, the message_content intent is what Discord calls a privileged intent. This means that once your bot reaches 75 guilds, Discord will have to verify your bot for you to continue using the intent.

Tokens

Tokens are a string of characters that authentify you with the Discord API (Kind of like a password). They carry your autorisations, like privileged intents. Tokens are highly sensitive pieces of info, if it falls in the wrong hands, it could have desastrous consequences for your bot, so make sure to keep it somewhere safe, and only share it with people you truly trust.

Conclusion

Alright! I think this article has come to an end, in the next one, we will look at cogs: how to use them, load them and their gotchas. See you on the next one!

Further Reading

Top comments (0)