わすれっぽいきみえ

みらいのじぶんにやさしくしてやる

個人で使ってたSlackの全コメントを整理した

きっかけ

twitter.com

こういう発言をしていたのだけど、Asanaと連携している個人用Slackワークスペースは私が個人的にいろいろとテストしていた関係で、あちこちのチャンネルがとっ散らかってて下準備しないと夫を呼ぶに呼べない状態だった。Asanaの方はプロジェクトを移して本当に自分だけで使いたいタスクリストはprivateに寄せればよかったんだけど、特にSlackは個人用メモ帳みたいに使ってるチャンネルもあって1個ずつ消すにも結構な量があった。よりによって、そのメモ帳チャンネルがgeneralを改名したnoteって名前のチャンネルだったりして、あとでこんな風に困るとは想像もしてなかった。

「新しいSlackのワークスペース作ったら?」

と言われたけど、ワークスペースを増やして切り替えるのもなんだか面倒くさかったので、なんかいい方法ないかな?と考えた。

どうやって整理したか

tonton7.blogspot.com

基本的にはこの記事と方針は同じ。ただし、この記事が書かれたのが2017年でdeprecatedになったAPIを使ってしまってたり、画面が当時とは違うところもあったので、私が実際に実行した方法は以下になる。

  1. 移行先チャンネルをpublicチャンネルとして新規作成する。チャンネルのコメントをimportするにはpublicなチャンネルでないとできなかったため。
  2. ワークスペースのコメントを全てexportする。
  3. Slackのimportページに進んで、ステップ1で作ったチャンネルに移行したいチャンネルのコメントをimportする
  4. 完全にimportし終わったら移行先チャンネルをprivateチャンネルにする。正直このステップはお好みで。移行したいだけでほかの人に見られてもいいやと思うコメントしかないなら、このステップはとばしていい。
  5. 移行元となるチャンネルのコメントを全削除。

Slack自体にはチャンネル内のコメントを1つずつ消す方法しかないので、今回APIを叩いて全コメントを削除するスクリプトを書いた。

1. publicチャンネルを新規作成

このへんは知ってる人の方が多そうだけどあえて書いておくと以下の図の右上の『+』ボタンか一番下の『Add a Channel』をクリックするとチャンネル作成のフォームが表示される。

f:id:kimikimi714:20200518001753p:plain

あとは出てきたフォームの名前を好きにつけて『Create』のボタンを押せば終わり。チャンネルの説明文を入れたければ『Description』のところに書いてもいいけど、別に後から書けるので最初の時点で書く必要はあんまりない。

f:id:kimikimi714:20200518001810p:plain

1点注意が必要なのは privateチャンネルに一度してしまうと二度とpublicチャンネルにできない ことだ。昔は切り替えられた気がするんだが、どこかのタイミングでできなくなってしまった。で、最初からprivateチャンネルにしてしまうとimportもできなくなってしまうので、はじめはpublicチャンネルで作って後からprivateチャンネルに切り替えるようにする。

Slackのアップデートで上記手順は変わってしまうかもしれないので、公式の説明リンクも載せておく。私はSlackの言語設定を英語のまま使ってるので日本語のボタンで説明されたいときは下のリンクの方が参考になるかもしれない。

slack.com

2. Slackのコメントをexportする

まず図のワークスペース名のすぐ左に下矢印のプルダウンメニューのボタンがあるのでそれを押し、図の青色にハイライトされてる部分を順にクリックして『Workspace Settings』を開く。

f:id:kimikimi714:20200518002111p:plain

すると開いたページの右上の方に『Import / Export Data』というリンクが見つかるので、そこをクリック。『Import』、『Export』と書かれたタブがあるので、『Export』をクリックする。

f:id:kimikimi714:20200518002135p:plain

f:id:kimikimi714:20200518002202p:plain

『Export』のページでいつのデータをダウンロードしたいかが選べるので、選択肢の中から自分にあったものを選ぶ。私は『Entire workspace history』を選んで、『Start Export』のボタンを押した。コメント数が多ければ多いほどダウンロードには時間がかかると思うので、その辺は自己責任で。

f:id:kimikimi714:20200518002234p:plain

