PythonのPの字も知らないカレー好きの私がdiscord.pyを使ってDiscord botを作ってみる

## 初めに
### やってみようと思ったきっかけ
以前node.jsライブラリを使ったDiscord Botを作ったことがあり結構面白くてのめり込んだことがあった。
なら今度は触ったことがない最近流行りのPythonで作ったのなら最終的に機械学習とかできるようになるんじゃないかと考え、
とにかく触ってみるかということで作ることにした。

### Discord とは
通話もできてテキストメッセージもできる多機能なコミュニケーションツール
友人とDiscordでボイスチャンネルにあつまって通話しながらオンラインゲームとかを楽しんだりする時に使用する。
slackみたいな感じ。

https://discord.com/

### Discord BOTとは
イベントを検知して自動で反応して色々してくれるロボット。
例えばテキストメッセージで「おはよう！」と送信時、「おはようございます！」と返してくれたりとか、
ボイスチャンネルにユーザが入室した時、「いらっしゃいませ！」と言ってくれたりできる。
![omocha_robot.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2630436/03423555-0be6-8d0c-fe39-b1244b40a5ef.png)

## 事前準備
### Discordアカウント作成
何はともあれ、まずはDiscordアカウントを作るところから。
公式ページからアカウントを新規作成してログインまで進める。

https://discord.com/

※作成済みの場合はログインしておくだけでOK。

無事作成できたらこんな画面が出てくるはず。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2630436/dda9fc1a-a902-4686-f746-330d69c8aa8c.png)

### Pythonインストール
次にBOTプログラムを動かすための環境構築する。
今回は以下の条件でローカルで動かすことを想定。
* Windows10
* python最新版(本記事ではバージョン3.11.1を使用)
* discord.py最新版(本記事ではバージョン2.1.0を使用)

pythonの最新版をインストールする。

 https://www.python.org/

※インストーラーは全てデフォルトで進めてOK。

### discord.pyインストール
公式ページは以下のリンクから。

https://discordpy.readthedocs.io/ja/latest/index.html

インストールをするには、コマンドプロンプトを起動して以下コマンドを実行する。
```
py -3 -m pip install -U discord.py
```

## BOT登録
### BOTの新規登録
どんなBOTを定義するため、BOT登録をしていく。
Discordのデベロッパーポータルにアクセスする。

https://discord.com/developers/applications/

アクセスできたら画面右上の「New Application」をクリック。
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2630436/19c8c97a-aa20-fa8d-1a8e-42da57b23a4b.png)
NAMEに作るカレーの名前(BOTの名前)を入力して、Discordの開発者利用規約およびポリシーに同意する旨のチェックをいれて「Create」をクリックする。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2630436/040cfe88-c2af-2383-6584-d5596d57c619.png)
画面左のSettingsから「Bot」 を選択し「Add Bot」をクリック。
![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2630436/6b2c2822-e318-0263-28cc-135836b14353.png)
![4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2630436/7613d72f-77f7-6154-5290-1918d5309d2d.png)
アプリにBOTの命を吹き込むか聞かれるので「Yes, do it!」をクリックする。
![5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2630436/8585c181-1a2d-6ed1-f8e6-ead0fa279416.png)
画面が表示されればアプリボットが作成され詳細情報が確認できるようになる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2630436/65047c05-accc-7010-96e0-412f26fe4cfd.png)

### アイコン設定
アイコン画像を設定する。
これはユーザのアイコンと同様に顔となる部分である。

APP ICONの＋部分をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2630436/5713b4de-2ab1-0d94-2ab8-3fe1f32f05d9.png)
カレー画像を選択し「Save Changes」をクリックする。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2630436/03fdc72b-e094-b7f8-87a1-1251e956b2e4.png)
何も設定されていなかったアイコンにカレー画像が表示されていれば設定完了。
カレー画像がなければシチューか最悪ハヤシライスでもよい。

