Discord Botを作ってみよう #01 - Hello, Pycord!

# まえがき

[ひとりアドベントカレンダー](https://qiita.com/advent-calendar/2022/ukwhatn)という狂気の企画、2日目記事です。

# はじめに


この記事(群)は、Pythonと[Pycord](https://pycord.dev/)を利用してDiscord Botを開発しようとする方に向けたものです。

本記事群では、以下の流れでPycordの機能を紹介していきます。

>1. **#01 - Hello, Pycord!**(本記事)
>2. **[#02 - スラッシュコマンドを使ってみよう](https://qiita.com/ukwhatn/items/48953e30ed67dee6fe38)**
>3. **[#03 - イベントリスナを使ってみよう](https://qiita.com/ukwhatn/items/187b468bd2c9c74fc9be)**
>4. **[#04 - インタラクティブなGUIを作ってみよう]()**
>5. **[#05 - Cogを導入しよう]()**
>6. **[#06 - （番外編)デプロイ環境のはなし]()**

:::note warn
この記事は、対象読者を**Pythonの記法に関する基礎知識はあるが、公式ドキュメントだけで実装できるほど慣れても居ない方**としています。

もしこの記事を読んでもコードの意味がわからない場合は、基礎知識が不足している可能性があります。Paizaなどの入門サイトや技術書を参照しながら、足りない知識を補完していくことを推奨します。
:::

:::note
* **動作確認日:** 2022/12/3
* **各種バージョン**
    * Python: 3.10.7
    * Pycord: 2.3.1
:::

# 開発の前に

## Botアカウントを作成する

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

以下の手順に従って、Botアカウントの作成を行ってください。

1. **[Discord Developer Portal](https://discord.com/developers/applications)**へアクセス
2. **"New Application"をクリックし、出てきたモーダルにBotアカウントの名前を入力し、Createボタンで登録**する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/428968/42e66d7d-c193-6989-d5f7-ac812ccd91c4.png)
3. サイドバーから**Bot**を選択し、**Add Bot**をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/428968/98fc01aa-cdc6-11fd-538c-8967774c9957.png)
4. 出てきた画面で**Reset Token**をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/428968/19b687cb-11b6-f230-402c-94f90f306445.png)
5. 表示された長い文字列(トークン)をコピーし、メモ帳などに貼り付けておく
6. 少し下にスクロールして、**Privileged Gateway Intents**の中にある3つのスイッチをすべて有効化して保存してください
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/428968/004e3f57-618b-dbe0-d2ea-79acfffd257e.png)

:::note
**トークンとは？**
トークンは、Botごとに発行される一意な文字列で、これを用いて「どのBotが起動しているのか」をDiscordに知らせる、いわばユーザIDとパスワードを合体させたようなものです。

このトークンさえわかれば、誰でも、あらゆるコードをあなたのBotとして起動させることができます。そのため、慎重に扱われなければなりません。

例えば、**GithubのPublicリポジトリに公開する**とか、**Discordサーバーに貼っておく**とかはすべきではありません。
:::

:::note
**Privileged Gateway Intents(特権インテント)とは？**
DiscordがBotの安全性を担保するために設けているものです。
いくつかのデータを読み取るために、Developer Portalの中で個別で有効化し、更にプログラムの中でも設定を行わなければなりません。
今回有効化した3つのIntentsは、それぞれ次のようなデータを読み取るための設定です。

* **PRESENCE INTENT** : サーバー内のユーザーのステータスを確認する
* **SERVER MEMBERS INTENT** : サーバー内のメンバーの増減やニックネーム・ロールの変更などを取得する
* **MESSAGE CONTENT INTENT** : サーバー内で送信されたメッセージを取得する

Developer Portalにも書いてあるとおり、100以上のサーバーで利用されているBotは、この特権インテントを利用するためにDiscordによる許可が必要です。
逆に言えば、100未満のサーバーで利用するのであれば、これらを気にする必要はありません。全てONにしておいて大丈夫です。
:::

## Botをサーバーに参加させる

ここまでで、BotをDiscordに登録することができました。
しかし、それだけではBotを動かすことはできません。サーバーに参加させて初めて利用することができます。

以下の手順に従って、Botをサーバーに参加させてみましょう。

1. Developer Portalのサイドバーから`OAuth2` -> `URL Generator`を選択![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/428968/f2c34e8b-f054-63c3-b6e7-b5331ea8f40f.png)
2. **SCOPES**の中から以下のものにチェックを入れる![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/428968/4573e0af-5ee5-4b79-eda3-6e0b0d8e9752.png)
    1. `applications.commands` 
        * あとで利用する「スラッシュコマンド」に必要です
    2. `bot`
        * botとして動作させるために必要です
        * **BOT PERMISSIONS**は、サーバーに参加した時に最初からもっている権限を設定することができます。
            * 参加後は、通常のロール編集を行えばBotの権限を変更できます。
            * 今回は何も設定しなくて大丈夫です。
3. 下部の**GENERATED URL**の内容をコピーし、ブラウザで開く
4. 参加させたいサーバーを選んでAuthorizeする![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/428968/69f8c25f-4293-30be-582a-c54058e6a36c.png)

# Botを動かしてみよう

ここから、Pythonで実際にBotのプログラムを書いていきます。

最初は、簡単なテンプレートを使って動かしていきましょう。

:::note 
* Pythonの環境構築ができていることが前提となります
    * まだの方は[こちら](https://qiita.com/ukwhatn/items/e192c419bde15a776819)も参照してください。
* 開発に際しては、**venv**などを利用してpipでパッケージを導入する先を独立させると良いでしょう。
    * [参考資料](https://camp.trainocate.co.jp/magazine/venv-python/)
:::

## pycordのインストール

```sh
pip install py-cord
```

## main.pyの作成
プロジェクトのディレクトリに`main.py`を作成し、以下のコードをコピペしてください。

```py
# Pycordを読み込む
import discord

# アクセストークンを設定
TOKEN = "YOUR_ACCESS_TOKEN"  # 自分のアクセストークンと置換してください

# Botの大元となるオブジェクトを生成する
bot = discord.Bot(
        intents=discord.Intents.all(),  # 全てのインテンツを利用できるようにする
        activity=discord.Game("Discord Bot入門"),  # "〇〇をプレイ中"の"〇〇"を設定,
)


# 起動時に自動的に動くメソッド
# #03で詳しく説明します
@bot.event
async def on_ready():
    # 起動すると、実行したターミナルに"Hello!"と表示される
    print("Hello!")


# Botが見える場所でメッセージが投稿された時に動くメソッド
@bot.event
async def on_message(message: discord.Message):
    # メッセージ送信者がBot(自分を含む)だった場合は無視する
    if message.author.bot:
        return

    # メッセージが"hello"だった場合、"Hello!"と返信する
    if message.content == 'hello':
        await message.reply("Hello!")


# Botを起動
bot.run(TOKEN)

```

## 実行

それでは、main.pyを実行させてみましょう。

**ターミナルに`Hello!`と表示されたら成功です！**

そのまま、先程Botを参加させたサーバーで`hello`と発言してみましょう。
画像のように、Botから返信が来ると思います。来ない場合は権限を見直してみましょう。
Botがそのチャンネルを閲覧でき、かつメッセージを送信できる必要があります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/428968/0798911e-9bb1-393f-0e66-b724fc6be469.png)


今日はここまで！

# このシリーズの他の記事

* **Discord Botを作ってみよう**
    1. **#01 - Hello, Pycord!**(本記事)
    2. **[#02 - スラッシュコマンドを使ってみよう](https://qiita.com/ukwhatn/items/48953e30ed67dee6fe38)**
    3. **[#03 - イベントリスナを使ってみよう](https://qiita.com/ukwhatn/items/187b468bd2c9c74fc9be)**
    4. **[#04 - インタラクティブなGUIを作ってみよう]()**
    5. **[#05 - Cogを導入しよう]()**
    6. **[#06 - （番外編)デプロイ環境のはなし]()**