リアクションによる役職の付与、剝奪

#まずはじめに
この記事は海外の開発者様**[Anson](https://github.com/ansonfoong?tab=repositories)**様のコードを日本語で少し分かりやすく解説した物になります。また、ご本人様への確認を取り許可を頂いている為二次配布を禁止し、個人利用にのみ使用可能とします。

[元ソースの掲載ページ](https://github.com/ansonfoong/ReactionPy)
[ご本人様の解説動画](https://www.youtube.com/watch?v=MgCJG8kkq50)


#概要
ここ最近DiscordのBot開発にのめり込んでいるのですが、よく大手のサーバーに入っているbotで**リアクションを付けると役職が付与される**アレ、どうすれば上手く実現できるのかなぁ...と悩みつつcommand.commandsのやつを調べたりなんやらと色々探してみたはいいものの、**まっっっっっっったくと言って良いほどしっくりくるpython用の日本語の記事が無かった**んですよね。なので私が調べ見つけた海外の開発者**Anson**様のコードを一部改変したものを掲載、簡単な解説を忘備録として。

##筆者の環境
前回の記事と変わらずですが一応。

- Windows10
- Pycharm Community Edition
- python 3.7.4
- discord.py 1.2.4

##前提条件
こちらも前回と変わらずpythonとdiscord.pyが動く環境が有る前提でお話します。
無いよ、という方は各自調べてください。ここでは一切解説しません
また、同じ名前のカスタム絵文字と役職が無いと以下のbotでは役職を付与する事が出来ないので事前に設定しておいてください。

**例*![emoji.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/521746/f5c1bf46-52c1-79b5-4380-4045581ed916.png)
*

![role.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/521746/b7a85c99-4fd4-2234-6f43-2ef4c95b839d.png)


#本題
```python
import discord

client = discord.Client()


@client.event
async def on_raw_reaction_add(payload):
    
    if payload.message_id == ID:

        print(payload.emoji.name)
        guild_id = payload.guild_id
        guild = discord.utils.find(lambda g: g.id == guild_id, client.guilds)

        role = discord.utils.find(lambda r: r.name == payload.emoji.name, guild.roles)

        if role is not None:
            print(role.name + " was found!")
            print(role.id)
            member = discord.utils.find(lambda m: m.id == payload.user_id, guild.members)
            await member.add_roles(role)
            print("done")


@client.event
async def on_raw_reaction_remove(payload):
    if payload.message_id == ID:
        print(payload.emoji.name)

        guild_id = payload.guild_id
        guild = discord.utils.find(lambda g: g.id == guild_id, client.guilds)
        role = discord.utils.find(lambda r: r.name == payload.emoji.name, guild.roles)

        if role is not None:
            member = discord.utils.find(lambda m: m.id == payload.user_id, guild.members)
            await member.remove_roles(role)
            print("done")


@client.event
async def on_ready():
    print("Botは正常に起動しました！")
    print(client.user.name)  # ボットの名前
    print(client.user.id)  # ボットのID
    print(discord.__version__)  # discord.pyのバージョン
    print('------')
    await client.change_presence(activity=discord.Game(name="役職を管理！"))

client.run("TOKEN")
```
こちらになります。今回は

```python
on_raw_reaction_add(payload)
```
と

```python
on_raw_reaction_remove(payload)
```
がキーとなってきます

では少しではありますが簡単な解説を以下に。

##簡単な解説
コメントアウトの方に解説を書かせて頂きます。

```python
@client.event
async def on_raw_reaction_add(payload):
    # メッセージにリアクションが追加されたときに以下の動作が呼び出されます
```

```python
    if payload.message_id == ID:
        # ここでリアクションを追加して欲しいメッセージをあらかじめ設定しておきます(IDに該当メッセージのIDをコピペしてください)
```

```python
        guild_id = payload.guild_id
        guild = discord.utils.find(lambda g: g.id == guild_id, client.guilds)

        role = discord.utils.find(lambda r: r.name == payload.emoji.name, guild.roles)
```

lambda関数に関しては
https://qiita.com/nagataaaas/items/531b1fc5ce42a791c7df
(nagataaaas様の記事)を読めば理解出来ると思います。

```python
        if role is not None:
            # 対応する役職があった場合以下の動作を行います
```

```python
@client.event
async def on_raw_reaction_remove(payload):
    # メッセージからリアクションが削除されたときに呼び出されます
```

```python
    if payload.message_id == ID:
    # IDには先ほどon_raw_reaction_add(payload)の方で使ったIDと同じものを利用してください。
```

こんなものですかね。同じような記述のコードは省略しました。

#最後に
discord.pyの日本語の記事って少ない or versionが古いものが多いですよねぇ...
このbotに関しても実装したい...けど日本語の記事でそれっぽいのは見つからないし...と言った流れで海外の方のコードを漁るようになったら案外早く見つかったので、私と同じく初学者の方であれこれしたいけどそれっぽいの見つかんないよ！てかドキュメント読んでも分かんないよ！って方は海外の方を参考にしてみては？

改めて、今回参考にさせて頂いたサイトや開発者様のURLを載せて〆ようと思います。


[Anson様のyoutubeチャンネル](https://www.youtube.com/user/DatAdam93)
[公式ドキュメントのon_raw_reaction_add(payload)ページ](https://discordpy.readthedocs.io/ja/latest/api.html?highlight=on_raw_reaction#discord.on_raw_reaction_add)
[nagataaaas様のQiitaページ](https://qiita.com/nagataaaas)