Discord.pyで湯婆婆を作る

# はじめに

@Nemesis さんの [Javaで湯婆婆を実装してみる](https://qiita.com/Nemesis/items/c7192a7c510788d2cba2) と、@nekozuki_dev さんの [Discord Botで湯婆婆を実装してみる](https://qiita.com/nekozuki_dev/items/485d47a459a63f59400f)のdiscord.py版です。
discord.py初見の方は [Pythonで実用Discord Bot(discordpy解説)](https://qiita.com/1ntegrale9/items/9d570ef8175cf178468f) みたいなやつを読んで下さい。（いないと思うけど）
初記事なので見にくいところがあったらごめんなさい。
**ライトテーマ注意！**

# 置き換え
#### 名前の入力
```java
Scanner keiyakusho = new Scanner(System.in);
String name = keiyakusho.nextLine();
```

原作ではこのようにコンソールから入力を求めていますが、

![ニックネーム](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/659894/f9ac3d83-4681-988c-a788-a920a3140f41.png)

「ニックネームがあるじゃん！」
というわけで今回はニックネームを使います。

#### 出力
```java
System.out.println("今からお前の名前は"+newName+"だ。いいかい、"+newName+"だよ。分かったら返事をするんだ、"+newName+"!!");
```

原作では結果を出力するだけになっていますが、Discord APIではニックネームを変更することができるので、実際にニックネームを変更しようと思います。

# コードを書く

実際にコードを書いていきます。

#### 基本のBot
[公式が用意](https://discordpy.readthedocs.io/ja/latest/quickstart.html#a-minimal-bot)しているやつを使います。

```py
import discord

client = discord.Client()

@client.event
async def on_ready():
    print('We have logged in as {0.user}'.format(client))

@client.event
async def on_message(message):
    if message.author == client.user:
        return

    if message.content.startswith('$hello'):
        await message.channel.send('Hello!')

client.run('your token here')
```
これで`$hello`と送信すると反応してくれるBotが出来ました。
![Hello!](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/659894/d8414f90-3b6b-97ba-a62f-39843f6e71a3.gif)


#### メンションで反応するようにする

[`User.mentioned_in`](https://discordpy.readthedocs.io/ja/latest/api.html#discord.User.mentioned_in)([`ClientUser.mentioned_in`](https://discordpy.readthedocs.io/ja/latest/api.html#discord.ClientUser.mentioned_in))を使ってメンション判定をします。

```py
if message.content.startswith('$hello'):
  await message.channel.send('Hello!')
```

を

```py
if client.user.mentioned_in(message):
  await message.channel.send('Hello!')
```
にします。
![メンションで反応](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/659894/771231da-d405-3d3b-c27a-d714293f82f4.gif)
~~湯婆婆が英語を話す貴重なシーン~~

#### 反応を変える
```py
await message.channel.send('Hello!')
```
ここを変えていきます。

```java

System.out.println("契約書だよ。そこに名前を書きな。");

Scanner keiyakusho = new Scanner(System.in);
String name = keiyakusho.nextLine();

System.out.println("フン。"+name +"というのかい。贅沢な名だねぇ。");

Random random = new Random();
int newNameIndex = random.nextInt(name.length());
String newName = name.substring(newNameIndex,newNameIndex+1);

System.out.println("今からお前の名前は"+newName+"だ。いいかい、"+newName+"だよ。分かったら返事をするんだ、"+newName+"!!");
```
これは原作のコードです。
これをPythonでかき直すと、

```py
import random
#~~~~~~~~~
print("契約書だよ。そこに名前を書きな。")

name = input()

print(f"フン。{name}というのかい。贅沢な名だねぇ。")

new_name = random.choice(name)

print(f"今からお前の名前は{new_name}だ。いいかい、{new_name}だよ。分かったら返事をするんだ、{new_name}!!")
```
こうなります。
これをdiscord.py仕様に書き直すと…

```py
import random
#~~~~~~~~~
await message.channel.send("契約書だよ。そこに名前を書きな。")

await message.channel.send(f"(あなたは契約書に`{message.author.display_name}`と書き込んだ。)")

name = message.author.display_name

await message.channel.send(f"フン。`{name}`というのかい。贅沢な名だねぇ。")

new_name = random.choice(name.replace(" ",""))

await message.channel.send(f"今からお前の名前は`{new_name}`だ。"
f"いいかい、`{new_name}`だよ。分かったら返事をするんだ、`{new_name}`!!")

await message.author.edit(nick=new_name)

await message.channel.send(f"(あなたのニックネームは`{new_name}`になった。)")
```

こうなります。
![はっや！！！](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/659894/235bc2ba-51e7-e04f-9a4d-41b5d234d0c8.gif)
(ここからサーバーを変えています。)
早すぎるので少し待たせていきます。

#### ロースペックにする

`asyncio.sleep`を使って応答を遅くします。
**`asyncio.sleep`を使わないとBot全体が止まるので注意！**

```py
import random
import asyncio
#~~~~~~~~~
await message.channel.send("契約書だよ。そこに名前を書きな。")
await asyncio.sleep(1)
await message.channel.send(f"(あなたは契約書に`{message.author.display_name}`と書き込んだ。)")

name = message.author.display_name
await asyncio.sleep(2)
await message.channel.send(f"フン。`{name}`というのかい。贅沢な名だねぇ。")

new_name = random.choice(name.replace(" ",""))
await asyncio.sleep(4)
await message.channel.send(f"今からお前の名前は`{new_name}`だ。"
f"いいかい、`{new_name}`だよ。分かったら返事をするんだ、`{new_name}`!!")

await message.author.edit(nick=new_name)

await message.channel.send(f"(あなたのニックネームは`{new_name}`になった。)")
```
こうなりました。
これをメインコードに組み込んだ結果が…
![完成](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/659894/44561b1e-6fe0-e979-bc6b-aa623226b6ce.gif)
もう完成でいいね！~~異論は認めない~~

# 最後に


discord.pyで湯婆婆を作りました。
初記事なので見にくいところがあるかもしれません。
そういうときはコメントでお願いします。

最後まで読んでいただいてありがとうございました。

#### 今回のソース

```py
import discord
import random
import asyncio

client = discord.Client()

@client.event
async def on_ready():
    print('We have logged in as {0.user}'.format(client))

@client.event
async def on_message(message):
    if message.author == client.user:
        return

    if client.user.mentioned_in(message):
        await message.channel.send("契約書だよ。そこに名前を書きな。")
        await asyncio.sleep(1)
        await message.channel.send(f"(あなたは契約書に`{message.author.display_name}`と書き込んだ。)")
        
        name = message.author.display_name
        await asyncio.sleep(2)
        await message.channel.send(f"フン。`{name}`というのかい。贅沢な名だねぇ。")
        
        new_name = random.choice(name.replace(" ",""))
        await asyncio.sleep(4)
        await message.channel.send(f"今からお前の名前は`{new_name}`だ。"
        f"いいかい、`{new_name}`だよ。分かったら返事をするんだ、`{new_name}`!!")
        
        await message.author.edit(nick=new_name)
        
        await message.channel.send(f"(あなたのニックネームは`{new_name}`になった。)")

client.run("your token here")
```

#### 補足

やろうとした人の権限が上だとForbidden吐きます。
できたらそれはそれで問題なのでヨシ！