人によって時間は違うと思うが一定時間待ってるとダウンロード用のリンクが表示される。exportを開始して10日後にはリンクが無効化されてしまうので、覚えてるうちに早くダウンロードしてしまうこと。

f:id:kimikimi714:20200518002252p:plain

こちらも公式の説明リンクがあるので、適宜参考にするとよい。

slack.com

3. exportしたデータを再度Slackに読み込んでステップ1で作ったチャンネルにimportする

この章には私が実際にやった手順を残しておく。公式の説明リンクは以下。

slack.com

importはステップ2の『Import』のタブを開けば良い。その中にSlackのexportデータをSlackに読み込み直す『Slack』という項目があるので、その中の『Import』ボタンを押す。

f:id:kimikimi714:20200518002316p:plain

1. Review imports guide

次の画面に進むと全部で5つのステップでimportが進むことが説明される。最初の『1. Review imports guide』はインポートの説明ページを確認してねってことなので、もう読んでたら『Next』に進む。

f:id:kimikimi714:20200518002352p:plain

2. Upload your exported history to your new workspace

『2. Upload your exported history to your new workspace』で、ステップ2でダウンロードしたexportデータをアップロードする。ここがわかりにくいんだが、自分のローカルPCにファイルをダウンロードしていれば図の中の『upload it directly』のリンクをクリックして、ファイルを指定すればよい。exportしたデータはzipファイルになるはずなので、そのzipファイルを直接指定する。わざわざ解凍する必要はない。

f:id:kimikimi714:20200518002416p:plain

図の中にある入力フォームはクラウドサーバーにexportデータをあげていた場合、Slackからのアクセスを許可したリンクとして指定してあげればSlackがクラウドサーバーに直接アクセスしてexportデータを取ってくれる。公式の説明リンクにSlackのexportデータのダウンロードのリンクをフォームにコピペすればいいと書いてあったが、私の場合はうまく動かなかったのでファイルサイズも大したことないし素直に『upload it directly』を使った。exportデータのアップロードが完了するとまた『Next』のボタンが表示されるのでクリックして次の手順に進む。

3. Choose users to import

『3. Choose users to import』はexportデータに含まれるユーザーのうち、新たにワークスペースにinviteしたい人がいたらinviteするための手順になっている。私の今回の場合だとコメントだけ別のチャンネルに移したいのであってユーザーは関係がないので、『Don't import these users - just their messages』を選んで『Next』をクリックした。importをどういう目的で行うかによって選択は変わるはずなので、ほかにどういう方法があるのかは自分で確かめてみてほしい。公式のガイドは図の中の赤線を引いた『Slack import guide』から確認できる。

f:id:kimikimi714:20200518002448p:plain

4. Choose channels to import

『4. Choose channels to import』で、いよいよどのチャンネルのデータをどのチャンネルに移行するか選ぶ。『How would you like to import channels with a matching name?』は移行先ワークスペースに同一名のチャンネルがすでに存在する場合にどのチャンネルに移行させるかを選び、『How would you like to import channels with no matching name?』は移行先ワークスペースに同一名のチャンネルが存在しない場合にどのチャンネルに移行させるかを選ぶ。選択項目が細かくあって1個ずつ説明すると大変なため自分がやった手順だけ書いておく。

まずあるワークスペース内のコメントを同じワークスペースの別チャンネルに移したいだけなので、関係ないチャンネルのコメントは移行させたくない。なので、移行元チャンネルを個別に選んで移行先チャンネルを指定する方法をとった。たとえば #notify チャンネルの内容を #random チャンネルに移行して、ほかのチャンネルは移行しない なら以下の図のように選択すればよい。すぐ上にあるDon't import these channelsはなぜか無視されたので、あんまり気にせずやった。図の内容だと同一名のチャンネルがある場合の方法になるが、同一チャンネルがない場合も選択の仕方は同じなので、すぐ下の方にある『Show 3 channels』のプルダウンメニューを開いて、移行先を選べばOK。

f:id:kimikimi714:20200518152757p:plain

5. Review and run import

あとはこの項目でimport内容を確認の上『import』ボタンを押して完了。

f:id:kimikimi714:20200518152834p:plain

4. 移行完了したチャンネルをprivateチャンネルにする

