58
41

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Discord BotAdvent Calendar 2020

Day 6

初心者に捧ぐDiscordのEmbed入門

Last updated at Posted at 2020-12-05

はじめに

この記事はDiscordBotアドベントカレンダー2020の6日目の記事です。
今回は、DiscordBotのメッセージ出力方法の一つ、Embed(埋め込み)メッセージについて書こうと思います

Embed事始め

御存知の通りEmbedはDiscord上にリンク・文字・画像といった複合的要素をレイアウトして送信できるメッセージ形態です。
しかし皆さんはEmbedをどれくらい使っているでしょうか。
大抵のBot作成初心者さんは初めてのBotの出力を以下のようにプレーンテキストメッセージで実装しているのではないでしょうか1

await message.channel.send("Hello!")

Embedは項目が多く、導入が難しいという初心者さんの声も聞かれますが、食わず嫌いは非常にもったいないです!
Embedメッセージを一度でも使うとその魅力に縛られ手放せなくなります。
今回は、Bot作成を初めて日が浅く、上記コードの出力を主としているような人に、Embedを布教するための記事になりそうです。

Embedを使用できるのはBotのみ

非常に優秀な機能なのでぜひ我々人間も使いたいところですが、現状人間ユーザーアカウントはEmbedを作成できません。
自由にEmbedを操る力はBotの特権です。2

Botの出力はEmbedを使いたい

私はBotに出力させるメッセージは、特に理由がない限りEmbedを使用することをオススメしたいです。
Botは普通にメッセージを送信できるのになぜEmbedなのか、それは
通常メッセージに比べて 圧倒的に視認性が高い事が挙げられます。
次項で触れていきますが、EmbedはBotの出力に適した特徴がたくさんあるのです。
せっかくBotに与えられた特権機能、フルに活用して使いやすいBotを作ってみませんか?

Embedのメリット

複数種類の情報を出力できる

Embedには、名前と値のセットであるfieldを最大25セットまで追加したり、画像をimagethumbnailの大小2種類埋め込むことも可能です。

Botの情報をコンパクトに格納できる

Embedのauthorエリアにはリンクも含めたbotや開発者の情報を記載できます。連絡先をリンクしておくとフィードバックが手軽かつスムーズになるかもしれません。

フレーム色設定(後述)でメッセージの種類を視覚的に分類できる

Embedの特徴の一つが、左端の細いバーでしょう。実はこのバー、色を自由に変更できます。
これを利用して、正常な実行結果の緑、情報出力の青、エラーメッセージの赤、のようにバーの色の切り替えでメッセージの種類をよりわかりやすいものにできるでしょう。

