LoginSignup
1
4

使い魔ボットを創ろう - TwitchIOでシンプルなTwitchボットを作る

Last updated at Posted at 2023-11-16

Twitchをやってると何かとサポートしてくれるボットが欲しくなったので作ることしました。これはまず作ってみたChatGPTで雑談するボットです。にゃんこ仕様ですにゃん

TwitchIO-SimpleSample_00.png

TwitchIO ライブラリを使うと簡単にボットを作れるので、まずはシンプルなものを説明します。そのうちChatGPT入も解説します。

2024-12-03 翻訳AIのコードを公開しました。開発中のボットAIの会話も見れます。

今回説明することは4つ

  • ACCESS_TOKEN の取得
  • プログラミング
    • チャンネルへのJoin
    • コメントが書き込まれたらコメントを返す
    • コマンドが入力されたらコメントを返す

ACCESS_TOKEN の取得

ボットをチャンネルにログインさせるには ACCESS_TOKEN が必要になります。ボット用のアカウントでログインした状態で以下のURLにアクセスし、画像の手順をふみます。
Twitch Chat OAuth Password Generator

Qiita_Twitch_OAuth_01.png

Qiita_Twitch_OAuth_02-2.png

Qiita_Twitch_OAuth_02-03.png

表示されたものをコピっておいてください。

プログラミング

まずは TwitchIO をインストールです。

$ pip install twitchio

全体のコードを見てから1つ1つ追って見ていきます。

from twitchio import Channel, Message
from twitchio.ext import commands


WTITCH_ACCESS_TOKEN = "XXXXXXXXXXXXXXXXXXXXXXXX"
LOGIN_CHANNEL = "akiraaak"
COMMAND_PREFIX = "!"

class Bot(commands.Bot):

    def __init__(self):
        super().__init__(
            token=WTITCH_ACCESS_TOKEN,
            prefix=COMMAND_PREFIX,
            initial_channels=[LOGIN_CHANNEL]
        )

    async def event_channel_joined(self, channel: Channel):
        print(f"ログインしました。チャンネル名: {channel.name}")
        for chatter in channel.chatters:
            print(f'ユーザーID: {chatter.id}')
            print(f'ユーザー名: {chatter.name}')
            print(f'表示名: {chatter.display_name}')
        await channel.send(f"{chatter.name}があらわれた!")

    async def event_ready(self):
        print("全てのチャンネルにログインしました。")
        print(f'ユーザーID: {self.user_id}')
        print(f'ユーザー名: {self.nick}')

    # コメントが書き込まれると呼び出される
    async def event_message(self, message: Message):
        # ボットの発言は無視する
        if message.echo:
            return

        # メッセージがコマンドであれば、ここで処理を終了
        if message.content.startswith(COMMAND_PREFIX):
            await self.handle_commands(message)
            return

        print(f'ユーザーID: {message.author.name}')
        print(f'ユーザー名: {message.author.display_name}')
        # オウム返し
        await message.channel.send(f"{message.content}")

    # !hello こんにちは
    @commands.command(name='hello')
    async def cmd_hello(self, ctx: commands.Context):
        await ctx.send(f'Hello! {ctx.author.name}! {ctx.message.content}')


def main():
    bot = Bot()
    bot.run()


if __name__ == "__main__":
    main()

さきほど取得した ACCESS_TOKENWTITCH_ACCESS_TOKEN に設定してください。

Twitch のボットは TwitchIO を使うととても簡単に作れます。commands.Bot を継承した Bot を定義して、そのインスタンスを作成し run() するだけです。

class Bot(commands.Bot):

    def __init__(self):
        super().__init__(
            token=WTITCH_ACCESS_TOKEN,
            prefix=COMMAND_PREFIX,
            initial_channels=[LOGIN_CHANNEL]
        )
bot = Bot()
bot.run()

Bot クラスのコンストラクタには、ボットのACCESS_TOKEN、Joinするチャンネル、コマンドラインのPrefixを指定します。

