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

気になったことメモ

  • Web API とWebhook の意味の違い
  • Python で記述するとどうなるか、簡単なのか
  • Discord のデータ保存期間