🐓

Nitter + IFTTT Pro + Slack で Twitter を雑に見る

2020/10/06に公開

そんな雑な閲覧で大丈夫か? 大丈夫だ、問題ない

はじめに

私は Twitter に対して基本的には、

アレは 人間で作った蠱毒の壺か何か の類いだ

と考えていて、Twitter を使う際にはその辺りを勘定に入れて 常に解毒する様に意識付けて利用している のですが、最近、色々と閲覧環境を調整した結果、

と言う組み合わせに落ち着きました。

そしてこの環境は色々とアレな所があるにしろ、結構 雑に Twitter を解毒して閲覧 すると言う目的には合致したので、今回はその辺りの情報を共有したいと思います。

利用したもの

Nitter

Nitter とは GitHub の、

と言うリポジトリで公開されている nim言語で実装された Web Application で、ほぼ JavaScript を利用せずに Twitter を閲覧することが出来るソフトウェアです。あと nitter.net で公式インスタンスが稼動しています。

そして Nitter では今の Twitter は当の昔に廃止され実現が難しくなった、

Timeline などの RSS Feed の取得

が出来る様になっているため、今回の hack ではこの機能を利用しています。

ただこれ、

Nitter ってどうやって Twitter の情報を取得しているんだろう……?

と思って実装を調べたところ、なんか Twitter の Official Client から引っこ抜いたと思われる認証トークンを使っている のを見付けてしまい、

そんな実装で大丈夫か……?

と思うところは有るには有ります。

とは言え、一応 Nitter のインスタンスは公式以外でもそこそこに公開されているし、今のところ閉鎖される様な感じもなかったため、その辺りは見なかったこととして華麗にスルー しました。よろしいですね?

IFTTT Pro

今回の hack では Slack との Integration 周りを自分で実装するには面倒極まりなかった ので、最近有料化して云々が話題となっていた IFTTT Pro を使いました。

なお私個人としては Nitter から取得した RSS の情報を加工したかった のと、あと IFTTT から流し込む Slack のチャンネル数が多かった ため、IFTTT Pro を契約する事にしましたが、その辺りの機能はイラネーと言う方は、 IFTTT の無償利用でもこの hack と同じ様なことは Polling 速度と Applet の数さえ気にしなければ 出来ると思います。

Slack

これは言うまでも無いんですが今回は Slack で Twitter を流し見たかったので、前々から使っていた、

ぼっち Slack

を利用しています。

ただぼっち Slack については IFTTT Pro を使った時とは違い、特に過去ログは流れてしまっても問題なかった(と言うかむしろ過去ログは適宜流れて欲しい)のと、あと有償の機能が使いたいとかの要件もなかったため、Slack に関しては無償版を使っています。

環境の作り方

下準備

今回は、

Nitter で RSS Feed 化した Timeline を IFTTT に食わせて Slack に投げる

と言う構成を取っているので、アカウント登録不要で使える Nitter を除く、

  • Twitter のアカウント
  • IFTTT のアカウント
  • Slack のアカウント

の辺りは最低限必要です。

また私の要件の様に Twitter アカウントをリスト分けした Twitter リストの方の Timeline を RSS Feed 化して利用したい場合、 その RSS Feed の URL も取得する必要がありますが、Twitter リストの Timeline を RSS Feed として Nitter で取得するにはおおよそこんな感じになります:

# 例えばこの Twitter リストの Timeline を RSS 化したいとする
> https://twitter.com/i/lists/1199943467561930752

# 上記の URL から nitter の URL を得るには `twitter.com` を `nitter.net` に入れ替える
> https://nitter.net/i/lists/1199943467561930752

# そしてこの Nitter の URL にアクセスすると、下記の様な URL に redirect する
> https://nitter.net/kalaclista/lists/Developers

# 最後に Redirect した URL の末尾に `/rss` を付けると Twitter リストの RSS が得られる
> https://nitter.net/kalaclista/lists/Developers/rss

