2022/9/1からslackのフリープランの変更があります。
そこでslack-apiを使って90日より過去の投稿のバックアップを取得するツールを、Node.jsで作ってみました。
なお、公開チャンネルであれば公式のエクスポート機能があります。
バックアップの対象にするのは以下になります。
- 公開チャンネル・非公開チャンネルへの投稿
- リプライ
- 添付ファイル
※DMのバックアップは行っていません。
作成したもののソースはこちらになります。
slackチャンネルの使い方によっては生成されるバックアップのファイルサイズが膨大なものになったりするかもしれません。ツールの実行は自己責任でお願いします。
環境情報
- Node.js 16
- slack/web-api 6.7.2
トークンの取得
こちらの記事を参考にトークンを取得します。今回作るツールに必要になるPermissionsのScopeは、
- channels:history
- groups:history
- im:history
- mpim:history
- files:read
- channels:read
- groups:read
- mpim:read
- im:read
これらになります。
チャンネル一覧の取得
conversations.listを叩きます。公開チャンネル、非公開チャンネルの両方を取るようにします。
const list = await client.conversations.list({
cursor: cursor,
types: "public_channel,private_channel",
});
デフォルトでは100件分が取得できます。cursor
の初期値はnull
で、このAPIの応答に含まれるnext_cursor
を与えることで続きの100件が取得できます。
※このAPIで取得できるチャンネルはトークンを発行したユーザーの閲覧範囲に限られます。
チャンネルの履歴の取得
conversations.historyを叩きます。
const history = await client.conversations
.history({
cursor: cursor,
channel: channelID,
limit: HISTORY_LIMIT,
})
cursor
はチャンネル一覧と同様の振る舞いをします。channel
にはチャンネルのIDを指定します。こちらもデフォルトで100件分の履歴が取得できますが、一度でより多くの履歴を取れるようlimit
を指定します(最大1000件まで指定できるようです)。
リプライの取得
以前のAPIではチャンネル履歴の取得で合わせてリプライまで取れていたんですが、今のAPIではリプライが取得できません。
なのであるメッセージの持つreply_count
が1以上であれば、conversations.repliesを叩いてリプライを取得します。
const replies = await client.conversations
.replies({
channel: channelID,
ts: message.ts,
})
こちらを叩くことでmessage
に紐づくリプライが全て取得されます。
添付ファイルの取得
メッセージに紐づく添付ファイルを取得します。ただしこちらはAPIは提供されていないので、HTTPリクエストを送る必要があります。リクエストするURLはチャンネル履歴やリプライの応答の、files.url_private_download
になります。
中にはfiles
が無いメッセージやurl_private_download
が無い添付ファイル情報も含まれているので、そこは条件を書きます。url_private_download
が無い場合は外部ファイルの埋め込みだったりするので、JSON自体を保存してしまえば良いでしょう。
url_private_download
をリクエストするには、Bearerトークンで認証する必要があります。
headers: {
"Content-Type": "application/json",
Authorization: "Bearer " + TOKEN,
},
TOKEN
に指定するトークンは、APIで利用しているものと同じで問題ありません。
ストレージに保存
ダウンロードしたファイルはストレージに保存します。メッセージと対応付けられるようにmessage.ts
をディレクトリ名にします。また、添付ファイルは同名のファイルが複数添付されている場合があるので、files.id
でディレクトリをさらに掘るか、ファイル名に付与するかする必要があります。
メッセージをJSONファイルとして保存
取得してきたメッセージを一つのArrayに統合し、JSON.stringfy
でJSON化してストレージに保存します。
一つのチャンネルのメッセージ全てを一つのJSONにしてしまうと、超巨大なJSONファイルとなってしまう可能性があるので、適度に小分けして保存するのが良いでしょう。
zip化
archiverを使ってストレージに保存したJSON、添付ファイルを一つのzipファイルにします。
まとめ
以上がslackのapiを使ったバックアップの取り方でした。大体10000件の投稿があるチャンネルに対して実行すると、約15分かかって約1GBのバックアップが作成されました。ファイルサイズはチャンネルの添付ファイル量が大きく影響すると思います。