Building a Discord Chatbot with Python (4) - Receiving Messages with Your Chatbot

In this article, we’ll finally dive into creating a chatbot in Python.

Firstly, ensure that your working directory, discord-chatbot, contains at least the following two components from our previous sessions:

  1. Move to the discord-chatbot directory and activate the virtual environment:

    cd discord-chatbot
    source .venv/bin/activate
    
  2. Ensure discord.py is installed:

    pip list
    

To begin, we’ll build a basic chatbot that only connects to Discord.
Create a file named chatbot.py and write the following code:

import discord


with open('.discord_token') as f:
    token = f.read().strip()

intents = discord.Intents.default()
client = discord.Client(intents=intents)
client.run(token)

Then execute the script.

python chatbot.py

If everything goes well, the console should display logs indicating a successful connection to Discord, like the one below:

2023-08-18 23:39:36 INFO     discord.client logging in using static token
2023-08-18 23:39:37 INFO     discord.gateway Shard ID None has connected to Gateway (Session ID: xxx).

Terminate the bot using Ctrl+C.

Let’s dissect the script step-by-step:

import discord

Here, we’re importing the discord.py library.

with open('.discord_token') as f:
    token = f.read().strip()

This block reads the token stored in the .discord_token file and assigns it to the token variable.
The strip function ensures any trailing newline characters are removed.

intents = discord.Intents.default()

discord.Intents defines the types of events a chatbot will subscribe to.
Here, we’re using the default settings.

client = discord.Client(intents=intents)

This line initializes the Discord client, which acts as the backbone of our chatbot.

client.run(token)

Lastly, we’re using the token to launch the client, thus activating our chatbot.

Let’s further enhance our chatbot by adding more features.

While discord.py offers a myriad of methods for adding features, in this series, we’ll focus on creating a custom class derived from the discord.Client class and making modifications to it.

Update chatbot.py as shown below:

import discord


class MyClient(discord.Client):
    async def on_ready(self):
        """Triggered when connecting to Discord."""
        print(f'Connected as {self.user}.')

    async def on_message(self, message: discord.Message):
        """Triggered when receiving a message."""
        print(f'Received a message from {message.author}: {message.content}')


with open('.discord_token') as f:
    token = f.read().strip()

intents = discord.Intents.default()
client = MyClient(intents=intents)
client.run(token)
  1. We’ve defined a class named MyClient that inherits from the discord.Client.
    Within this class, we’ve overridden two functions: on_ready and on_message.
  2. Their respective purposes are:
    • on_ready: Triggered when connecting to Discord.
    • on_message: Triggered when receiving a message.
  3. Both functions are prefaced with the keyword async, denoting them as coroutine functions - specialized functions designed for asynchronous operations. We’ll delve deeper into this in upcoming sessions.
  4. self.user holds the bot’s username.
  5. The message argument in on_message receives data of the type discord.Message.
    Here, message.author denotes the sender and message.content contains the message text.
What's the 'f' at the beginning of the strings?

Strings like f'Connected as {self.user}.' are called formatted string literals or f-strings.
Introduced in Python 3.6, they allow the inclusion of embedded expressions inside string literals.
(Ref: Formatted string literals)

It offers a concise way to embed values into strings, so we’ll use them a lot throughout this series.

What does the colon (:) next to the `message` variable indicate?
This represents type hinting, introduced in Python 3.5. It provides insights into the expected data type of the variable. While Python operates seamlessly without specifying types, type hints offer several advantages, such as enhanced auto-completion in editors like VSCode.
  1. Let’s give it a go:

    python chatbot.py
    
  2. Upon connection, you’ll see a message on the console, something akin to: Successfully connected as xxx..

  3. If you type a message in the chat, the message like Received a message from xxx: will appear in your console. However, The message content isn’t being displayed!

Let’s refer to the documentation. There, you might stumble upon:

If Intents.message_content is not enabled this will always be an empty string unless the bot is mentioned or the message is a direct message.

Ah, we need to correctly set discord.Intents. To fetch the content of a message, it’s imperative to set the intents.message_content value to True.

intents.message_content = True

Add this to the code and re-run script!
You’ll now see messages like: Received a message from xxx: yyy.

In this article, we successfully connected our chatbot to Discord and configured it to receive user messages.
In the next article, we’ll set up the bot to respond directly to these messages in the chat.

import discord


class MyClient(discord.Client):
    async def on_ready(self):
        """Triggered when connecting to Discord."""
        print(f'Connected as {self.user}.')

    async def on_message(self, message: discord.Message):
        """Triggered when receiving a message."""
        print(f'Received a message from {message.author}: {message.content}')


with open('.discord_token') as f:
    token = f.read().strip()

intents = discord.Intents.default()
intents.message_content = True
client = MyClient(intents=intents)
client.run(token)

Related Content