⛳
YouTubeの更新通知をPubSubで受け取ってDiscordに通知してみた
作るに至った経緯
YouTubeの特定のチャンネルの更新のみをDiscordで受け取りたいって思ったから。DiscordのBotを作った後に、他にWebhookを使って送信してくれることができるらしいと分かったので使ってみたかった。
技術スタック
- Google Cloud Run functions
- PubSubHubBub
- Discord Webhook
- Python(functions-framework, flask)
- (YouTube Data API)
仕組み
- Google Cloud Run functionsでHTTPトリガーの関数をデプロイしておく。PubSubHubBubで購読確認のリクエストをhub.mode==subscribeの時だけ、hub.challengeをbodyに入れて返す事で購読確認を行う。WebSub(Pub/Sub)の仕組みについては、参考文献に置いてあるURLを参照してください。簡単に言うと、更新通知などのメッセージ送信をCDNで行ってくれるみたいな感じです。
- DiscordはWebSocketでリアルタイムにメッセージの送受信やアクションを行うことがメインですが、Webhookを使うことで、特定のチャンネルにメッセージの送信を行うことができます。
作ったもの
Google Cloud Run functionsのHTTPトリガーの関数を作り、下のコードをソースに入れる。
import functions_framework
from flask import make_response
@functions_framework.http
def main(request):
# 購読確認リクエスト処理
if "hub.mode" in request.args and request.args["hub.mode"] == "subscribe":
challenge = request.args.get("hub.challenge")
if challenge:
response = make_response(challenge)
response.headers["Content-Type"] = "text/plain"
response.status_code = 200
return response
else:
response = make_response("Invalid request", 400)
return response
# 実際のリクエスト処理
return "Hello Request"
認証リクエストとして、HTTPのGETメソッドでURLが送られてくるのでrequest.urlのクエリパラメータにhub.mode
とhub.challenge
があり、そのmodeがsubscribeの時であればchallengeをレスポンスのbodyに入れて返すようにするだけで購読確認ができる。
DiscordのBotは基本的にはWebSocketで通信を行ってるが、Webhookを使うことでエンドポイントのみの指定でこちらのアプリが立ち上がっているかどうかに関わらず送れるのでそれを使う。
Discordのアプリを作成して、Botとしての設定を行う。
OAuth2の設定で、
Scopeをbot
にチェックする。すると、下の方に更にカテゴリが出てくる。
出てきたカテゴリのBOT PERMISSIONSSのGENERAL PERMISSIONSのSend Messages
とTEXT PERMISSIONSのView Channel
とEmbed Links
をチェックする。
躓いた所
- Google Cloud Run functionsのトリガーとして、Pub/SubがあるがこれはWebSub(PubSubHubBub)とは違うので購読確認にはHTTP通信でGETリクエストが送られてくるということを理解していなかったのでずっと違う所を見ていた。
- Functionsのfunctions-frameworkがflaskを元にしているとあったが、
import flask
をしていなくてHTTPレスポンスが上手く返せていない状況だった。 - 購読確認リクエストというのが何かを理解していなくて、GETリクエストで送られてきたURLのクエリパラメータからhub.modeやhub.challengeを取得しなければならないことが分かっていなかった。
- そもそもBotを作るまで行くとそこまで必要ではないことが分かったので、Webhookで情報を伝えるだけで良かった。
- WebhookのエンドポイントURLにjsonで纏めて伝えるだけでよかったと思ったが、認証リクエストとして購読確認のリクエストを返さないといけないので作れそうになかった。
Discussion