流沙河鎮

情報技術系のこと書きます。

IFTTTでTwitterへの投稿をmstdn.jpにも転送する時の考慮点

Fediverseデビューしたものの即座にTwitterを離脱するのは難しそう。でもFediverse側も盛り上げていきたい。なので当面はTwitterとFediverse両方に同じ内容をポストしようとなるのだが、これがめんどくさい。そこで自動化することにした。(Twitterが国境を開放してくれればこんな事は考えなくていいのだが...)
ja.wikipedia.org
以下記事の手順を元にmstdn.jpで環境構築を試みたところ、mstdn.jpインスタンス特有の考慮点があった。Mastodonに普遍的な手順はこちらの記事に準じるので、これから試す人はまず見て欲しい。その上でそのままでは上手くいかない部分があるはずなので、そこで本エントリが役に立つはずだ。
www.mizdra.net

User-Agent問題

問題

Mastodonの一部インスタンスはUser-Agent (UA)によってリクエストを拒否する場合があるようで、mstdn.jpはIFTTTのwebhookがデフォルトで付与するUAに(恐らくcloudflareが)403を返すことが分かった。従って↑の記事の手順だけでは上手く動かない。
いくつかのクライアントで試した所、興味深いことにcURL(UA: curl/X.XX.X)では問題なくリクエスト可能で、Pythonのurllib(UA: Python-urllib/3.5)では403が返った。
この挙動についてmstdn.jpの規約類には記載がなく意図したものか不明だが、cURLのようなメジャーライブラリがデフォルトで設定するUAでは問題なく通る点、適当なUAを付与しても拒否されない点(後述)、そもそものAPI自体の存在意義を鑑みれば、不特定のUAが拒否されるのは正しい挙動ではなさそうに思われる。
halcy/Mastodon.pyでも問題になっているようだ。
github.com
github.com

対応

IFTTTでのシンプルな対策として、webhookのAdditional Headersで適当なUAを指定することでクリアした。付与するUAは本当に適当なものでよく、ぼくはTwitterToMstdn/1.0としてみた。
IFTTT上では以下のような設定となる。

mstdn.jpではbotでPublic に投稿するのはルール上NG

ルール

mstdn.jpの概要ページにはbotを運用する際のルールとして以下の記載がある。

また、ローカルタイムラインや連合タイムラインは、日常的に閲覧する用途に向いていないタイムラインではありますが、交流したい人を探す用途に用いられていることは確かですので、なるべく自動投稿の類が表示されることを避けたいと思っています。そこでmstdn.jpにBotを設置しようと考えている方々には、最低限以下の条件を守って頂きたいと思います:

Publicな投稿をしないこと(Unlisted, Private, Directを使ってください)
能動的に他のアカウントをフォローしに行かないこと
フォローしていない人のトゥートを自動でお気に入り登録したり、リプライを飛ばしたりしないこと

mstdn.jp

対応

TwitterMastodonへの二重投稿を目的にAPIを叩くのが本質的にbotと言えるのかは微妙に思えるものの、APIを叩いている点ではbot的と言えるし、二重投稿自体がコミュニティの歴史的にセンシティブな問題をはらむように見えたので郷に入っては何とやらということでvisibility=unlistedとすることにした。
statuses API methods - Mastodon documentation
unlistedの場合、ローカルタイムラインと連合タイムラインには表示されずホームタイムラインにのみ表示される形になる。今のところフォロワーに見えれば十分なので問題ないだろう。

  • ホームタイムライン: フォローしている人と自分のトゥートのみが流れる
  • ローカルタイムライン: サーバ内の全ユーザーのトゥートのうち、公開範囲が 「公開」 になっているものが流れる
  • 連合タイムライン: 他の連合先インスタンスのトゥートも含めて流れる

IFTTT上では以下のような設定となる。

供養

ここから先は特に読む必要ないのだが、当初IFTTTからmstdn.jpへのPOSTが拒否される原因がわからずIPアドレス等で拒否されているのではと考えたため、IFTTTからLambdaを叩いて、Lambdaからmstdn.jpのAPIを叩くピタゴラスイッチを実装した。が、Lambdaの実装を進める中でUAが原因と気付いたので全く徒労になってしまった。。。
ただ収穫として、Lambda実装に前から気になっていた関数URLを使ってみたところ、コストを最小化しつつ最低限の認証もかけられる方式として非常に良さげであることがわかった。API Gatewayを挟まないことでコストを節約できる&今回の要件では複雑な仕組みは要らないので構成をシンプルにできる。
また、Lambda 関数URLの認証方式はIAMか認証なしの二択になるが、IAM連携を何やかんやするのが面倒な場合は、IFTTTから適当なTokenを渡してLambdaのコード内で検証してやれば簡易な認証には十分使えそうだという学びを得た。
docs.aws.amazon.com