PythonでDiscord

#はじめに
ディスコードを使ってサーバーを運営していくうちに実装したものをコード例を載せながら解説していこうと思います。使用したdiscord.pyはrewrite版です。

```python
import discord

client = discord.Client()
@client.event
async def on_ready():
    print('Logged in as')
    print(client.user.name)
    print(client.user.id)
    print('------')

client.run("")
```
雛形はこんな感じです。
print('------')とclient.run("")の間にそれぞれの実装したい処理を書いていきます。

#新しく入ってきた人にロールを付与してメッセージを送る
```python
# ?joinと打つとmemberという名前の役職が付与される
@client.event
async def on_message(message):
    if message.content == '?join' and len(message.author.roles) == 1:
        role = discord.utils.get(message.guild.roles, name='member')
        await message.author.add_roles(role)
        reply = f'''ようこそ{message.author.mention}さん
<#657524000993312768> をお読みください
<#657105501036740608> を書いてもらえると嬉しいです
'''

        await message.channel.send(reply)
    elif message.content == '+midnight':
        role = discord.utils.get(message.guild.roles, name='midnight')
        await message.author.add_roles(role)
    elif message.content == '-midnight':
        role = discord.utils.get(message.guild.roles, name='midnight')
        await message.author.remove_roles(role)
    elif message.content == '+novice':
        role = discord.utils.get(message.guild.roles, name='novice')
        await message.author.add_roles(role)
    elif message.content == '-novice':
        role = discord.utils.get(message.guild.roles, name='novice')
        await message.author.remove_roles(role)
```

この処理はテキストチャンネルに ?join という書き込みがされたときに、メッセージの送り主にメンションを行って、返信を送るものです。返信を送るとともに新規のメンバーに役職を追加することで ?join を送信していない人はサーバー内の他のチャンネルを見られないようにすることが出来ます。

![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/118622/5c989c86-7183-564c-9c4d-46814b677780.png)

