kawasin73のブログ

技術記事とかいろんなことをかくブログです

Twitter をフィルタリングする Twilter を作った

あなたとわたしと Twitter。どうも、かわしんです。

今週の頭の日曜月曜火曜の 3 日間かけて Twilter というコマンド(?)サービス(?)を作ったので、その紹介をしたいと思います。

Github リポジトリはこちらです。star をつけていただけると喜びます。

また、良かったらご自身で運用してみてください。

github.com

なぜ Twilter を作ったのか

僕のツイッターライフ

僕は Twitter を情報収集と娯楽のために利用していますが、僕の性格として全ての情報を把握しておきたいため、フォローしている人の全てのツイートを読んでいます。

残念ながら Twitter の公式アプリは、勝手にツイートの順番を入れ替えたり、勝手にオススメのツイートだけをフィルタリングして上に表示したり、時間が経ってアプリを開くと勝手にスクロール位置を最新のツイートに変えてしまったりします。

余計なお世話にも程があります。僕はタイムラインの全てのツイートを確認したいのに勝手にスクロール位置やツイートの順番を変えられると、どこまで確認していたかがわからなくなってしまいます。

そこで、僕は Tweetbot という iOS アプリを利用してタイムラインの購読をしています。

このアプリは有料アプリですが、タイムラインの順番やスクロール位置を勝手に変えることはしません。また、複数の iOSバイス間でスクロール位置を同期してくれるので、家で iPad で読んで通学途中で iPhone で読むみたいな場合でもシームレスにタイムラインの確認ができます。さらに、キャッシュなどの最適化を行なっているため通信状況が悪くてもツイートの確認ができるのもいいところです。

僕みたいな異常な完璧主義の方にオススメのアプリです。

さて、全てのツイートの監視をしている僕ですが時間は有限であるため、ツイートが増えるスピードがツイートを読むスピードを超えてしまうと未読のツイートが無限に増えてしまいます。

そのため、ツイート数とその人が垂れ流す情報の有用さのバランスを元にフォローしている人を定期的に整理して、ツイートの流速調整を行っていました。

今は 100 フォロー以下を目安にやっていますが、割ときつくて、70 ~ 80 フォローくらいがちょうどいい流速なのではないかと思っています。

迎える限界

そんなツイッターライフを送っていた僕ですが、ある日僕のルールの限界を感じさせるユーザーに出会います。

重曹 さんです。この方の代表作はこれです。死ぬほど面白い。複数のツイートに分割されているのでリプライを辿っていってください。

「なかのやま」さん「NZK」さん「重曹」さんのセンスの塊の3名で構成される LINE グループのチャット内容を時々ツイートされるのですが、これが死ぬほど面白いのでフォローして LINE チャット画面を楽しみにしていました。

しかし、重曹さんの毎日のツイート数はかなり多く、僕のタイムラインが爆発してしまいました。LINE グループのツイートの数に比べてその他のツイートが多すぎるため僕のルールではフォローを外すしかないのですが、どうしてもこのセンスあふれる LINE グループの画像は見たいという板挟みの状態になってしまいました。

その時の僕の心の叫びがこれです。

ということで、Twilter を作ることにしました。

Twilter とは何か

Twilter は Twi t ter を F ilter してくれるサービスです。安直な名前なのですでに Twilter という名前のアプリは色々あるようです。しかし、それらはブラウザのエクステンションでツイッターのウェブサイトで表示を消す程度のことしかしてくれないようなので、自分で Twilter を作ることにしました。

機能としては以下の通りです。

  • 特定のユーザーのツイートを定期的に確認し、
  • 設定された条件にマッチするツイートをフィルタリングし、
  • そのツイートを連携している Twitterアカウントでリツイートする

というものです。その連携している Twitter アカウントだけを自分の Twitter アカウントからフォローすれば、フィルタリングされたツイートを自分のアカウントのタイムラインで確認することができます。

こんな形で使います。この設定では、重曹さんのリツイートでないオリジナルの画像ツイートのみをフィルタリングします。

$ export TWITTER_CONSUMER_KEY=xxxxxxxxxxxxxxxxxx
$ export TWITTER_CONSUMER_SECRET=xxxxxxxxxxxxxxxxxx
$ export TWITTER_ACCESS_TOKEN=xxxxxxxxxxxxxxxxxx
$ export TWITTER_ACCESS_TOKEN_SECRET=xxxxxxxxxxxxxxxxxx
$ export REDIS_URL=redis://user:password@host_name:6379

$ twilter -target "YTmoyashifes:and(photo,not(rt))"

このコマンド自体はフォアグラウンドで動きますので、デーモン化は dockersystemd などで行なってください。

docker イメージは https://hub.docker.com/r/kawasin73/twilter で公開しています。

注意事項

まず注意事項を記載しておきますが、リツイートを行うアカウントは 鍵アカウント(Private Account)にすることを強く推奨します。

相手ユーザーに多くのリツイートによる通知が表示されて迷惑になってしまうことを防ぐためです。鍵アカウントであれば相手ユーザーはリツイートされたことがわかりません。

また、監視できる対象ユーザーはツイートをリツイート可能なパブリックアカウントのみです。鍵アカウントは対象外ですので注意してください。

オプション一覧

オプションはこんな感じになっています。