ACCESS_TOKEN は最初に取得したものですね。

チャンネルは配信のチャンネルで、僕のチャンネルだと https://www.twitch.tv/akiraaak なので akiraaak になります。

コマンドラインのPrefixですが、のちのち出てきますが、ボットにはコマンドを設定できます。ビートセイバーのボットだと、!bsr !bomb !link などがあるんですが、この先頭の ! になります。?なんかも一般的です。 まずは!を指定しておけばいいとおもいます。

チャンネルへのJoin

run() を実行してチャンネルに入るとコールバック関数が呼ばれます。今回は2つ定義しています。

コンストラクタのチャンネルの指定は配列でした。 initial_channels=[LOGIN_CHANNEL] コールバック関数はそれぞれのチャンネルに入った後に呼ばれるものと、全てに入ったあとに呼ばれるものと2つあります。

それぞれのチャンネルで呼ばれるコールバック関数

async def event_channel_joined(self, channel: Channel):
    print(f"ログインしました。チャンネル名: {channel.name}")
    for chatter in channel.chatters:
        print(f'ユーザーID: {chatter.id}')
        print(f'ユーザー名: {chatter.name}')
        print(f'表示名: {chatter.display_name}')
    await channel.send(f"{chatter.name}があらわれた!")

全てのチャンネルに入ったあとに呼ばれるコールバック関数

async def event_ready(self):
    print("全てのチャンネルにログインしました。")
    print(f'ユーザーID: {self.user_id}')
    print(f'ユーザー名: {self.nick}')

ただし、event_channel_joined()のユーザー情報は正しいものが入ってきてないように思います。id,display_name が None だったり、全てのユーザーが返ってこなかったり。挙動がよくわかりません。

await channel.send() を使うことでコメントを書くことができます。
await channel.send(f"{chatter.name}があらわれた!")

TwitchIO-SimpleSample_03.png

コメントが書き込まれたらコメントを返す

少し複雑なコードになっているので、先に下のコマンドの説明に目を通した方がいいかもしれません。

    # コメントが書き込まれると呼び出される
    async def event_message(self, message: Message):
        # 1.ボットの発言は無視する
        if message.echo:
            return

        # 2.メッセージがコマンドであれば、ここで処理を終了
        if message.content.startswith(COMMAND_PREFIX):
            await self.handle_commands(message)
            return

        print(f'ユーザーID: {message.author.name}')
        print(f'ユーザー名: {message.author.display_name}')
        # オウム返し
        await message.channel.send(f"{message.content}")

コメントが書き込まれたらコメントを返すだけなのですが、最初に大切な儀式が2つあります。

  1. ボット自身が書き込んだコメントの場合は抜ける
  2. コメントがコマンドだったらコマンド処理を実行して抜ける

この2つにだけ気をつければ、あとは message.author にユーザー情報が入ってくるのと message.content にコメントが入ってくるのでそれを処理すれば大丈夫です。

await message.channel.send() でそのままオウム返しをしてます。

TwitchIO-SimpleSample_04.png

コマンドが入力されたらコメントを返す

ボットにはコマンドという機能があります。コメントがprefix(今回は!)から始まった特定の単語のときに関数が呼ばれます。

このコマンドは !hello というコマンドになります。!hello こんにちは とコマンドの後ろに文字を続けて使うこともできます。ビートセイバーだと !bsr 2142bなんて使い方がされてますね。

# !hello こんにちは
@commands.command(name='hello')
async def cmd_hello(self, ctx: commands.Context):
    await ctx.send(f'Hello! {ctx.author.name}! {ctx.message.content}')

!hello こんにちはこんにちわ と入力されたので Hello! akiraaak !hello こんにちはこんにちわ と返しています。

TwitchIO-SimpleSample_05.png

おわりに

TwitchIO を使うととても簡単にTwitchボットが作れると思います。どうぞお試しくださいまし。

Twitchボット開発風景の配信もやってるのでよかったらみにきね
あキら

1
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
4