やり方としてはシステムのメッセージチャンネルの設定のみに
@everyoneにメッセージを読むことを禁止＋送信のみ可能にさせ、それ以外のテキストチャンネルとボイスチャンネルの権限を@everyoneにメッセージを読むことを禁止させる。その時に新しく参加したメンバーの役職(ここで言う@member)の権限はメッセージを読むことを可能＋送信のみ可能にさせる。そうすることで新しく参加したメンバーはシステムのメッセージチャンネルのみ(ここで言う#ようこそ)のみがテキストチャンネルで表示される。
新しく入ってきたメンバーはシステムのメッセージチャンネル(#ようこそ)にテキストを送信することはできるが、メッセージ履歴を見ることが出来ない。(自分で送信したものも見ることが出来ない。メンションされた場合のみ通知欄から見ることが出来る)

![1515.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/118622/ddefb121-d504-95df-fe55-232d768fc573.png)

![1513.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/118622/4ee8f69b-be4d-6d13-9ef3-683375ab8469.png)

![1514.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/118622/469807ce-8164-5bbd-d5d8-4106d56217c6.png)


```python
if message.content == '?join' and len(message.author.roles) == 1:
```

メッセージが ?join であるか判定し、メッセージの送り主が役職を持たない(新規でサーバーに入ってきた人は@everyone役職しか持たないため、持っている役職の数が1つ)場合にボットからメッセージを送るようにしました。

```python
reply = f'''ようこそ{message.author.mention}さん
<#657524000993312768> をお読みください
<#657105501036740608> を書いてもらえると嬉しいです
'''
```

本文中に #ようこそ と書いてもハッシュタグとして機能しないため(文字の色が変わらない)、送りたいメッセージの本文に <#テキストチャンネルのID> を書くことで、ハッシュタグ機能付きの文字列を送ることが出来ます。


```python
    await message.channel.send(reply)
elif message.content == '+midnight':
    role = discord.utils.get(message.guild.roles, name='midnight')
    await message.author.add_roles(role)
elif message.content == '-midnight':
    role = discord.utils.get(message.guild.roles, name='midnight')
    await message.author.remove_roles(role)
elif message.content == '+novice':
    role = discord.utils.get(message.guild.roles, name='novice')
    await message.author.add_roles(role)
elif message.content == '-novice':
    role = discord.utils.get(message.guild.roles, name='novice')
    await message.author.remove_roles(role)
```

このコードの部分は+midnightや+noviceと送信することでmidnight, novice役職を付けたり、-midnight, -noviceと送信することで外したりさせるための処理です。上のテキストチャンネルの権限設定を利用してnovice役職を持つメンバーのみが表示されるテキストチャンネルを作りました。

#メンバー全員に役職を付与する
```python
# +pollと打つとメンバー全員にpoll役職付与・-pollで役職除去
    if message.content == '+poll':
        for i in range(len(message.guild.members)):
            if 'Rythm' in str(message.guild.members[i]) or 'DISBOARD' in str(message.guild.members[i]) or 'Poll Bot' in str(message.guild.members[i]):
                print('YES')
            else:
                print('NO')
                print(message.guild.members[i])

                role = discord.utils.get(message.guild.roles, name='poll')
                await message.guild.members[i].add_roles(role)

    if message.content == '-poll':
        for i in range(len(message.guild.members)):
            if 'Rythm' in str(message.guild.members[i]) or 'DISBOARD' in str(message.guild.members[i]) or 'Poll Bot' in str(message.guild.members[i]):
                print('YES')
            else:
                print('NO')
                print(message.guild.members[i])

                role = discord.utils.get(message.guild.roles, name='poll')
                await message.guild.members[i].remove_roles(role)
```

この処理は誰かが+pollと書き込むと、ボット(Rythm, DISBOARD, Poll Bot)を除くメンバー全てにpoll役職を付与しています。poll役職を持っている人だけが #アンケート調査 というテキストチャンネルを表示するようにして、アンケートの時にだけ表示をするテキストチャンネルを作りました。こうすることで表示されるテキストチャンネルを必要なとき以外は非表示にでき、テキストチャンネル一覧をシンプルにすることが可能になります。

```python
if 'Rythm' in str(message.guild.members[i]) or 'DISBOARD' in str(message.guild.members[i]) or 'Poll Bot' in str(message.guild.members[i]):
```

ここでメンバーの名前に特定の文字が入っていないか(今回の例では Rythm, DISBOARD, Poll Bot)をみることで、ボットであるか判定しています

```python
role = discord.utils.get(message.guild.roles, name='poll')
await message.guild.members[i].add_roles(role)
# メンバーに役職を付与するとき
await message.guild.members[i].remove_roles(role)
# メンバーから役職をとるとき
```
この処理でメンバーに役職を付与したり、除去したりしています。

#会話ログを削除する
```python
# ?cleanと打つと打ったテキストチャンネル内のログが消える
    if message.content == '?clean':
        if message.author.guild_permissions.administrator:
            await message.channel.purge()
            #await message.channel.send('チャンネル内のログを削除しました')
        elif message.channel.id == 657108629396389889:
            print("YES")
            print(message.channel.id)
            await message.channel.purge()
        else:
            print("NO")
            print(message.channel.id)
            await message.channel.send('ログの削除には管理者権限が必要です')
```

これはサーバーの管理者(各サーバーで王冠表示の一人のみ)が ?clean と打つと、?cleanを送信したテキストチャンネル内の会話ログを全削除(一度に100件まで)するコードです。

```python
elif message.channel.id == 657108629396389889:
  print("YES")
  print(message.channel.id)
  await message.channel.purge()
 ```

ここの部分でメッセージが送られたのが、特定のチャンネルの場合(チャンネルIDが657108629396389889のもの)のみサーバー管理者でなくても会話ログを削除できるようになっています。