なお注意点として、この Twitter リストを RSS 化するための URL には Twitter リストのタイトルが含まれていて(この例だと Developers)、かつこのリストのタイトルに英数字以外の文字列が含まれている(例えば日本語)と、途中の redirect 先の URL が 404 not found になるので、Twitter リストのタイトルは英数字だけで構成する必要があります。

また他の URL で RSS Feed を取得したい等、どの URL でどの情報を取れるかについては、

を参照するとなんとなくは把握できると思います。

IFTTT Pro の設定をする

まず最初に IFTTT 上で、

  • IFTTT の RSS Service を有効にする
  • IFTTT と (ぼっち)Slack との連携を有効にする

と言う二つの事は最低限やっておきます。

そして IFTTT で作成する Applet はおおよそ下記の様な感じになります:

  1. RSS Service の Feed に Nitter での RSS Feed を指定
  2. RSS Service の動作は New feed item を指定
  3. Slack Service へは Post to channel を選択し下記の様に設定
    • Message{{EntryContent}}
    • Title{{EntryAuthor}}
    • Title URL{{EntryUrl}}

ちなみに TitleTitle URL に色々と仕込んでいるのは、これをやっておかないと Slack 上でどれが誰の Tweet なのか判別が付かなくなるのと、Slack への Post から元の Tweet の URL を辿れなくなるためです。

またこの設定は Slack に流し込みたい Timeline の数だけ繰り返すので、私個人の環境では面倒と言えば面倒な作業でした。(私の場合 Twitter リストが 28個あったため)

One More Thing!(と言うか味付け)

ちなみに私が実際に使っている IFTTT の Applet では上記の設定に加え、RSS Service と Slack Service の間に下記の様な Filter Code を仕込み、Slack Service の Thumbnail URL にも{{EntryImageUrl}} を追加しています:

let body = Feed.newFeedItem.EntryContent.replace(/nitter.net/g, 'twitter.com');
let url = Feed.newFeedItem.EntryUrl.replace('nitter.net', 'twitter.com');;
let avatar = Feed.newFeedItem.EntryAuthor.replace('@', 'https://us-central1-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.cloudfunctions.net/nitter-avatar?id=');


Slack.postToChannel.setMessage(body);
Slack.postToChannel.setTitleUrl(url);
Slack.postToChannel.setImageUrl(avatar);

そしてこの Filter Code は何をしているかと言うと、おおよそ:

  • nitter.net を指している URL を twitter.com に戻す
  • Slack で Twitter でのアイコンを Cloud Functions 経由で表示できる様にする

と言う様なことをやっています。

なお上記の Google Cooud Functions で実際に動かしているスクリプトの内容は下記の通りです:

const https = require("https");

function getAvatarUrl(id) {
  return new Promise((resolve, reject) => {
    https.get(`https://nitter.net/${id}/rss`, (res) => {
      if (res.statusCode !== 200) {
        reject("error");
        return;
      }

      res.setEncoding("utf8");
      let data = "";
      res.on("data", (x) => {
        data += x;
      });
      res.on("end", () => {
        resolve(
          data.match(
            /<url>(https:\/\/nitter\.net\/pic\/profile_images.+?)<\/url>/
          )[1]
        );
        return;
      });
    });
  });
}

exports.main = async (req, res) => {
  let id = (req.query['id'] || '').replace(/[^a-zA-Z0-9_\-.]/g, "");

  if (id === "") {
    res.status(404);
    res.send('id required'); 
    res.end();
    return;
  }

  return getAvatarUrl(id).then(
    (url) => {
      res.redirect(303, url);
    },
    () => {
      res.status(500);
      res.end();
    }
  );
};

この方法の特徴

と言うことで以上が今回作った環境の説明と作り方なのですが、最後にこの方法の利点や欠点を記述してからこの記事を終えたいと思います。

どこかで Tweet を取り漏らすことがある

