Perlで素早くMastodon(OStatus)インスタンス風のものを立てる(2)(MojoliciousでPubHubSubbub)

|

前回 PubSubHubbub経由で更新を受け取るところまではいけたのだけど、Sojolicious絡みでOStatusに必要な機能がMojoliciusプラグインとして存在しているので、それを利用するために出来ればMojoliciousベースにしたい。ということで、 Mojolicious::Plugin::PubSubHubbub(以下M::P::PuSH)ベースに書き直したのでメモ。

試行錯誤

subscribe自体は問題なさそうなんだけど、いざ更新通知を受け取ろうとすると:

[Thu Apr 20 20:03:39 2017] [debug] POST "/callback"
[Thu Apr 20 20:03:39 2017] [debug] Routing to a callback
[Thu Apr 20 20:03:39 2017] [warn] Unsupported media type: unknown
[Thu Apr 20 20:03:39 2017] [debug] 400 Bad Request (0.000907s, 1102.536/s)

という感じでエラーになってしまう。

モジュールのソースを追った結果、どうやらmastodonは更新通知を送るときにContent-Typeを設定しないらしい。M::P::PuSHは更新通知にAtomとRSSを両方受け付けるようになっていて、Content-Typeを見て処理を切り替えるのだけど、Content-Typeが設定されていないとエラーを返すらしい。

実際のところ更新通知にどのようなフォーマットを使うかというのはPubSubHubbubにもOStatusにも規定がない(このあたりが相互運用性が怪しいと言われる所以)ので一概にM::P::PuSHが悪いとも言えないのだけど、とりあえず今はmastodonの更新通知を受け付けられないと困るので:

diff -aur liborig/Mojolicious/Plugin/PubSubHubbub.pm lib/Mojolicious/Plugin/PubSubHubbub.pm
--- liborig/Mojolicious/Plugin/PubSubHubbub.pm  2017-04-20 22:36:36.857296800 +0900
+++ lib/Mojolicious/Plugin/PubSubHubbub.pm  2017-04-20 22:38:12.216751100 +0900
@@ -625,7 +625,8 @@
   my $c      = shift;
   my $log    = $c->app->log;

-  my $ct = $c->req->headers->header('Content-Type') || 'unknown';
+  # fallback to atom
+  my $ct = $c->req->headers->header('Content-Type') || 'application/atom+xml';
   my $type;

   # Is Atom

というパッチを当てたらうまく動いた。

結果

ファイル一式をgistに置いた。依存関係があるのでまず:

cpanm Mojolicious::Plugin::PubSubHubbub

としておいた後、gistの二つのファイルを

./lib/Mojolicious/Plugin/PubSubHubbub.pm
./app.pl

の形になるように置いて、app.pl内の設定を変更した後:

morbo app.pl

として起動。前回同様/subsribeにアクセスすると購読開始、この状態で発言すると標準入力に通知Atomが表示される。/unsubscribeにアクセスすると購読終了。

まとめ

前回基本部分は確認してたのでM::P::Pushでもすぐに出来るだろう、と思ったらモジュールが想定より厚い作りだったのでちょっと手間取った。やっぱり試してみないと分からないもんだ。というか前回基本部分確認できてなかったらもっと苦労してただろうなあ。

受信はこれでだいたい分かったけどやっぱりおひとりさまインスタンスは送信だと思うので、次はその辺を調べてみたい。まずはリモートフォローされる方法かな…。