dorapon2000’s diary

忘備録的な。セキュリティとかネットワークすきです。

Twitter APIのPOST lists/members/create_allの制約と対応

突然の宣伝で恐縮ですが、最近ListIDOというサービスを作りました。

listido.dorapon2000.xyz

内部でTwitter APIを使っており、主にTwitterのリストを操作しています。その中で、リストにメンバーをまとめて追加できるPOST lists/members/create_allという大変便利なAPIがあります。このAPIがなければ、ListIDOというサービスを作ろうとは思いませんでした。

しかし、便利すぎるがゆえに、その制約がどうなっているのかが気がかりでした。フォローは1日に400人までしかできません。ではリストにメンバーを追加する場合は?制約の厳しさ次第でサービスの根幹を揺るがされてしまいます。

今回はそのAPIについて調べたことをまとめ、その制約に対する自分の対応も紹介します。

3行まとめ

  • 1度の呼び出しで100人まで追加できる
  • リストに大量・無差別なメンバーの追加はTwitterルールで禁止されている
  • 具体的なレートリミットはなさそう

POST lists/members/create_all

POST lists/members/create_all | Docs | Twitter Developer Platform

Twitterのリストにメンバーを複数人追加するAPIです。リストの作成や、1人だけ追加するAPIは別であります。また、API v2には同じ役割のAPIがないため、API v1.1でしかできない操作になります。

APIドキュメントに記載されている制約

  • メンバーの追加先のリストは自分が所有している必要がある
  • 1つのリストには5000メンバーまでしか含めない
  • 1度の操作で100人までしかリストに追加できない
  • 同じリストに対してメンバーの追加と削除を急激に行うと問題が起きる可能性がある
  • レートリミットあり

2つ目の5000メンバーという上限はリスト機能にあるそもそもの制約1です。3つ目の100人までしか一度に追加できないのはAPIを呼び出すときに注意が必要です。つまり、300人追加したい場合は3回に分けてAPIを呼ぶ必要があります。4つ目は成約というより注意喚起で、おそらくDBの整合性の問題なのだと思います。

問題は5つ目で、原文は

f:id:dorapon2000:20211115234433p:plain

YES!!!(具体的にいくつやねん!!!!!)これはPOSTのリスト操作APIすべてに言えます。

GETのAPIには何分間に何回までしか呼び出せない等の具体的なレートリミットが書かれているところに、POSTではただ「Yes」としか書かれていません。

Standard API v1.1の制約

Rate limits: Standard v1.1 | Docs | Twitter Developer Platform

こちらにおそらくすべてのGETのAPIと一部のPOSTのAPIのレートリミットが列挙されています。なぜPOSTは一部しか列挙されていないのか.... POST lists/members/create_allはもちろんありません。

Twitterの自動化ルール

Twitterの自動化開発ルール | Twitterヘルプ

少しずれますが、開発者向けの自動化ルールのページにも、リストに関する言及があります。

リストまたはコレクションへの追加の自動化: Twitterアカウントを大量または無差別にリストに追加したり、ツイートを大量または無差別にコレクションに追加したりしないでください。多数の無関係の利用者をリストに追加することは、Twitterルールで禁止されています。

リストに大量にアカウントを追加する行為はTwitterルールで禁止されているようです。この「大量」という言葉が曖昧ですが、Yesよりは具体的になりました。

API呼び出しのHTTPヘッダを見る

Twitter APIを呼び出すと、HTTPヘッダ内にレートリミットに応じた残りリクエスト数などが記載されます。

以下のサイトでは、実際にAPIを呼んだときのレスポンスヘッダまで載っているので、どうなるか見てみます。

POST lists/members/create_all - リストに複数のメンバーを追加する

f:id:dorapon2000:20211116001914p:plain

対照としてGETも

GET lists/show - リストを取得する

f:id:dorapon2000:20211116002118p:plain

GET lists/showにはx-rate-limit-limit/x-rate-limit-remaining/x-rate-limit-resetがありますが、POST lists/members/create_allにはありません。

困りました。

GET application/rate_limit_statusを使う

Retrieve rate limit details programatically | Docs | Twitter Developer Platform

Twitter APIの中にはレートリミットの残量を確認できるAPIがあります。これで調べられるのでは、と思ったところ

for read-only (GET) operations

GETしかわかりませんでした汗。

他の実装を見てみる

そもそも、なぜレートリミットが知りたいかというと、それによって実装が変わってくるからです。緩いなら連続でAPIを呼んでも問題にならないですし、厳しければ間隔を明けてAPIを呼ぶ必要があります。

https://github.com/search?l=Python&q=lists%2Fmembers%2Fcreate_all&type=Code

GitHub全体で検索して、他の実装がどうなっているのか調べてみました。流石に個人のコードをここに貼ったりするのははばかられるので、見た感じの感想を述べると、連続で呼び出す実装ばかりで、そこのところはあまり気にしていないようです。

これで1つ、実装の目安が立ちました。

レートリミットの答えらしきもの

blog.ryotak.me

ネットの海を探して、このような記事を見つけました。記事単体で面白かったのですが、注目したいのは以下の記述です。

Twitter APIの一部のレートリミットが、ドキュメント上には存在すると書いてあるにも関わらず、実際には存在しないことがわかった。 それらのエンドポイントの一つにPOST /1.1/lists/destroy.jsonが存在した。

薄々そう思っていましたが、おそらくPOST lists/members/create_allについてもそういうことなのでしょう。

ListIDOではどう実装したか

具体的な制約があれば、その制約を守っていれば怒られる(垢バン)ことはないです。しかし今回、その制約がなさそうということで、守るべきなのは制約ではなく節度に変わりました。

その節度も「大量の追加」という言葉で具体性がありません。結局、ListIDOでは1つのリストに対して15分に50人までしか追加できないようにしています。具体的には、ジョブサーバを立てて、リストへの追加作業を15分間隔でメインのアプリとは非同期に定期実行させます。300人のメンバーをリストに追加する必要があるならば、6つのジョブを75分かけて完遂させます。

単にfor文を回して3回APIを呼ぶ実装と比べて、格段に実装コストがあがりましたが、勉強になるからと自分をなだめました。

最後に

多くはいないが同じような疑問を持つ人は必ずいると思い、ニッチな内容ですが記事にしました。それで本記事を呼んで疑問を解消できたのであれば書いた甲斐があります。読んでいただきありがとうございました。

参考