DiscordチャットボットをPythonでつくる (5) - 「おみくじ」機能を追加する

今回は、チャットに入力されたメッセージに対し、チャットボットが返信を行う仕組みを追加します。
そして、その仕組みを利用した「おみくじ」機能を追加していきます。

前回までは、チャットに入力されたメッセージをチャットボットが受信するところまで完成しました。
現在のchatbot.pyは以下の様になっています。

import discord


class MyClient(discord.Client):
    async def on_ready(self):
        """Discord接続時に実行される関数."""
        print(f'{self.user}として接続しました。')

    async def on_message(self, message: discord.Message):
        """メッセージ受信時に実行される関数."""
        print(f'{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)

それでは、メッセージに返信を行う仕組みを on_message に追加していきましょう。
しかし、これを行う際に一点注意が必要です。

以下の問について少し考えてみてください。

Question
on_messageに書かれているprint関数を「メッセージを送信する関数」に変更した場合、
どのようなことが起きるでしょうか?




















正解は、「メッセージの無限ループが発生する」です。

チャットボットが送信したメッセージに対しても on_message が実行されるため、
自身のメッセージに対しても返信を行い無限ループが発生してしまいます。

無限ループを防止するため、on_message の最初に送信者がボットの場合の処理を入れておきましょう。

async def on_message(self, message: discord.Message):
        """メッセージ受信時に実行される関数."""
        # ボット自身のメッセージは無視する
        if message.author == self.user:
            return
    ...

それでは、メッセージを返信する処理を追加します。
メッセージの送信は、message.channel.send 関数で行うことができます。

on_message関数を以下のように変更しましょう。

async def on_message(self, message: discord.Message):
        """メッセージ受信時に実行される関数."""
        # ボット自身のメッセージは無視する
        if message.author == self.user:
            return

        print(f'{message.author}よりメッセージを受信しました: {message.content}')
        await message.channel.send(f'こんにちは、{message.author}!')

message.channel.send関数はコルーチン関数であるため、実行する際に先頭に await を付けます。
(コルーチンに関する説明は引き続き先延ばしにします。)

それでは実行してみましょう。

python chatbot.py

メッセージを送信すると、以下のようにチャットボットが返信することを確認できました。

メッセージに返信ができるようになったので、on_message関数の調整を行うことで様々な機能を追加することができるようなります。

それでは最初に、「おみくじ」機能を追加してみましょう。

「おみくじ」機能は、以下の仕様にします。

  • !omikujiというメッセージで発動する。
  • 「大吉」、「吉」、「小吉」、「凶」、「大凶」の5つのうちいずれかがランダムに選択される。

それでは実装してみましょう。
chatbot.pyの先頭にimport randomを追加し、on_messageを以下のように変更します。

async def on_message(self, message: discord.Message):
        """メッセージ受信時に実行される関数."""
        # ボット自身のメッセージは無視する
        if message.author == self.user:
            return

        print(f'{message.author}よりメッセージを受信しました: {message.content}')

        if message.content == '!omikuji':
            choice = random.choice(['大吉', '吉', '小吉', '凶', '大凶'])
            await message.channel.send(f"あなたの今日の運勢は **{choice}** です!")

実行してみましょう。
先程から起動したままであった場合は一度Ctrl+Cで停止して再度起動します。

python chatbot.py

!omikuji と入力すると、以下のようにチャットボットが今日の運勢を占ってくれます。

今回は受信したメッセージに返信できるようになり、
それを利用してチャットボットに「おみくじ」機能を追加しました。

今回はユーザのメッセージに対しチャットボットが返信するという1往復のコミュニケーションでしたが、
次回は、複数回の往復を実現する仕組みについて紹介します。
そしてその仕組みを利用して、チャットボットに「クイズ」機能を新たに追加します。

import discord
import random


class MyClient(discord.Client):
    async def on_ready(self):
        """Discord接続時に実行される関数."""
        print(f'{self.user}として接続しました。')

    async def on_message(self, message: discord.Message):
        """メッセージ受信時に実行される関数."""
        # ボット自身のメッセージは無視する
        if message.author == self.user:
            return

        print(f'{message.author}よりメッセージを受信しました: {message.content}')

        if message.content == '!omikuji':
            choice = random.choice(['大吉', '吉', '小吉', '凶', '大凶'])
            await message.channel.send(f"あなたの今日の運勢は **{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)

関連記事