Discord.pyでEmbedを扱う(メモ)

<font color="#ff0000">注意:DiscordのバージョンアップによりEmbedの見た目がこの記事の写真と異なっていますので、ご注意ください。</font>
2021/1/19追記: 内容の一部修正・追記・タイトル変更を行いました。

自分用のメモがてら、Discord.pyのEmbedにできることを残しておきます。
旧バージョンのasync版では使用できない(そもそも使えない)[^1]ので注意です。
#そもそもEmbedって何?
以下の様なメッセージを指す。
![image.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/444993/2109475e-b942-e380-53f3-d47f49363c76.png)
**ユーザーには作成できない。**
Embedにはヘッダー、フッターテキストの設定や画像の貼り付け、サムネイルの設定等ができる。
Embed一つ当たりに格納できる最大文字数は最大で6000文字。テキストにはマークアップも使用可能。
#Embedオブジェクトの定義
以下の様に行う。

```python:Embedオブジェクトの定義
embed = discord.Embed(title="Embedのタイトル",description="Embedの概要")
```

「Embed」の**「E」が大文字になっている**ことと、**「n」ではなく「m」を入力する**ことに注意。
なお、これらの二つのキーワード引数は必須ではないが、指定しておかないと送信しようとした際にエラーが発生する。
#Embedの送信
定義したEmbedをDiscordのテキストチャンネルへ送信するには、`send()`のキーワード引数`embed`にEmbedオブジェクトを指定する。
ここでは、「embed」の文字が小文字になっているので注意。
以下のコマンドを実行すると、画像の様なEmbedが送信される。

```python:Embedの送信
embed = discord.Embed(title="Hi!!",description="How are you?")
await channel.send(embed=embed)
```

![image.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/444993/f8702eb4-0e7d-318f-1b37-a4d06b92bd77.png)
なお、二行目の`channel`は、そのままchannelと書き込めば良いのではなく、Channelオブジェクトが入る点に注意。
コマンドフレームワークを使用しており、コマンド定義内で使用する場合は、`ctx`で良い。
また、引数に直接`discord.Embed()`を書き込む事も出来るが、コードが見づらくなる可能性があるうえ、利便性が悪いので、避けた方が良い。
##枠の色を指定
`discord.Embed()`のキーワード引数の`color`に16進数カラーコードを指定することでEmbedの枠に色を付けることができる。

```python:枠の色の指定
embed = discord.Embed(title="Hi!!",description="I got a color!",color=0xff0000) #16進数カラーコード
```
送信すると以下の様になる。
![image.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/444993/8cd66078-189a-b1da-ce8b-3e20b2e5e022.png)


###特殊な指定方法
`discord.Colour()`というクラスを使うと、カラーコードではなく色の名前で色を指定できる。

```python:特殊な色の指定
embed = discord.Embed(title="Hi!!",description="I got a special color!",color=discord.Colour.red())
```
![image.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/444993/a0c79f9c-73f8-aaa5-9598-4d50f9744876.png)

ただ、この方法だと望んでいる色とは少し違う色で作成されたりするのでカラーコード指定をオススメする。
使える色の名前の一覧は[公式APIリファレンス](https://discordpy.readthedocs.io/ja/latest/api.html?highlight=embed#colour)に載っている。

`from_rgb()`を使えばRGB値から、`from_hsv()`を使えばHSV値から指定することも出来る。

```python:RGB、HSVから色を指定
embed = discord.Embed(title="Hi!!",description="I got a special color!",color=discord.Colour.from_rgb(255,0,0))
embed = discord.Embed(title="Hi!!",description="I got a special color!",color=discord.Colour.from_hsv(0,100,100))
```
この場合はどちらも枠が赤くなる。

#フィールドの追加~add_field()
`add_field()`でEmbedにフィールドを追加できる。

```python:要素の追加
embed.add_field(name="フィールドの名前",value="フィールドの値")
```
以下のようにEmbedを作成して送信すると画像のようになる。

```python
embed = discord.Embed(title="Nice",description="to")
embed.add_field(name="meet",value="you")
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/444993/8aa6e8f4-477b-2ac8-253e-0618a20353be.png)

##フィールドのインライン表示
全体的に小さいフィールドを2つ以上追加した場合、画像のように横に並んで表示される場合がある。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/444993/b0e45b08-ded9-9162-8e1d-0564e03de797.png)
これは**インライン表示**と言い、複数のフィールドを一つの段にまとめることができる。
無効にしたい場合は、`add_field()`のキーワード引数、`inline`に`False`を指定する。

```python:インライン表示の無効化
embed = discord.Embed(title="There are",description="small fields")
embed.add_field(name="small1",value="small1",inline=False)
embed.add_field(name="small2",value="small2",inline=False)
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/444993/43201b33-a88a-25c0-3896-a3a5f72e0a21.png)

なお、インライン表示は指定が無い場合有効になる。

#画像の埋め込み~set_image()
`set_image()`で画像を埋め込むことができる。

