5分で作るDiscordBot＋AI応答

# 分報ってご存知ですか？
みなさんは、だれかと連絡を取るほどじゃないけど、なんとなく
「なんかお腹すいたな〜」とか
「なんか暇だなぁ〜」みたいな、
反応があれば嬉しいけど、反応が何もなくても何の問題もない。みたいなコミュニケーションを取りたいと思ったことはないでしょうか？
エンジニアの世界では「日報」よりもさらに細かく、「分報」という、何か連絡したいわけじゃないけど、現在の状況を垂れ流す文化があり、Slackなどの連絡ツールに「〜times」みたいな名前で自分用のつぶやきスペースを作り、社内版Twitterみたいな運用をしている人々がいます。

[分報のメリット・活用方法とは？書き方やslackでの運用事例を紹介](https://freelanch.co.jp/useful/times/)

最近エンジニアの友人と一緒にハッカソンに出場することになったのですが、LINEとかじゃなくて、そういう分報を書き込める場所が欲しいよね、という話になり、気軽にDiscordにそういう場所を作ってみることにしました。

# 準備
- [Discord](https://support.discord.com/hc/ja)のアカウント作成
    - やりとりをする場所はDiscordにしてみます
- [OpenAI](https://openai.com/)のAPIキーの取得
    - 分報だけでなく、Discordの中でChatGPTとの会話ができ、その会話に横槍をいれるみたいな形で第三者が割り込んでこれたら面白いよね。ということで、DiscordのBotアカウントを作って、それにメンションをしたらChatGPTに回答を考えてもらって返信をしてみるようにします
- [RailWay](https://railway.app/)のアカウント作成と課金
    - DiscordBotの裏側のプログラムを用意し、それをホスティングしておくツールはRailWayにしてみました。

# 実装
## Discord編
Discordなんて初めて聞きました、という人は、まずは[こちら](https://support.discord.com/hc/ja/sections/360008206871-Discord-Basics)を読んでみましょう

### Discordサーバーを準備
アカウントを作成したら、サーバーを作成ボタンを押します。
![スクリーンショット 2024-04-11 0.54.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/27192/b808de6d-2451-c4ac-d2b7-3456e785c3db.png)

適当に選んで次に進みましょう（チャンネルが自動で作られますが、あとで好みの形に編集できるので特に悩まなくても大丈夫です）
![スクリーンショット 2024-04-11 0.54.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/27192/34e0e6ef-ec35-89a9-690d-70caa8581b6c.png)

![スクリーンショット 2024-04-11 0.56.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/27192/f1ae6bb8-6de5-bed6-4379-51763c0e6d0c.png)

![スクリーンショット 2024-04-11 0.55.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/27192/307c94f0-0290-c4ac-0313-6f040b876d5f.png)

サクッとできました！
![スクリーンショット 2024-04-11 0.55.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/27192/289d2115-823b-6b50-2b01-f874e2af975f.png)

### Discord Botを準備
Discord上でBotアカウントを動かすためには、[Discord Developer Portal](https://discord.com/developers/applications)からアカウントを追加する必要があります

右上のNew Applicationをクリック
![スクリーンショット 2024-04-11 1.06.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/27192/f1a7f3e8-5fc5-6cdd-536c-aa0286a08a4e.png)

Botの名前を決め、チェックボタンを押して、Createボタンを押す
![スクリーンショット 2024-04-11 1.06.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/27192/9886e7e6-004b-00ca-269b-277483158769.png)

こんな感じでBotが作られたかと思います

![スクリーンショット 2024-04-15 14.59.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/27192/b7dd6e55-e886-48c9-3118-2c6b88cfbeac.png)

サイドバーの「Bot」からリセットトークンを行い、トークンを控えておきます。
![スクリーンショット 2024-04-15 15.00.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/27192/d64f2802-3d01-9631-b8d4-720df3b7dae4.png)

:::note warn
PUBLIC BOTの設定はかならずOFFにしましょう
:::
![スクリーンショット 2024-04-15 14.58.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/27192/23dd3dfb-9cb3-645b-fa22-beaff0d8758f.png)

Privileged Gateway Intentsの三つの設定はすべてONにしましょう
![スクリーンショット 2024-04-15 15.04.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/27192/ebda1fab-9677-1b67-62be-9a0c4d1d74c5.png)

### Discord Botをサーバーに追加
サイドバー「OAuth2」から「OAuth2 URL Generator」の「Bot」にチェックを入れ、BOT PERMISSIONSはチェックなしで、作られたURLをコピーします
![スクリーンショット 2024-04-15 15.17.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/27192/5e8ae2f8-e2d6-22bb-021c-133576062507.png)

![スクリーンショット 2024-04-15 15.15.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/27192/cca295ea-01a5-b667-a807-6baec29904ee.png)

ブラウザのURL欄にコピーしたURLを入力してアクセスすると以下のような画面が表示されるので追加するサーバーを選択し、認証を行いましょう。

![スクリーンショット 2024-04-15 15.19.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/27192/241a58dd-f5c3-3c73-12b0-52da525d3c61.png)

これでサーバーにBotが追加されました。
![スクリーンショット 2024-04-15 15.13.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/27192/bd18025e-873e-afae-0b9f-b572055556d4.png)

## サーバー編
ここからは[RailWay](https://railway.app/)というサービスを使います。
課金をしないと使えませんが、少額から始めることができ、よほど利用しない限りは月5ドルのHobbyプランで収まると思います。
サービス料については[こちら](https://railway.app/pricing)

### サーバーのソースコードの準備
GitHubにChatGPTにつないだDiscordBotを作る用のテンプレートを用意しています。
https://github.com/cog1t0/discordpy-railway/tree/main

画面右上の「Use ThisTemplate」から「Create a new repository」を選択します
![スクリーンショット 2024-04-15 15.28.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/27192/92e0a7b1-cf24-b503-dbff-4700ed2218a2.png)

### RailWayの設定
RailWayのダッシュボードから「NewProject」 -> 「Deploy from GitHub repo」で先ほどコピーしたリポジトリを選択し、デプロイします。
![スクリーンショット 2024-04-15 15.25.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/27192/6142639b-ea97-3481-28bf-c43d5ecd6295.png)

環境変数を設定しましょう
DISCORD_BOT_TOKENはdiscordbotを作った時に控えていたトークンを入力します。
OPENAI_API_KEYは自分のopenAIのAPIキーを貼り付けます。[やり方](https://nicecamera.kidsplates.jp/help/feature/ai-kata/openapi_apikey/)
![スクリーンショット 2024-04-15 15.33.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/27192/1471d502-e938-2d73-e2cd-2c90ca002d78.png)

追加したらもう一度デプロイを行います
![スクリーンショット 2024-04-15 15.37.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/27192/0f91ea61-eb5f-14a0-35bd-19d2faba48f4.png)

## 完成！！
これで、discordにopenAIと繋がったBotを作ることができました！
![スクリーンショット 2024-04-15 15.40.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/27192/a9f9d406-8877-1347-6c15-bae14cd3ef96.png)

軽く立ち上げまでの解説でしたが、プロンプトややり取りを作り込みたい場合は、以下のファイルを編集していきましょう。

```main.py
import discord
from discord.ext import commands
from openai import OpenAI
from constant import TOKEN, OPENAI_API_KEY  # OPENAI_API_KEYもconstant.pyからインポート

extensions = (
)

class MyBot(commands.Bot):
    def __init__(self):
        super().__init__(
            command_prefix=commands.when_mentioned,
            intents=discord.Intents.all(),
        )

    async def setup_hook(self):
        for extension in extensions:
            await self.load_extension(f'extensions.{extension}')

    # メンションを受けた際の処理を追加
    async def on_message(self, message):
        messages = [
            {"role": "system", "content": "あなたは技術的な質問に、端的にわかりやすく回答するAIアシスタントです."}
        ]
        if message.author.bot:  # ボット自体のメッセージは無視
            return
        if self.user.mentioned_in(message):  # Botへのメンションが含まれている場合
            content = message.content.replace(f'<@!{self.user.id}>', '')  # メンションを削除
            messages.append({"role": "user", "content": content.split('>')[1].lstrip()})

            # OpenAIのAPIキーを設定
            client = OpenAI(
                # This is the default and can be omitted
                api_key=OPENAI_API_KEY,
            )
            # OpenAI APIを呼び出して応答を生成
            chat_completion = client.chat.completions.create(
                messages=messages,
                model="gpt-3.5-turbo",
            )

            await message.channel.send(chat_completion.choices[0].message.content)  # 応答を送信

if __name__ == '__main__':
    MyBot().run(TOKEN)
```

# 参考記事
以下を参考にさせていただきました🙏
ありがとうございます。

https://qiita.com/ukwhatn/items/c3abfbbd447f5802afa3

https://qiita.com/Pumila/items/29f26fb349d5592046ae