Slack から Discord の移行メモ
Slack から、2022年9月1日からデータ保存期間の制限が発表され、
使い方によっては他のメッセージアプリへの移行を余儀なくされる人が少なからずいるだろう。
slack.com
・「Slack」が初の値上げへ ~無料プランのメッセージ履歴は『90日間のみ保存』に制限 - 窓の杜
自分もその中の一人である。
そしてつい最近、Slack から Discord へ移行することに成功したので、その時に実施した手順を記す。
概要
移行の内容だが、これまでに Slack で投稿したメッセージを Discord にも投稿するという単純なものである。
自分は Slack にURLリンクを投稿することでその時のリーディングリスト(あるいはブックマーク)として利用しており、
時々当時の自分が何に興味を持っていたのか見返したりしている。
そして Slack にはデータエクスポート機能があり、容易にこれまでのメッセージデータをダウンロードできる。
・ワークスペースのデータをエクスポートする | Slack
実は過去のメッセージが無くても特に支障は無いのだが、
せっかくなので頑張ってこのエクスポートデータを Discord にインポートしてみることにした。
エクスポートデータを手動で Discord に投稿するにはデータ量が膨大であり、そしてDiscord 側にはデータインポート機能が無いため、
自動化の方法を検討する必要がある。
前提・準備
- 動作環境:macOS (Monterey)
- 使用言語:シェルスクリプト
- 方法:curl で Discord の API を呼び出す
- 使用するデータ:Slack からエクスポートしたデータ (zip)
※ 保存期間制限の前に全メッセージデータをエクスポート済みである。
この手のアプリには便利な Web API が用意されている。
下記記事のとおり問題なく Discord の API を利用できたので、下記記事を参考にする。
・【Bash】discordにメッセージを送信する方法
下記リクエストでAPI エンドポイントを呼び出せば、Discord の対象チャンネルに指定のメッセージを投稿できるようだ。
curl \ -X POST \ -H "Content-Type: application/json" \ -d "{\"content\": \"$CONTENT\"}" \ "$WEBHOOK_URL"
Discord 側の設定を操作して Webhook URL を作成する必要がある。
Webhook URL は簡単に作成できる。詳しくは下記記事を参照。
・https://support.discord.com/hc/ja/articles/228383668-%E3%82%BF%E3%82%A4%E3%83%88%E3%83%AB-Webhooks%E3%81%B8%E3%81%AE%E5%BA%8F%E7%AB%A0
Webhook URL のフォーマットは下記のとおりである。
https://discord.com/api/webhooks/<hogehoge>
この文字列を curl の $WEBHOOK_URL の部分と置き換えればいい。
$CONTENT がメッセージ内容となる。
次に、Slack エクスポートデータの仕様解析である。
エクスポートデータは zip ファイルである。
これを解凍すると、チャンネル名毎にフォルダが存在し、そして各フォルダに json ファイルが複数存在している。
ここからの手順はいろいろとあると思うが、自分は全部の json ファイルを1つのファイルにまとめる方法で実施した。
これは下記コマンドを実行すればいい。
$ cat <dir>/*.json | jq -c '.' > <read_file>
このコマンドにより、各 json ファイルのデータが1行の json 形式のデータとして記録された1つのファイルが作成される。
※ jq コマンド:json データの処理において様々な便利な機能を提供する。jq
そして Slack の json データの仕様は下記を参照。
・Slack からエクスポートしたデータの読み方 | Slack
これらフィールドの中で移行したいデータは、"text"と"ts"である。
ここまでの説明で、大まかな移行手順がイメージできたと思う。
解決
自動化のために、インプットデータを curl の引数として渡すためのスクリプトを作成する。
結論としては、下記スクリプトを作成して実行する。
shell_script.sh
#!/bin/bash readonly WEBHOOK_URL="https://discord.com/api/webhooks/<copy>" readonly FILE_NAME="<read_file>" readonly USER_NAME="<discord_display_name>" # WHILE_I=1 # Debug # r option is important. # To process the last line of the file. while read -r line || [ -n "${line}" ]; do # echo "__WHILE_I $WHILE_I" # Debug echo "$line" | jq -c '.[]' | while read -r json_array; do TEXT=$(echo "$json_array" | jq -r '.text') # せっかくなので日付情報もメッセージに付加する。 TS=$(echo "$json_array" | jq -r '.ts' | sed 's/\..*//g') DATE=$(date -r $TS +"%Y-%m-%d") CONTENT=$(echo "($DATE) $TEXT") curl \ -X POST \ -H "Content-Type: application/json" \ -d "{\"username\": \"$USER_NAME\", \"content\": \"$CONTENT\"}" \ "$WEBHOOK_URL" done # WHILE_I=$((WHILE_I + 1)) # Debug # echo; # Debug done < $FILE_NAME # echo "__END $WHILE_I" # Debug
※ 事前にテストすることを推奨。
実行コマンド
$ bash <shell_script>.sh
参考
これが正常に動作するまで、様々なエラーに直面した。
先人達が残してくれた情報に感謝する。
・JSONをwhile read lineしてjqしててハマった話 - シンプライン(Simpline)公式採用サイト‐採用情報
・BASHのwhile readで最終行が処理されない問題の解決方法 - Qiita
・bash で json を jq でスマートにループする