```python:画像埋め込み
embed.set_image(url="画像url")
```
画像urlは、先頭がhttpかhttpsの物のみ使える。
画像はEmbedの下部、フッターテキスト(後述)の上に埋め込まれる。
例えば、Discordのデフォルトアバターを埋め込むと画像の様になる。

```python:デフォルトアバターを埋め込む
embed = discord.Embed(title="this is",description="default avatar")
embed.set_image(url="https://cdn.discordapp.com/embed/avatars/0.png")
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/444993/c8e3a42f-5299-0e51-5600-5b649b720525.png)

#サムネイルの設定~set_thumbnail()
`set_thumbnail()`でサムネイルを設定できる。
書き方は`set_image()`の時と同じ。

```python:サムネイル設定
embed.set_thumbnail(url="画像url")
```
サムネイルは通常、Embedの右上に配置される。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/444993/8d0c1a45-7f06-7cd1-a251-95efd2b92601.png)

#作成者の設定~set_author()
`set_author()`でEmbedの作成者を設定できる。
「作成者」とあるが、ヘッダーテキストのような物と考えた方が良い。

```python:作成者の設定
embed.set_author(name="名前",url="埋め込むurl",icon_url="アイコンのurl")
```
`name`に指定した値がヘッダーテキストとして扱われる。
`url`には、urlを指定するとヘッダーテキストにurlが埋め込まれる。
`icon_url`には、画像urlを指定すると左上にアイコンが表示されるようになる。

次のように作成者を設定すると画像のようになる。

```python
embed = discord.Embed(title="vege",description="table")
embed.set_author(name="Poteto143`s profile",url="https://qiita.com/Poteto143",icon_url="https://cdn.discordapp.com/embed/avatars/0.png")
embed
```
一見するとリンクが出来てないように見えるが、マウスポインターを置くとしっかりとリンクになっているのが分かる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/444993/6f15dc9c-8a49-2a9b-2746-419858615673.png)

#その他汎用的な関数
##Embedをコピー~copy()
Embedの情報をコピーし、同じ内容を持つEmbedを返す。
テンプレートとなるEmbedを用意し、そこから個別に手を加えて使い回すという処理ができる。
##フィールドをクリア~clear_fields()
サムネイルや画像などを維持し、フィールドを全て削除する。
##指定したフィールドを削除~remove_field()
Embedのフィールドを、インデックス指定で一件削除する。
0が先頭。

```py
embed.remove_field(0)#先頭のフィールドを削除
embed.remove_field(len(embed.fields()) - 1)#末端のフィールドを削除
```
##既存のフィールドを編集~set_field_at()
第一引数に指定するフィールドのインデックス番号をint型で渡し、それ以降の引数は`add_field()`と同様。

```py
embed.set_field_at(2, name="hello", value="world", inline=False)#三番目のフィールドを書き換え
```

#フィールドを任意の場所に挿入~insert_field_at()
第一引数に、フィールドを挿入したい場所のインデックス番号をint型で渡し、それ以降の引数は`add_field()`と同様。


```py
embed.insert_field_at(2, name="hello", value="world", inline=False)#三番目のフィールドの前に新しく要素を挿入する
```
##作成者の削除~remove_author()
前述の`set_author()`でセットした制作者の情報をEmbedから消す。

##Embedを辞書型に変換~to_dict()
Embedの情報をPythonの辞書型にまとめる。
この関数が返す値を保存し、クラスメソッドである`Embed.from_dict()`の引数に渡すと辞書の情報からEmbedを作る事が出来る。

#他に覚えておくと良いこと
`title`,`description`,`colour`はEmbedを定義した後も以下の様に書き換え可能。

```py
embed = discord.Embed(title="hello", description="wolrd")
embed.title = "goodbye" #embedのタイトルがgoodbyeに書き変わる
```
また、以下の様にすることでEmbedに含まれる画像や埋め込まれている動画[^2]の情報も取得できる。

```py
embed.image.url #埋め込まれた画像のURLを取得する
embed.video.url #埋め込まれた動画のURLを取得する
```

`Message.embeds`を使うと、メッセージに含まれる**Embedのリスト**を取得できる。
なお、リストで返される理由はWebhookを通して送信したメッセージは複数のEmbedを持つことが可能だからだ。

#便利なサイト
[公式APIリファレンス](https://discordpy.readthedocs.io/ja/latest/api.html?highlight=embed#embed)・Discord.pyの仕様がまとめられた公式のサイト。ここではEmbedの項目にリンクしている。
[Discord Embed Generator](https://cog-creators.github.io/discord-embed-sandbox/)・分かりやすいインターフェースでEmbedの可視化が出来る。
Googleのカラーピッカー・Googleで「カラーピッカー」と検索するだけで使える。枠の色を決めるときに使える。
[^1]: 2019年4月のrewrite版正式リリースにより、サポートが終了したため。詳しくは[こちらの記事](https://qiita.com/1ntegrale9/items/f4c47a6a69ecf23fc5db)を参照
[^2]: 動画を埋め込んだEmbedはYoutubeなどのURLを送信したときに自動で発生するEmbedのみであり、現在Discord.pyを用いてこれらを自分で作り出すことは出来ない。