ここは以下の公式の説明リンクから方法を確認してほしい。

slack.com

5. 移行元のチャンネルのメッセージを全て削除する

github.com

この中のdelete_slack_messages.goとしてコードを置いた。

このスクリプトを使うためには以下の前準備を行う必要がある。

  1. slackにアプリを1つ作って、そのアプリのユーザーtokenに必要な権限を付与する。すでにアプリがあるなら、それを流用しても構わない。
  2. token に渡すSlackのアプリのトークンは xoxb- で始まる『Bot User OAuth Access Token』ではなく、 xoxp- で始まる『OAuth Access Token』を渡す。でないとアプリ以外の他ユーザーによるコメントの削除が行えない。

[前準備]アプリの作成と権限の付与

Slackアプリの作成については過去記事でも参照した通り、Qiitaの記事を参考にしてほしい。今回Cloud Functionsは使わないので、その手順はスキップで。大事なのは利用するAPIのために、アプリに必要な権限を付与することだ。

私がスクリプト内で呼び出しているAPIは以下。

API 概要
chat.delete 特定チャンネルのコメントを削除する。スレッド内のコメントは削除しないので、スレッド内まで削除する場合は別のAPIを利用する必要がある。
conversations.history 特定チャンネルのコメント一覧を取得する。スレッドまで取得してくれるのかは未確認。私の今回の用途ではスレッドだけなら手作業で削除できると思って調査しなかった。

この2つのAPI仕様を確認すると chat.delete では user に対して chat:write:userchat:write:bot の権限が必要で、 conversations.history では user に対して channels:historygroups:historyim:historympim:history が必要だとわかる。 user とは『OAuth Access Token』を利用した際の権限を指す。この権限を付与するためにSlackアプリの『OAuth & Permissions』のページ(URLは https://api.slack.com/apps/{your_app_id}/oauth)の下の方に出てくる『Scopes』を確認する。以下の画像は必要な権限を『User Token Scopes』で全て付与した様子を表す。

f:id:kimikimi714:20200518152919p:plain

まだ付与できてない権限があったら『Add an OAuth Scope』から必要な権限を選択して付与する。付与するとアプリの再インストールを促されるので、再インストールをして権限の付与は完了。

[前準備]OAuth Access Tokenの取得

権限の付与と同じ『OAuth & Permissions』ページの一番上の方にtokenが2つ表示されている。この中の上の『OAuth Access Token』の方をスクリプトに指定する。

f:id:kimikimi714:20200518152943p:plain

使い方

使い方は以下。channel に渡す {channel_id} はSlackをブラウザで開いたときのURLで https://app.slack.com/client/{workspace_id}/{channel_id} からコピペして使ってほしい。

// 特定チャンネルの全てのコメントを削除する場合(-executeフラグをtrueで指定しなければドライラン実行となり削除しない)
$ go run delete_slack_messages.go -token {slack_user_token} -channel {channel_id} [-execute true]

// 特定チャンネルの特定のコメントだけを削除する場合(-executeフラグをtrueで指定しなければドライラン実行となり削除しない)
go run delete_slack_messages.go -token {slack_user_token} -channel {channel_id} -timestamp {message_timestamp} [-execute true]

以下の画像はdry-runで実行したときのCLIの出力になる。

f:id:kimikimi714:20200518153705p:plain

本当は general などSlack上で表示されるチャンネル名をそのまま channel に渡したかったんだが、そうすると別のAPIをさらに叩く必要がありそう(未調査)なのと日本語でチャンネルを作成してしまっていた場合の文字コードを考慮するのが面倒になってやめた。

じみこの機能にしないの?

実は最初はこのSlackのコメント削除機能をじみこに追加することを考えていたが、別にCloud Functionsを使うわけでもないし、Slackのコメント削除アプリがじみこである必要もないと気が付いてやめた。とはいえ産まれる前に家のことがいい感じに回る環境をもうちょっと作っておきたいなと思ってはいたので、スクリプト単体で作ってしまうことにした。

今後もなんかあると便利そうなスクリプトは以下のリポジトリに作っていこうと思う。

github.com

今回はGoで書いたけど、またPHPとかVue.jsとか使ってなんか作るのもいいかも。結局かまってちゃんも飽きて放置してるし。