pythonからDiscordのwebhookでメッセージ投稿する備忘録


最近RaspberryPi上でpython走らせてDiscordにメッセージ投稿する・・・
みたいなのをチョコチョコ作ってるのに毎度毎度躓く。
悩みたいのはそこじゃない。

公式ちゃんと読めよって話ですが、サンプル殆ど載っていないので備忘録。

参考

DiscordにWebhookでいろいろ投稿する
Webhook Resource
file
Visualizer and validator for Discord embeds.
Videos in Rich Embeds

材料

python3:3.7.3
json:2.0.9
requests:2.21.0
添付ファイルサンプルとして:ブランドガイドライン

メッセージだけ

import json
import requests

WEBHOOK_URL = "うえぶふっくURL?wait=true"

payload = {
    "username"      : "メッセージ",
    "content"       : "だけだよ。",
    "avatar_url"    : "https://github.com/qiita.png",
}

### メッセージだけ
res = requests.post( WEBHOOK_URL, json=payload )
print( res.status_code )
print( json.dumps( json.loads(res.content), indent=4, ensure_ascii=False ) )

application/jsonjson指定するだけ。
webohook URL に?wait=trueを付けてあげるとcontent返してくれる。付けないとstatus_codeが204、content返ってこない。
チャンネル下のスレッドに投下したいなら、thread_idも付けてやる。アーカイブ済のスレッドは自動でアーカイブ解除してくれるらしい。
スレッドIDを取得するには「ユーザー設定」→「アプリの設定」→「詳細設定」で「開発者モード」をONにすると表示される「IDをコピー」メニューでコピーするのが手っ取り早い。
それぞれWebhookURLに繋げるとこんな感じ。
https://discord.com/api/webhooks/{webhookID}/{webhookトークン}?wait=true&thread_id={スレッドID}

添付ファイルだけ

import json
import requests

WEBHOOK_URL = "うえぶふっくURL?wait=true"

### 画像添付
with open("favicon.png", 'rb') as f:
    file_bin = f.read()
files_qiita = {
    "favicon" : ( "favicon.png", file_bin),
}
res = requests.post( WEBHOOK_URL, files = files_qiita )
print( res.status_code )
print( json.dumps( json.loads(res.content), indent=4, ensure_ascii=False ) )

multipart/form-data、バイナリreadしてfilesに指定するだけ。
wait付くなくてもcontent返ってくる。

メッセージ+embed+添付ファイル

import json
import requests

WEBHOOK_URL = "うえぶふっくURL?wait=true"

payload2 = {
    "payload_json" : {
        "username"      :"メッセージと、",
        "content"       :"添付ファイルと、",
        "avatar_url"    : "https://github.com/qiita.png",
        "embeds": [
            {
                "title"         : "payload_json",
                "description"   : "embedsそのまま使うと怒られる。代わりにpayload_jsonに全部ぶち込んで文字列にdumpしたら良さげ。ensure_ascii=False 無くても多分大丈夫。",
                "url"           : "https://birdie0.github.io/discord-webhooks-guide/structure/file.html",
                "timestamp"     : "2020-08-22T15:18:00+0900",
                "color"         : 5620992,
                "footer": {
                    "icon_url"  : "attachment://favicon.png",
                    "text"      : "Qiita",
                },
                "thumbnail": {
                    "url"       : "attachment://logo-background-color.png"
                },
                "image": {
                    "url"       : "attachment://logo-effect-background-color.png"
                },
                "author": {
                    "name"      : "embedと。",
                    "url"       : "https://qiita.com/",
                    "icon_url"  : "attachment://favicon.png",
                },
                "video": {
                    "url"       : "https://www.youtube.com/embed/q05aeEf17Kc"
                },
                "fields": [
                    {
                        "name"  : "添付画像を",
                        "value" : "embedsで使うと別表示しなくなるっぽい。",
                        "inline": True,
                    },
                    {
                        "name"  : "attachment:",
                        "value" : "embedの中でしか添付使えないっぽい。",
                        "inline": True,
                    },
                    {
                        "name"  : "Visualizer and validator for Discord embeds.",
                        "value" : "日本語入れたら怒らたけど、color pickerが地味に便利。",
                    },
                    {
                        "name"  : "Youtubeの",
                        "value" : "[埋め込みは無理っぽい](https://support.discord.com/hc/en-us/community/posts/360037387352-Videos-in-Rich-Embeds)\nvideo URL 指定しても無視される。",
                    },
                ],
            }
        ]
    }
}

### embed付き
with open("favicon.png", 'rb') as f:
    file_bin_favicon = f.read()
with open("logo-background-color.png", 'rb') as f:
    file_bin_logobg = f.read()
with open("logo-effect-background-color.png", 'rb') as f:
    file_bin_logoeffect = f.read()
files_qiita  = {
    "favicon" : ( "favicon.png", file_bin_favicon ),
    "logo_bg" : ( "logo-background-color.png", file_bin_logobg ),
    "logo_effect" : ( "logo-effect-background-color.png", file_bin_logoeffect ),
}
payload2['payload_json'] = json.dumps( payload2['payload_json'], ensure_ascii=False )
res = requests.post(WEBHOOK_URL, files = files_qiita  , data = payload2 )
print( res.status_code )
print( json.dumps( json.loads(res.content), indent=4, ensure_ascii=False ) )

multipart/form-data
添付ファイルは前項同様filesに指定。メッセージ内容の方は公式読んでもフワっとしててハッキリ分からない。
添付ファイルを付ける場合embedとかそのまま使うと怒られる。代わりにpayload_jsonに全部入れてdumpして文字列化、dataに指定。これで何とかなった。
添付した画像ファイルはembeds内では使えたが、avatar_urlには使えなかった。
Embed Objectvideoは居たので youtube URL を試してみるが、現状webhookには使えなさそう。
wait付くなくてもcontent返ってくる。
実際に投稿するとこんな感じ。