(画像: エラーメッセージを赤色フレームで表示する例
image.png

Embedの構成要素

Embedには具体的にどんなパラメータがあるのか、主な要素を表にしてみました。

説明 上限
title Embedのタイトル 256文字
description Embedの説明。小さめの文字でレイアウトされる 2048文字
color Embedフレーム左のバーの色
author Embed作成者の情報エリア 256文字
thumbnail 小さい画像エリア
field nameとvalueのセットからなるEmbedのメインコンテンツ field数 : 25セット
name :256文字
value : 1024文字
image 大きな画像エリア
footer フッター。開発者情報やライセンス等を記載できる 2048文字

discord.pyでEmbedサンプルコード

embed.py
import discord

client = discord.Client()
@client.event
# 今回はon_readyでログイン時に指定チャンネルにEmbedを送信させていますが、on_messageでユーザー入力に反応するときも要領は同じです。
async def on_ready(): 
    embed = discord.Embed( # Embedを定義する
                          title="Example Embed",# タイトル
                          color=0x00ff00, # フレーム色指定(今回は緑)
                          description="Example Embed for Advent Calendar", # Embedの説明文 必要に応じて
                          url="https://example.com" # これを設定すると、タイトルが指定URLへのリンクになる
                          )
    embed.set_author(name=client.user, # Botのユーザー名
                     url="https://repo.exapmle.com/bot", # titleのurlのようにnameをリンクにできる。botのWebサイトとかGithubとか
                     icon_url=client.user.avatar_url # Botのアイコンを設定してみる
                     )

    embed.set_thumbnail(url="https://image.example.com/thumbnail.png") # サムネイルとして小さい画像を設定できる

    embed.set_image(url="https://image.example.com/main.png") # 大きな画像タイルを設定できる

    embed.add_field(name="フィールド1",value="値1") # フィールドを追加。
    embed.add_field(name="フィールド2",value="値2")

    embed.set_footer(text="made by nashiroaoi", # フッターには開発者の情報でも入れてみる
                     icon_url="https://dev.exapmple.com/profile.png")

    channel = client.get_channel(CHANNEL_ID)

    await channel.send(embed=embed) # embedの送信には、embed={定義したembed名}

client.run(TOKEN)

実際に上記のEmbedを出力させてみます。
(画像URLはサンプルコードではプレースホルダになっているので具体的な値を入れています)
embed

テスト用にお借りした画像URL
thumbnail : Wikipedia pythonロゴ
image : 美雲このは壁紙3

Embedのfield詳解

Embedのメインコンテンツの一つであるfield要素。
discord.pyでもfield要素の構築に便利な色々な操作が可能です。
いくつか見ていきましょう。

add_field() -fieldの追加-

fieldをEmbedに追加するには、add_embed()メソッドを使用します。このメソッドにはnamevalueinlineの3つのキーワード引数を取ります。inlinebool型で、これがFalseになると、1行に1fieldが配置されます。デフォルトはTrueです。

inline=True inline=False
image.png image.png

insert_field_at() -fieldの挿入-

add_field()で作成された新しいfieldは常にEmbedの最後尾に追加されていきます。すでに作成したfieldの間にあとからfieldを差し込みたいときは、insert_field_at()メソッドを使います。
add_field()メソッドと同じ3種類の引数に加え、挿入地点を指定するindex引数を取ります。
indexの値は0スタートであることに注意してください。
つまり、先頭フィールド(1番目)は0、2番目フィールドは1です。

embed.add_field(name="name1", value="value1")  # フィールド1を追加
embed.add_field(name="name2", value="value2")  # フィールド2を追加
embed.insert_field_at(1, name="name3", value="value3")  # フィールド3を先頭から 2 番めに挿入

結果、insertしたfield3はfield2より後に書かれたにもかかわらず、先頭から2番めに入り込んでいます。
image.png

set_field_at() -fieldの編集-

このメソッドは、追加したfieldを新しいデータで上書きします。add_field()の引数3つに加え、上書きしたいfieldを指定するindex引数を取ります。

remove_field() -fieldの削除-

既に作成したfieldを削除するメソッドです。削除したいfieldを指定するindex引数を取ります。

clear_fields() -fieldの全削除-

Embed内の全fieldを削除します。引数は取りません。

Embedハマりどころ

便利なEmbedですが、使用する上で注意が必要なポイントもいくつかあります。
私が過去実際ハマったものを中心に、Embed周りのトラブルを見ていきましょう。

Embedの表示がスマホで崩れる

スマホ(android)アプリでEmbed出力を表示したとき、Embedの表示が崩れ、極端な縦長になったりすることがあります。
私の調査の限りでは残念ながら対処法を発見することができませんでした。

Bad Requestエラーが出て送信できない

考えられる原因はいくつかあります。

文字数制限

Embedには極端に大量の送信がされることを防ぐため、テキストメッセージの制限(2000字)のようにEmbedにもいくつかの制限があります。
Embedの構成要素の文字数制限のほか、Embed内の文字総数が6000字以上になるとBad Requestが発生し、送信できません。

field情報の欠落

add_field()メソッドには、namevalueの2種類の引数が必須となります(inlineはデフォルト値Trueが適用されます)。
箇条書きを表現したくて、nameだけ、valueだけ、のfieldを追加しようとすると、Bad Requestが発生します。
箇条書きを表現したいときでも、両方に何かしら値を入れてやらなければいけません。
私がよくやる手として、nameに絵文字や中黒などを入れる方法があります。

ローカルの画像を埋め込みたい

Embedの画像thumbnailやimageは、画像をURLで指定するためローカルの画像を埋め込むにはひと手間必要になります。
実際の流れを見てみましょう。

import discord

client = discord.Client()

@client.event
async def on_ready():
    embed = discord.Embed(title="Local Image") # まずは普通にEmbedを定義
    fname="upload.png " # アップロードするときのファイル名 自由に決めて良いですが、拡張子を忘れないように
    file = discord.File(fp="ローカル画像パス",filename=fname,spoiler=False) # ローカル画像からFileオブジェクトを作成
    embed.set_image(url=f"attachment://{fname}") # embedに画像を埋め込むときのURLはattachment://ファイル名
    channel = client.get_channel(CHANNEL_ID)
    await channel.send(file=file, embed=embed) # ファイルとembedを両方添えて送信する

client.run(TOKEN)

より詳しい情報は公式リファレンスを参照ください。

あとがき

起承転結のないぶった切りな終わり方ですが、そろそろ筆を置こうとおもいます。
Embedを使うのは決して難しくはありません。もしそう思えるとしたらそれはEmbedの構成を把握しきれないことで圧倒されているのだと思います。
多くの項目を設定できるEmbedですが、各要素をすべて使う必要はありません。中には必要性の薄い要素や、出力内容次第ではむしろゴチャゴチャさせないために要素を省くべきケースもあります。
最初からフルに使いこなそうとはせず、出力したい内容を最小限埋め込んだシンプルなものから始めていくと良いと思います。
この記事が脱プレーンテキストメッセージのきっかけになれば執筆者冥利に尽きることです。

それでは少し早いですが、Merry Christmas!良いお年を。

  1. 断じてプレーンテキストメッセージが悪いわけではありません。が、今回はEmbed布教記事ということで少し下げさせてください。

  2. 人間ユーザーがリンクを送信したとき自動でリンク先のタイトルやサムネイルがEmbedとして生成されますが、あれは自由に操作できるとは到底言えないのでノーカンとします。

  3. conoHaの案件とかではありません。私の趣味です。

58
41
5

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
58
41

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?