この点について私は 速の早い Timeline を適当に刈り込んでくれるので利点として捉えています が、

Timeline に Tweet が流れる速度 > Timeline が RSS として取り込まれる速度

になっている場合、一部の過去の Tweet が RSS として含まれずに流れ、結果として取り込めなかった Tweet が取り漏らしとして発生することへと繋がっています。

そのため 過去の Tweet をすべて取得したい と言う場合には、Tweet の Timeline を取得する部分については素直に自前で実装した方が良いと思います。

Tweet と Retweet の区別が付かず、一部情報が欠落する

これは Nitter の RSS Feed に起因する問題なのですが、現状使っている IFTTT の Applet だと following している方の Retweet が普通の Tweet と同じ形式で送られてくる ため、結果として、

いやコレ誰?

と言う Tweet も Slack 上に結構流れて来ます。

そしてこれは私の Applet 固有の問題だと言えますが、IFTTT Pro の Add filterThumbnail URL を強制的にアバターアイコンに差し替えている都合上、画像や動画付き Tweet などの Tweet に付随する埋め込みメディアの情報当然の様に欠落する状態 となっています。とは言えこの辺りは工夫次第で何とかなりそうではあるんですが。

また IFTTT から投稿された URL はどうも Slack上で展開されないっぽいし、また Tweet 自体の内容からも Tweet の URL が省略されてしまう場合もあるので、雑に Twitter を Slack で見る と言う目的でもなければ この点は結構なデメリットなのでは……? とも考えています。

IFTTT Pro、お前 RSS の URL の叩き過ぎじゃろ

これ、私もビックリしたんですが IFTTT Pro は各 Service の Polling 速度が上がる みたいな感じになっていて、実際にこの Applet が動いている様子を見ると 各 Applet が 5分に一回のペースで RSS を取得 しています。

しかも私が使ってる IFTTT Pro の Applet は Twitter リストの Timeline の数だけ存在していて、それが 28個分あるので 5 * 28一時間に 140回、同じサービスからデータを取得 しているっぽく、これは およそ 2分30秒おきに Nitter からデータを取ってきている と言う計算になります。なんか日本の警察だと逮捕されそうですね

そのためこの辺りは IFTTT Pro の仕様上どうしようも無い 感じなんですが、もう少しマシな方法で RSS を取得して欲しいなーとは思ってます。と言うか 5分に一回 RSS を取得するクローラーって相当にお行儀が悪いのでは……?

あとこれが関係しているのかどうかは分かりませんが、今回の方法で作った IFTTT Pro の Applet は一晩寝て起きると大体数個から5~6個はエラーが出て止まっています。なので朝起きて一番には IFTTT の Mobile App などで Applet を起動し直してます。

おわりに

と言う事で今回の話は以上となります。

まぁ私の場合 Twitter の Timeline は雑に解毒して見るぐらいが丁度良い と考えているので、今回の内容で十二分に満足できる環境は構築できたのですが、もう少しこの方法をマシにしたい方はnitter から RSS Feed を取ってきている部分を Webhook に置き換え て、その Webhook に対して Twitter の API を叩いて取ってきたデータを流し込む と言う感じに変えると良い感じになるんじゃないかなーとは思っています。

あと nitter とか IFTTT Pro のクローラーの中身がお行儀悪くて気になる と言う方も 入力を Webhook に切り替えるのはやっておいた方が良い のではないかとも考えていて、この辺りは各自調整しましょうと言う感じです。

あと私については今の環境で満足しているので コレをあれこれと調整する気分は今のところ無い のですが、今回の構成は色々と工夫を加えればもう少し利便性が向上する余地がある とも思っているので、よかったら この構成を参考に色々と試してみるのも良いのではないかな? と考えています。はい。

更新履歴

  • 2020-10-07: 文中の表現を調整し、いくつかの情報を追記
  • 2020-10-06: 初版

Discussion