Slack の指定チャンネルの全メッセージをエクスポートする

オレオレレベルだけど形になった。

動機

ひとり Slack しているのだが、過去のメッセージを素早く読みたい or 検索したいことが多い。しかし Slack 上では読み込みに時間がかかるし、検索も(ローカルで GREP するのに比べたら)遅いので不便である。

ローカルにエクスポートできたら解決するんじゃない? テキストエディタでサクサク流し読みもできるし、GREP でサクっと検索もできるし。

エクスポートするにはどうしたら?……ああ、API を使えばいいのか。んじゃスクリプト書こうか。

成果物

https://github.com/stakiran/slack_exporter

Slack API と格闘する

認証はどうやるの?

Legacy Token を使うことにした。

Legacy Token は「Slack 内で何でもできる root 権限的なトークン」である。元々 Slack APIトークンはこれだけだったのだが、「(セキュリティ的に)お粗末だよね」ということで別のトークン体系が採用され、このトークンは Legacy(古い。非推奨)となった。

が、私はひとり Slack しているだけなので、Legacy Token が楽でいいや、ということで使うことにした。

使用したAPIは?

「チャンネルID」を得るために channels.list method | Slack を使った。

「チャンネルID」から「そのチャンネル内の全メッセージ」を得るために channels.history method | Slack を使った。

チャンネル内のメッセージ総数を得るために search.messages method | Slack を使った。

ページネーションはどうした?

channels.history は 1 リクエストで 1000 件までメッセージ取得が可能。それ以上を取りたい場合は、1000件単位で何度もリクエストを投げる……いわゆるページネーションが必要になってくる。

Slack API のページネーションはかなり楽で、取得したい範囲のタイプスタンプ(latest と olders)を指定するだけ。たとえば latest=1498435916.943443, oldest=1486815979.000008 と指定すると、2017/06/26 09:11:56 から 2017/02/11 21:26:19 の間のメッセージを取得することになる(もちろんこの間が1000件を超えたら全部は取得されない)。

なので、最初に1000件取得して、取得結果から最初と最後のメッセージのタイプスタンプを取り出して、それをセットして次の1000件を取得して……というふうに繰り返せばよい。

Rate Limit は?

詳しくは Rate Limits | Slack をご参照くださいだが、おおよそ以下のように割と緩い感じ。

In general we allow applications that integrate with Slack to send no more than one message per second.

アプリについては1秒1メッセージ以内の送信で頼むよ。

We allow bursts over that limit for short periods.

短時間ならバーストしてもOKです。

However, if your app continues to exceed the limit over a longer period of time it will be rate limited.

もし短時間を越えてバーストしてたら、こっち側で通信制限かけることがありますんで。

GitHub API が1時間5000回以内 とハッキリ定めてるのとは対照的だ。