### インテント設定
次はインテント設定をする。
これはBOTが使う機能のみ明示的に開放するためONにする。
画面左から「Bot」を選択する。
![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2630436/10edd3b1-23be-066a-f56b-76eafadcf923.png)
Privileged Gateway Intentsの項目内に３つスイッチがありデフォルトは全てOFFとなっている。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2630436/9ef20738-bae1-64f0-d695-c6618692aab0.png)
自分のサーバでしか使用しないようなBOTであれば全てONしてしまって問題ない。
全てONに設定後、「Save Changes」をクリックする。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2630436/0938569b-81ab-b11a-6d40-1060e6a0396d.png)

### BOT権限要求設定
作成したサーバー上でBOTが色々動くためにはBOT自体に招待されたサーバーでの権限がなければ何もできない。
そのため、作ったBOTが正しく動くための権限は何が必要であるか設定しておく必要がある。
画面左のSettingsから「OAuth2」> 「URL Generator」 を選択する。
![19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2630436/a1de0933-08ad-068b-91d2-dcc7b90add2c.png)
SCOPESから「bot」にチェックを入れる。
![20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2630436/6c4c751c-5445-c07c-bba3-21e506b9a9ef.png)
BOT PERMISSIONSで自分のBOTが正常に動くために必要な権限にチェックをいれていく。
※とりあえず自分のサーバーで動かしたいだけであれば「Administrator」を選択しておけばOK。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2630436/d668c78c-a916-c8e2-1fc1-a06e8d9eade8.png)

## BOTプログラム作成
### コーディング
次にBOTにどういう動きをさせたいかプログラムを書いていく。
最初に作成したコードを保存するフォルダを作っておこう。
今回は「C:\test_bot」フォルダに保存する。(フォルダは任意の場所でOK)

とりあえず一番基本的な特定のテキストメッセージが送信された時に反応するBOTを作ってみる。
今回は「カレー」がチャットされた時、BOTが「ライス」か「ナン」どちらで食べるのがいいか教えてくれるという設定にしてみた。
```testbot_no1.py
# This example requires the 'message_content' intent.
# coding=shift-jis

# ライブラリインポート
import random
import discord

class MyClient(discord.Client):
async def on_ready(self):
	print(f'{client.user}がアップを始めました')

async def on_message(self, message):
    if message.author == client.user:
	        return

    if message.content.startswith('カレー'):
        num = random.randrange(2)
        if num == 0:
            await message.channel.send('ライス')
        else:
            await message.channel.send('ナン')

intents = discord.Intents.default()
intents.message_content = True

client = MyClient(intents=intents)
client.run('APP TOKEN')
```
### コード説明
ここでコード内でちょっとしたポイントを説明させてほしい。
2行目はエンコーティングの設定で、今回はBOTが日本語を受け取って日本語で返すため仕様であるが、
ここの記述がない場合、デフォルトのUTF-8で処理してしまうので文字コードを読み込めずエラーが出力されてしまう。
インド語であれば、UTF-8でも多分大丈夫だろう。
```
# coding=shift-jis
```

