Building a Discord Chatbot with Python (5) - Adding a 'Fortune Telling' Feature
In this article, we’ll expand our chatbot by enabling it to respond to user messages.
We’ll also introduce a fun ‘Fortune Telling’ feature to our chatbot.
A Recap of Our Progress
As of our previous session, our chatbot can now receive user messages in a chat.
Here’s what our chatbot.py
script currently looks like:
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)
Responding to Messages
Let’s now enable our chatbot to reply to user messages within the on_message
method.
But there’s something we should be wary of:
Caution on Sending Messages
Think about this:
print
function within on_message
with a function that sends a message?…
…
…
…
…
…
…
…
…
…
…
…
…
…
…
…
…
…
…
…
The answer is, “an infinite message loop would occur.”
Since the on_message
function also gets triggered by messages the bot sends, it could endlessly respond to its own messages.
To prevent this infinite loop, we’ll insert a condition at the start of on_message
to check if the message sender is the bot.
async def on_message(self, message: discord.Message):
"""Triggered when receiving a message."""
# Ignore messages sent by the bot itself
if message.author == self.user:
return
...
Using message.channel.send
to Send Messages
To allow our bot to reply, we’ll use the message.channel.send
method.
Let’s modify the on_message
function:
async def on_message(self, message: discord.Message):
"""Triggered when receiving a message."""
# Ignore messages sent by the bot itself
if message.author == self.user:
return
print(f'Received a message from {message.author}: {message.content}')
await message.channel.send(f'Hello, {message.author}!')
Explaining the Code
Since the message.channel.send
method is a coroutine function, you should prefix it with await
when calling it.
(We’ll delve deeper into the coroutine concept in upcoming sessions.)
Running the Code
Execute the script with:
python chatbot.py
Upon sending a message, you should see the bot replying, as shown below:
Adding a ‘Fortune Telling’ Feature
With the ability to respond to messages, we can now integrate various functionalities into the on_message
function.
Let’s start by introducing a ‘Fortune Telling’ feature.
Specifications
Here are the specifications for this feature:
- It gets triggered with the
!omikuji
message.
(“Omikuji” is a traditional Japanese fortune-telling method where individuals draw random fortunes written on paper strips.These fortunes range from “Great Blessing” to “Great Misfortune” and provide insights or guidance for the person’s future.) - It randomly selects and returns one result from the following options: “Great Blessing”, “Blessing”, “Small Blessing”, “Misfortune”, or “Great Misfortune”.
Implementing the Feature
Let’s proceed with the implementation. Add import random
at the beginning of chatbot.py
and modify on_message
as follows:
async def on_message(self, message: discord.Message):
"""Triggered when receiving a message."""
# Ignore messages sent by the bot itself
if message.author == self.user:
return
print(f'Received message from {message.author}: {message.content}')
if message.content == '!omikuji':
choice = random.choice(["Great Blessing", "Blessing", "Small Blessing", "Misfortune", "Great Misfortune"])
await message.channel.send(f"Your fortune for today is: **{choice}**!")
Running the Feature
Run the code again, and type !omikuji
. The bot should respond with your fortune for the day, as seen below:
Conclusion
Today, we’ve enhanced our chatbot to respond to messages and added a ‘Fortune Telling’ feature.
While this session was centered around a single interaction between the user and the chatbot,
in our next segment, we’ll delve into creating multi-turn interactions.
This will pave the way for adding a ‘Quiz’ feature to our chatbot.
Last Code
import discord
import random
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."""
# Ignore messages sent by the bot itself
if message.author == self.user:
return
print(f'Received a message from {message.author}: {message.content}')
if message.content == '!omikuji':
choice = random.choice([
"Great Blessing", "Blessing", "Small Blessing",
"Misfortune", "Great Misfortune"
])
await message.channel.send(
f"Your fortune for today is: **{choice}**!"
)
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)