【Python】discord.pyが開発終了ということなのでpycordに乗り換えよう

# 1. はじめに
当記事は、Discord API の Pythonラッパー「[discord.py](https://github.com/Rapptz/discord.py)」の開発終了を受けて、
今後どのように Pythonを使用してDiscorsd Botを作れば良いかについて解説したものです。

discord.pyの開発終了については[こちら](https://gist.github.com/Rapptz/4a2f62751b9600a31a0d3c78100287f1)を確認してください。
Discorsd Botの作り方／discord.pyの使い方については[#関連記事](https://qiita.com/melonade/items/25c038e8e4e6800aa639#5-関連記事)をご覧ください。

また、**Python・discord.pyの経験のある方を対象としています。**予めご了承ください。

# 2. 何故「pycord」を選ぶのか
discord.pyの主な代替ライブラリとして、

- pycord (https://github.com/Pycord-Development/pycord)
- nextcord (https://github.com/nextcord/nextcord)
- disnake (https://github.com/DisnakeDev/disnake)

などが挙げられます。
これらは全て discord.pyをフォークして開発の進められているライブラリのため、
現時点で標準の機能にはあまり差がないように感じました。

そのため、ライブラリの移行を考えている方が気になっていそうと考えた

- Application Commands (スラッシュコマンド)が実装できるかどうか
- discord.pyからの 書き換え量がどれくらいか
- GitHubのスター数

を基準に調べ、どのライブラリが良いかを選びました。

|ライブラリ|GitHubスター数|Application Commands|discord.pyからの書き換え|
|:--:|:--:|:--:|:--:|
|pycord|約1200|〇|普通|
|nextcord|約500|×|多い|
|disnake|約250|〇|多い|
(記事執筆時 2021/12/17 現在)

まず、nextcordには 現時点でApplication Commandsが実装されていませんでした。
今後、Message Content Intentを使用するのに申請が必要になる為、nextcordはあまりおすすめできません。

disnakeは pycordと比べると書き換えの量が多く、Application Commandsの実装もpycordに比べ少し複雑でした。
**そのため、当記事では [pycord](https://github.com/Pycord-Development/pycord) に乗り換える方法についてを解説します。**

# 3. pycordのインストール
```
$ pip install git+https://github.com/Pycord-Development/pycord
```
今回はApplication Commandsを実装するため、GitHubから直接インストールします。

# 4. Application Commandsの実装
## 4.0. コードの基本形
```python:discordbot.py
import discord

bot = discord.Bot()

# ここにコードを記述

bot.run('DISCORD_BOT_TOKEN')
```
`'DISCORD_BOT_TOKEN'` には、自分のBOTのTOKENを入れてください。

## 4.1. コマンドの実装(オプションなし)
```python:discordbot.py
@bot.slash_command(guild_ids=[...])
async def ping(ctx):
    await ctx.respond('pong')
```
![image-pp.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2273214/b1c56c2f-f507-b9bd-25c5-8537425adf9d.png)
これだけで画像のような `ping/pong` のコマンドを実装できます。
サーバー専用コマンドの場合は `[...]` にそのサーバーのIDを入れてください。
全体のコマンドの場合 `guild_ids=[...]` は必要ありませんが、コマンドの登録までに1時間弱かかるようです。
参考：[examples/app_commands/slash_basic.py](https://github.com/Pycord-Development/pycord/blob/master/examples/app_commands/slash_basic.py)

## 4.2. コマンドの実装(オプションあり)
```python:discordbot.py
from discord.commands import Option

@bot.slash_command(guild_ids=[...])
async def hello(
    ctx,
    name: Option(str, '名前を入力してください'),
    gender: Option(str, '性別を選択してください', choices=['男性', '女性', 'その他']),
    age: Option(int, '年齢を入力してください', required=False, default=18),
):
    await ctx.respond(f'こんにちは、{name}さん')
```
オプション(引数)を追加する場合は `from discord.commands import Option` を追加する必要があります。
参考：[examples/app_commands/slash_options.py](https://github.com/Pycord-Development/pycord/blob/master/examples/app_commands/slash_options.py)

## 4.3. オートコンプリートの実装
```python:discordbot.py
from discord.commands import Option

COLORS = ['red', 'orange', 'yellow', 'green', 'blue', 'indigo', 'violet']

async def get_colors(ctx):
    return [color for color in COLORS if color.startswith(ctx.value)]

@bot.slash_command(guild_ids=[...])
async def color(
    ctx,
    color: Option(str, '色を選択してください', autocomplete=get_colors),
):
    await ctx.respond(f'{color}が選択されました')
```
入力した値によって選択肢が変化するサジェスト機能を実装できます。
参考：[examples/app_commands/slash_autocomplete.py](https://github.com/Pycord-Development/pycord/blob/master/examples/app_commands/slash_autocomplete.py)

# 5. おわりに
この記事を読み、PythonでのApplication Commandsの実装に魅力を感じなかった方は、他の言語のライブラリも触ってみることをおすすめします。有名なものだと、discord.jsもApplication Commandsに対応しています。

また、Discord APIやそのラッパーについて質問・議論をしたい方はDiscordのコミュニティに参加することをおすすめします。
ROM専でもかなり有益な情報を得ることが可能なため、コミュニケーションが苦手という方も参加だけしておいて損はないです。

私のおすすめコミュニティはこちら

- [Discord Bot Portal JP](https://discord.gg/FWw6VqQ)
  - Discord Botの利用者/開発者が集まるサーバー

https://discord.gg/FWw6VqQ

私が初学者の頃からお世話になっているコミュニティです。
BOTを使った独自の質問システムが存在します。ぜひ参加してみてください。
(質問専用のサーバーではありませんのでご注意ください)

# 6. 関連記事
- [Pythonで実用Discord Bot(discordpy解説) - Qiita](https://qiita.com/1ntegrale9/items/9d570ef8175cf178468f)
- [discord.py入門(1) - Qiita](https://qiita.com/sizumita/items/9d44ae7d1ce007391699)
- [discord.py入門(2) - Qiita](https://qiita.com/sizumita/items/b37e74fca41d98077a18)