概要
AWS Lambda の Python 3.7 ランタイムを使ってDiscordのWebhook URL を叩くと 403 でうまいこと叩けずに困った。
原因を調べたらどうやらUAをチェックしているらしく、UAが urllib だとNG。( 試しに使った curl はOK )
Discordのライブラリを入れればいいんだろうけど、Lambdaという都合上、ほか依存ライブラリ追加したくない。
UAをcurlに偽装することでうまいこと叩けた。よかったよかった。
反省
- うまくいくパターンとだめなパターンの差分はHTTPヘッダをみよ。
- APIがコケる場合にはちゃんとステータス値とレスポンスボディとマニュアルをみよ。
参照
Python3のスクリプトでjsonをPOSTする - Qiita
詳細
What is Webhooks
Discordにおいて、なにかあったら自動で特定のチャンネルにメッセージを送りたい。
なんでも Webhookってのが作られるらしく、それならシンプルにJSONをポストするだけでそういうことができる。
(本当はDMを送りたかったんだけど、そっちはAPI経由になってだるそうなんでヤメ)
How to get Webhook URL
たぶん管理者権限がいる。
- チャンネルの右側に表示されているギアをクリック
- 左のメニューから「連携サービス」をクリック
- 「ウェブフック」とあるのでそこの「詳細」 or 「ウェブフックを確認」をクリック
- 「新しいウェブフック」をクリック、ポストされるときの名前を指定し、チャンネルを指定
- 「ウェブフックURLをコピー」をクリックすればOK
試す
とりあえず POST はオオゴトなんでまずは GET から。curlを使って試す。
$ curl -v https://discordapp.com/api/webhooks/xxxxxxxx
略
< HTTP/2 200
略
{"type": 1, "id": "xxxx", "name": "xxxxx", "avatar": null, "channel_id": "xxxxxx", "guild_id": "xxxxxx", "application_id": null, "token": "xxxxxx"}
OK。エンドポイントが正しくあることは確認できた。
POSTを試す。
$ curl -v -X POST -H "Content-Type: application/json" -d '{"content":"ふぁらおからウェブフック経由のポストで参上"}' https://discordapp.com/api/webhooks/xxxxxxxx
でOK。
Pythonのコードから試す
以下で試せばOK。試しに urllib.request.Request
の第3パラメータの User-Agent
を削除してみてほしい。それだと弾かれてしまう。
url = "https://discordapp.com/api/webhooks/xxxxxxxx"
method = "POST"
headers = {"Content-Type" : "application/json"}
obj = {"content" : "ふぁらおからウェブフック経由のポストで参上"}
json_data = json.dumps(obj).encode("utf-8")
request = urllib.request.Request(
url,
json_data,
{"User-Agent": "curl/7.64.1", "Content-Type" : "application/json"},
method
)
with urllib.request.urlopen(request) as response:
response_body = response.read().decode("utf-8")
print(response_body)