16～21行目がBOTがテキストメッセージを検知し反応するコードとなっている。
16行目で「カレー」を受け取る。
17行目で 0 or 1 の乱数取得
18～21行目で0の場合はライス、そうでなければナンが返されるといった具合。
```
    if message.content.startswith('カレー'):
        num = random.randrange(2)
        if num == 0:
            await message.channel.send('ライス')
        else:
            await message.channel.send('ナン')
```
27行目の「APP TOKEN」はBOT登録時画面のBuild-A-BotのTOKENからコピーして置き換える。
このAPP TOKENがプログラムと登録したBOTで一致していることにより、プログラムがどのBOTから動くかの紐づけとなっている。
```
client.run('APP TOKEN')
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2630436/9db9cdda-f642-e7af-8f6b-717e57b155e3.png)

:::note alert
トークン(APP TOKEN)は第三者に漏洩しないよう管理には十分注意してほしい。悪意のある第三者からBOTへのアクセスが可能となってしまい、BOTが参加しているサーバのユーザ情報の漏洩などの危険性がある。万が一トークンが漏洩してしまった場合はすぐに「Reset Token」を実行してトークンの変更をしたほうがよい。
:::
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2630436/232716c4-3ff2-9551-a6be-06751084ebc8.png)

## BOT起動
### BOTプログラム起動
いよいよBOTを起動をしていく
コマンドプロンプトを起動し以下コマンドを実行する。
```
cd C:\test_bot
py -3 testbot_no1.py
```

以下のログが表示されればOK。
```
[2022-12-14 14:55:22] [INFO    ] discord.client: logging in using static token
[2022-12-14 14:55:23] [INFO    ] discord.gateway: Shard ID None has connected to Gateway (Session ID: 9196fc28f72e476de032cdacfb10eb32).
やさいカレー#5636がアップを始めました
```
### サーバー作成
次にBOTを動作させたいサーバーを作成しよう。
Discordにログイン後の画面左の「サーバーを追加」(＋アイコン)をクリック。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2630436/3cbc250b-8dd8-b945-2d53-fcbafcfcc8f1.png)

サーバーを作成画面が表示されるので、目的にあったテンプレートを選択していく。
項目の中に「カレー」はないので、今回は「ゲーム」を選択してみる。
※テンプレート選びに失敗してもあとでカスタマイズができるので気軽に選んでみてほしい
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2630436/6cc05a81-b89e-96ad-46aa-58413d147ffe.png)
その後は適当に選び進めてサーバー名を入力し「新規作成」をクリック。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2630436/a75de5da-83b8-b458-51f2-e778f243c462.png)
以下の画面の通り、サーバー名のアイコンが表示されてばサーバー作成は成功。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2630436/2ca48c81-67fd-9e89-f3fd-328dd7c57176.png)

### BOTをサーバーへ招待するためのURL作成
BOTを動かすためのサーバーができたので、BOTをサーバ
これがないと皿に思い通りにカレーを盛ることは困難だからだ。

1つ前の手順で開いていた画面の一番下に GENERATED URL にBOT招待用のURLが生成されているので「COPY」をクリック。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2630436/f07f8a3c-9858-7f1c-b599-bcbff23a8c6b.png)

上記でコピーしたURLをブラウザに貼り付けアクセスする。
以下の画面が表示されるので盛りたい皿(サーバー)を選択のうえ、「はい」をクリック。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2630436/964b0456-42aa-3481-616c-315360d1a75d.png)

次に入っているスパイス(権限)が表示されるので問題なければ「認証」をクリック。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2630436/2895f4f9-46e1-730e-df75-2fbfb7c991e0.png)

もしも、人間か疑われた場合は、「私は人間です」にチェックを入れて対応しましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2630436/451c8070-9df8-cfcb-3000-baf47cfeea5b.png)

問題なくBOTを招待できれば認証しました画面が表示される。表示後は画面を閉じてOK。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2630436/dcd03522-3f5e-bc72-9d61-6187b0aa0384.png)

先ほど作ったサーバーを確認すればBOTが参加してきたメッセージが出力されているはず。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2630436/99d39e24-2bec-c28e-553f-cf09f29c7e31.png)

### 動作確認
さっそく「カレー」をチャットして返事をくれるか試してみる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2630436/1bce78e7-b3b9-2108-6fc4-c4905e0f8bb9.png)

無事「カレー」に対して「ライス」なのか「ナン」なのか答えてくれるBOTが完成した。

## まとめ
いかがだっただろうか。
Botといってもやり方を覚えてしまえば簡単に作れるし、触ったことのない言語であっても始めやすいと思うので、
もし興味があればぜひ自分でBOTを作ってみてカレーを好きになってほしいと思う。