Discord.NETでEmbedを使ってみた

##初めに
C#でDiscord Botを作っている際に**Embed(埋め込みメッセージ)**を作成したいなぁと思い、参考記事を探してみたのですが、出てくるのはDicord.pyやDiscord.jsの記事ばかり、、、
そんな中、いろいろなDiscord Bot(C#)の記事を見ていると、[コードの一部にEmbedを使っている記事](https://qiita.com/xxIN0xx/items/9cb561f1765d427957a9)を見つけ、それを参考に質問サイトや[Embed APIドキュメント](https://docs.stillu.cc/api/Discord.Embed.html)などを見ながらいろいろ試してみてたらEmbedを作成できたので自分のメモ用がてら書いておこうと思いました。

まだBotを作っていない人やBotをまだ動かせていない人は、他の方のBotの作り方の参考記事がいくつかあるのでそちらを参考にしてみてください。

**・Discord Bot 作り方（C#）参考記事**
記事1 :[【C#】Discord .NETでbotを作る](http://atriasoft.work/cs/537)
記事2 : [DiscordのBotをC#で作ってみる](https://qiita.com/HAGITAKO/items/fff2e029064ea38ff13a)
記事3 : [C#でDiscord BOTを作る方法](https://kagasu.hatenablog.com/entry/2017/07/18/113335)

ちなみに私は記事1を参考にBotを作りました。


##Embed（埋め込みメッセージ)とは
・<font color="Red">ユーザーが使用することができず、botにしか作れません</font>
・複数の情報をまとめて出力することができる便利な機能です
![Embedスクショ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1477630/21418e62-8650-6f1f-7996-3ea9f9f3d9b3.png)


##開発環境
Visual Studio 2019
Discord.Net 2.2.0

##Embedの作成の流れ
**1. Embedオブジェクトの定義**
**2. 埋め込み要素の作成**
**3. 作成したEmbedをメッセージとして送信する**


##1. Embedオブジェクトの定義
```c#
var embed = new EmbedBuilder();
```

##2. 埋め込み要素を作成

###・タイトルの追加（WithTitle）

文字が太字で大きめなのでタイトルなどに使えます。

```c#
embed.WithTitle("タイトル");
```

###・説明文などの追加（WithDescription）

説明などの長文など載せるのに使えます。

```c#
embed.WithDescription("ここに説明など");
```


タイトルと説明文を書くとこんな感じになります↓
![説明文.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1477630/f7bfbb6c-f51c-7009-8ac7-71df2878bac8.png)



###・左側のバーの色の設定（WithColor）

Color構造体を使って左側のバーの色を指定することができます。

```c#
embed.WithColor(Color.Green);
```
![Green.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1477630/9693e8f6-c0b1-18a5-d114-e0f401d1773b.png)


また、さらに細かい色の設定をしたい場合は、16進数カラーコードを指定することでできます。
自分の設定したい色の16進数のカラーコードを知りたい場合、[こちらのサイト](https://www.ltool.net/html-color-charts-rgb-color-table-in-japanese.php)が便利です。


![ColorPink16進数.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1477630/241b418f-8dad-9423-4912-4b8f02c066d6.png)
上記のサイトで取得したカラーコード(#E800B9)
<font color="Red">※コードは「#」を「0x」に置き換えて書いてください。</font>カラーコードのアルファベットは小文字でも大丈夫です。

```c#
embed.WithColor(0xE800B9);
```

![Pink.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1477630/ad238ce5-77b2-5730-3dbc-731a8d6d8f43.png)


###・フィールドの追加（AddField）

フィールドを追加できます。また、第3引数に<font color="Blue">true</font>を持たせることでフィールドを横に最大3つまで並べることが可能です。(無効にしたい場合は<font color="Blue">false</font>を指定してください。)
しかし、スマホの画面など画面の小さいサイズでは2列または、1列で表示されてしまいます。

```c#
embed.AddField("フィールド1", "値1", true);
embed.AddField("フィールド2", "値2", true);
embed.AddField("フィールド3", "値3", false);
embed.AddField("フィールド4", "値4", true);
embed.AddField("フィールド5", "値5", true);
embed.AddField("フィールド6", "値6", true);
```



PCの画面の場合
![フィールドPC.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1477630/5d380dc8-c493-29d1-0086-bc2a86510aaa.png)

スマホの画面の場合
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1477630/c9bfcd40-3776-f896-2f47-3ae7d5bf3b08.png" width=40%>


リンクを貼ったりすることもできます。[タイトル]\(URL)という文字列を記入することでリンクとして認識されます。

```c#
embed.AddField("YouTubeリンク", "YouTubeのリンクは [こちら](https://www.youtube.com/) をクリック。");
```

![フィールドリンク.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1477630/92d7d778-6875-635c-6cd5-198f2d54abc7.png)





###・画像の埋め込み（WithImageUrl）

画像URLを指定することで、下の大きい画像エリアにイメージを設定できます。

```c#
embed.WithImageUrl("https://example.com/sample/image.png");
```


###・サムネイルの埋め込み（WithThumbnailUrl）

画像URLを指定することで、右上の小さい画像エリアにサムネイルを設定できます。

```c#
embed.WithThumbnailUrl("https://example.com/sample/image.png");
```

![イメージサムネ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1477630/41ef66d9-e77e-e8ef-4b73-34102f1c0383.png)


お借りした画像URL
Image : [可愛いナマケモノのイラスト - 面白い動物無料素材](https://chicodeza.com/freeitems/namakemono-illust.html)
Thumbnail : [Wikipedia C# ロゴ](https://ja.wikipedia.org/wiki/C_Sharp#/media/%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB:C_Sharp_wordmark.svg)


###・ユーザー情報などの追加（WithAuthor）

作成者などのユーザー情報などを追加できます。また、第２引数に画像URLを指定することで、アイコンを設定できます。



```c#
embed.WithAuthor("name", "example.com/sample/image.png");
```

![Auther.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1477630/668fd3c8-4806-1582-cbb7-3cc067e53952.png)
メッセージを送信したユーザーのユーザー名とそのユーザーアイコンを取得し、設定することもできます。それについては最後のサンプルコードを参考にしてください。

###・フッターの追加（WithFooter）

フッターに文字列などを追加できます。また、第２引数に画像URLを指定することで、アイコンを設定できます。

```c#
embed.WithFooter("footer", "example.com/sample/image.png");
```

![フッター.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1477630/9c474127-dfc0-d7ec-2e1e-336390d7b0c3.png)


###・タイムスタンプの追加（WithTimestamp）

日時・日付・時刻などを示す文字列を追加できます。

```c#
embed.WithTimestamp(DateTime.Now);
```

![タイムスタンプ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1477630/31101a4f-9024-5b7e-ca7b-db5daa49734e.png)

##3. 作成したEmbedをメッセージとして送信する
SendMessageAsyncなどを使い、作成したEmbedをbotに送信させます。

```c#
await message.Channel.SendMessageAsync("テスト", embed: embed.Build());
```

##サンプルコード

Discord上のサーバーでユーザーが「test」と送信するとEmbedの作成し、それをメッセージとして返信させます。

```c#:サンプルコード
using System;
using System.Reflection;
using System.Threading.Tasks;
using Discord;
using Discord.Commands;
using Discord.WebSocket;
using Microsoft.Extensions.DependencyInjection;

namespace EmbedTest
{
    class Program
    {
        private DiscordSocketClient _client;
        public static CommandService _commands;
        public static System.IServiceProvider _services;

        static void Main(string[] args)
            => new Program().MainAsync().GetAwaiter().GetResult();

        public async Task MainAsync()
        {
            _client = new DiscordSocketClient(new DiscordSocketConfig
            {
                LogLevel = LogSeverity.Info
            });
            _client.Log += Log;
            _commands = new CommandService();
            _services = new ServiceCollection().BuildServiceProvider();
            _client.MessageReceived += CommandRecieved;
            //DiscordTokenを指定
            string token = "Token";
            await _commands.AddModulesAsync(Assembly.GetEntryAssembly(), _services);
            await _client.LoginAsync(TokenType.Bot, token);
            await _client.StartAsync();

            await Task.Delay(-1);
        }

        /// <summary>
        /// 何かしらのメッセージの受信
        /// </summary>
        /// <param name="msgParam"></param>
        /// <returns></returns>
        private async Task CommandRecieved(SocketMessage messageParam)
        {
            var message = messageParam as SocketUserMessage;

            //デバッグ用メッセージを出力
            Console.WriteLine("{0} {1}:{2}", message.Channel.Name, message.Author.Username, message);
            //メッセージがnullの場合
            if (message == null) return;
            //発言者がBotの場合無視する
            if (message.Author.IsBot) return;
            var context = new CommandContext(_client, message);
            var CommandContext = message.Content;

            //メッセージを送信したユーザー名の取得
            var author = message.Author.Username;
            //メッセージを送信したユーザーのアイコンの取得
            var authorIcon = message.Author.GetAvatarUrl();
            //メッセージを送信したユーザーのメンション
            var autherMention = message.Author.Mention;
            var now = DateTime.Now;

            //Embedオブジェクトの定義
            var embed = new EmbedBuilder();

            if (CommandContext == "test")
            {
                //埋め込み要素を作成
                embed.WithTitle("タイトル");
                embed.WithDescription("ここに説明など");
                embed.WithColor(Color.Green);                
                embed.AddField("フィールド1", "値1", true);
                embed.AddField("フィールド2", "値2", true);
                embed.AddField("フィールド3", "値3", true);
                embed.AddField("フィールド4", "値4", true);
                embed.AddField("フィールド5", "値5", true);
                embed.AddField("フィールド6", "値6", true);
                embed.AddField("YouTubeリンク", "[こちら](https://www.youtube.com/) をクリック。");
                embed.AddField("Yahooリンク", "[こちら](https://www.yahoo.co.jp/) をクリック。");
                embed.AddField("Googleリンク", "[こちら](https://www.google.com/) をクリック。");
                embed.AddField("メンション", autherMention);
                embed.WithImageUrl("example.com/sample/image.png");
                embed.WithAuthor(author, authorIcon);
                embed.WithThumbnailUrl("example.com/sample/image.png");
                embed.WithFooter("footer", "example.com/sample/image.png");
                embed.WithTimestamp(now);

                // 作成したEmbedをbotに送信させる。
                await message.Channel.SendMessageAsync("テスト", embed: embed.Build());
            }
        }

        private Task Log(LogMessage message)
        {
            System.Console.WriteLine(message.ToString());
            return Task.CompletedTask;
        }
    }
}
```

###実行結果

![サンプル.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1477630/6fc40901-9af9-74bf-3176-bf467a69320f.png)

<font color="Red">※Embedの中はすべての場所でメンションが使えるわけではないので注意が必要です。</font>
参考：[埋め込みの中でメンションを使える場所](https://scrapbox.io/discordjs-japan/%E5%9F%8B%E3%82%81%E8%BE%BC%E3%81%BF%E3%81%AE%E4%B8%AD%E3%81%A7%E3%83%A1%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%B3%E3%82%92%E4%BD%BF%E3%81%88%E3%82%8B%E5%A0%B4%E6%89%80)

##最後に
Embedは複数の情報をコンパクトにまとめて出力することができるためとても魅力的です。Embedを作る際は、埋め込み要素をすべて使う必要はないので、自分の使いたい要素をピックアップして作ってみてください。また、Discord.pyやDiscord.jsの記事でもコードの書き方は違いますが、Embedを使ってどのようなことができるのか、参考になる記事もあるのでいろいろ見てみるといいと思います。

##<font color="Red">追記(2021/5/20)</font>
Embedオブジェクトを定義するときに埋め込み要素を指定しておくことができるということを書いていなかったので簡単に書いておきました。
→[Embedオブジェクトを定義するときに埋め込み要素を指定する。](https://qiita.com/Miyakepp_098/items/fb0081d1e44e1beff597)

##参考文献
・[【C#】Discord .NETでbotを作る](http://atriasoft.work/cs/537)
・ [DiscordBotをC#で作ってAzureで公開してみた](https://qiita.com/xxIN0xx/items/9cb561f1765d427957a9)
・ [Embed APIドキュメント](https://docs.stillu.cc/api/Discord.Embed.html)
・ [色名表記→16進表記の変換](https://www.atmarkit.co.jp/fdotnet/dotnettips/239colorconv/colorconv.html
)