$ twilter -h
Usage of /usr/local/bin/twilter:
  -fallback int
        start filtering tweets fallback minutes ago if no checkpoint (minutes) (default 10)
  -interval int
        interval between monitoring (minutes) (default 10)
  -target value
        list of targets. target format = "<screen_name>:<filter>[/<filter>]"  filter format = "<filter_name>[(<attribute>[,<attribute>])]"
  -timeout int
        timeout for each monitoring + retweet loop (minutes) (default 5)

本当は設定ファイルから読み込めたら便利なんですが、Docker で運用する場合に面倒になるのと、ファイルフォーマットの策定など諸々めんどくさかったので対応していません。

フィルターについて

フィルタ設定は、target オプションによって設定します。複数の target を設定することもできます。

target<twitter_id>:<filter>[/<filter>[/...]] のフォーマットで指定します。フィルターは / によって区切ることで複数設定できます。(本当は | で区切りたかったけど、シェルのパイプと認識されてしまうため / にしました)

これらのフィルターのうち1つでもマッチするものがあればリツイートされます。

フィルターは以下の種類があります。

  • rt : リツイートされているツイート
  • qt : 引用リツイートされているツイート
  • photo : 画像付きツイート
  • video : 動画付きツイート
  • not(<filter>) : 引数のフィルターにマッチしないツイート
  • and(<filter>[,<filter>[,...]]) : 引数のフィルターの全てにマッチするツイート
  • or(<filter>[,<filter>[,...]]) : 引数のフィルターのどれか1つでもマッチするツイート

まだ実装していませんが、特定のキーワードやハッシュタグを含むツイートのフィルターも作る予定です。

ここで特に特徴的なのは、最後の notandor フィルターの 3 つだと思っています。

この3つのフィルターを組み合わせることで比較的柔軟に色々な種類のフィルターを定義することができます。また、提供するフィルターの種類もプリミティブなものだけで済むので実装コストも抑えられるのもいいところです。

Redis との連携

Twilter はデフォルトでは起動時刻から fallback に設定された分だけ前のツイートからフィルタリングを始めます。これは再起動した場合に停止していた間のツイートを取りこぼさないためです。

Twilter はオプション機能として、Redis を用意して環境変数REDIS_URL に接続情報を登録するとツイートの確認状況を Redis に保存します。再起動した場合は Redis に保存されているツイートより後のツイートからフィルタリングを始めます。これにより無駄にフィルタリングをせずに済みます。

Redis との連携機能はオプション機能なので、 Redis がなくても Twilter を利用することができます。

Rate Limit

Twitter にはリクエスト数の Rate Limit があり一定時間にできる API リクエストの数が決まっています。

Twilter ではリクエスト数制限に引っかかった場合でも自動で適切な時間待って再送する 再送処理を実装 していますが、これは一時的にバーストした場合のためのものなのであらかじめ適切にリクエスト数の見積もりと設定をする必要があります。

ユーザーごとのツイート一覧を取得する API のリクエスト数制限は 900 requests / 15 minutes の制限と、 2019 年 6 月 19 日からは 100,000 requests / day の制限があります。

GET statuses/user_timeline — Twitter Developers

Twilter では Twitter アカウントを監視する間隔を interval オプションで指定できます。デフォルトは 10 分になっています。単位は minute です。

ユーザーのツイート一覧取得は、1 回のリクエストあたり最大 200 ツイートを取得できるので、各自それに合わせて interval の値を設定してください。

また、リツイート投稿 API のリクエスト数制限は 300 requests / 3 hours です。リツイート投稿が多くならないようにユーザーの選定とフィルターの中身を設定してください。

POST statuses/retweet/:id — Twitter Developers

アクセストークンについて

Twitter のアクセストークンを取得するには開発者アカウントが必要です。

Twitter は気づいたら開発者アカウントを取得するために 200 字の作文を複数箇所行わなければならないようになってしまっていて、ハードルが上がっていて悲しいです。が、背に腹は変えられないので頑張って英語作文しましょう。

多分、インストール手順の中で Twitter の開発者アカウントを作成するのが一番難しいステップ です。本当に悲しい。

取得したアクセストークンは、TWITTER_CONSUMER_KEY TWITTER_CONSUMER_SECRET TWITTER_ACCESS_TOKEN TWITTER_ACCESS_TOKEN_SECRET環境変数に設定して利用します。

TWITTER_CONSUMER_KEYTWITTER_CONSUMER_SECRET には開発者アカウントの Consumer Key と Secret を登録してください。

TWITTER_ACCESS_TOKENTWITTER_ACCESS_TOKEN_SECRET には、開発者アカウントから発行されたリツイートを行う鍵アカウントの Access Token と Secret を登録してください。

多くの場合は開発者アカウントの Twitter アカウントとリツイートを行う Twitter アカウントは 別のもの を使うと思います。その場合はダッシュボードから TWITTER_ACCESS_TOKENTWITTER_ACCESS_TOKEN_SECRET を生成することができません。

twitter-auth というコマンドラインツールがアクセストークンの発行を簡単に行なってくれるため、利用することを推奨します。

github.com

最後に

と、まぁ、こんな感じです。

Twilter は自宅の kubernetes on Mac mini サーバーで運用しています。じわざわリツイートがタイムラインに流れてくるのを「ちゃんと動いているぞ」と思いながら眺めています。

情報をうまくフィルタリングして時間を有効活用できるようになりました。

Twilter では定期的にツイッターを監視するタスクスケジューリングの部分に一年前に 管理上手のうさちゃん を作った時に作ったタスクスケジューラ htask を使っています。

github.com

うまく汎用的なライブラリを再利用できて、ニヤニヤしてます。

では、良い Twitter ライフを !