~ ToDo 活用 ~ GAS をつかって Slack から削除されたメッセージを Google スプレッドシートにアーカイブする 

#:rocket: はじめに
この記事では ToDo 活用の一環として GAS をつかい、Slack 内から削除されたメッセージを Google スプレッドシートにアーカイブする方法をご紹介します。

#:back: 背景
僕は自分の ToDo を Slack の自分専用ワークスペース、通称「ぼっち Slack」を作り、そこの IM チャンネル (自分宛ての DM) で管理しています。
![2019-06-22_23h03_49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/430271/5899a910-fb6e-7656-d184-fbc4ceeff19f.png)
方法は、こんな感じでシンプルにやってます。
1. IM チャンネル に ToDo タスクを書く
2. 必要に応じて
    - メッセージ スレッドで付随的な情報を書く
    - 緊急のものはピン留め
    - 重要度高めはスターをつける等々
3. タスクが完了したら**メッセージを削除**

この方法のポイントは、タスクが完了したタイミングでメッセージごと削除してしまいます。たとえば Gmail の受信ボックスって、用が済んだらどんどんアーカイブしていって、受信ボックスが空だと超気持ちいいですよね。ToDo 管理もこのノリでやってまして、チャンネルに入っているメッセージの量 = 自分が抱えているタスクの量と見立てていて、空であれば「超気持ちいい！」というマインドで習慣化しています。

しかしはじめはメッセージ削除でいっかーと思っていたんですが、たまにタスクを復元したい、振り返りたいとおもうシーンがでてきました。当然ですが、メッセージを削除しているので終わったタスクはどこにも残ってません。やっぱり Gmail のように終わったタスクはアーカイブして残しておきたい……。

そこでこのスクリプトを作ってみました。

#:book: レシピ

## GAS ウェブ アプリケーション URL の発行
準備として GAS の新しいプロジェクトを作成し、ウェブ アプリケーション URL の発行をおこないます。

1. Google ドライブから Google スプレッドシートを新規作成し、スクリプト エディターを開きます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/430271/fa0c612b-f2fb-bce7-b428-87bf43d08da6.png)

2. 後述する Slack API 側の Event Verification 用に以下のコードを記述します。

    ```javascript:VerificationForSlack
    function doPost(e) {
    
      var json  = JSON.parse(e.postData.getDataAsString());

      if (json.type === 'url_verification') {
        return ContentService.createTextOutput(json.challenge);
      }
    
    }
    ```

3. [公開] から [ウェブ アプリケーションとして導入] をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/430271/8bd86b9a-8147-10f2-c0e8-110a70a9596d.png)

4. 「アプリケーションにアクセスできるユーザー」を [全員 (匿名ユーザーを含む)] に変更し、[導入] をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/430271/1b4922ef-b6ec-8da1-0b3f-41a217b771ab.png)

5. ウェブ アプリケーションの URL が発行されるので、どこかにコピーしておきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/430271/24976fa0-34dc-684b-99f4-0b3e5226c4ce.png)

## Slack App の作成
Slack Events API をつかって、メッセージ削除イベント発生時に GAS へ JSON データを送る Slack App を作ります。

1. [Slack API | Slack](https://api.slack.com/) にアクセスしてビルドを開始します。![2019-06-22_17h35_31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/430271/0be831d6-6b21-b807-dd2c-119c049ae897.png)

2. 新しいアプリを作成します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/430271/345a2769-185c-d3b7-1d26-062731cf993c.png)

3. [Event Subscriptions] から「Enable Events」を有効にし、「Request URL」に "GAS ウェブ アプリケーション URL の発行" の "5." でコピーしておいた Verification 用の URL を入力します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/430271/d5b626e4-c924-334b-ad11-a5d8c00207ec.png)
:bulb: ここでは Slack API が指定 URL に対して HTTP POST でテスト リクエストを投げています。送信先 (今回の場合は GAS) は Slack API へリクエストを投げ返すことで、初回の検証作業を完了することができます。上の画像のように「Verified」の表示がでれば成功です。

4. 同ページ内の「Subscribe to Workspace Events」より [message.im] を登録します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/430271/018e12fd-b503-7475-9680-d483e540ec43.png)
:bulb: 今回は、IM チャンネル に送信されたメッセージ イベントが取れればよいので、登録イベントはこの 1 つのみで OK。DM チャンネル以外の削除メッセージを取りたい場合は、それに応じたイベントを登録する必要があります

## GAS でウェブ アプリケーションを作る
Slack の IM チャンネル 内でメッセージ削除が生じたとき、その日付・メッセージ日付・メッセージ内容をスプレッドシートに保存するスクリプトを GAS で書きます。

1. 以下のコードを "GAS ウェブ アプリケーション URL の発行" の "1." で開いたスクリプト エディターに追記します。

    ```javascript:SlackToDoArchiveApp
    function doPost(e) {
      var json            = JSON.parse(e.postData.getDataAsString());
      var event           = json.event;
  
      if (!event.subtype) return;
      if (event.subtype !== 'message_deleted') return;  // イベントがメッセージ削除以外の場合は何もしない
      
      var deleteTs             = json.event.ts ;  // 削除実行時のタイムスタンプ
      var deleteTsDate         = new Date(deleteTs * 1000);
  
      var deletedMessageTs     = json.event.deleted_ts  // 削除したメッセージの元タイムスタンプ
      var deletedMessageTsDate = new Date(deletedMessageTs * 1000);
      
      var text                 = event.previous_message.text;  // 削除したメッセージ
  
      var ss      = SpreadsheetApp.openById('hogehoge'); // Google スプレッドシートの ID (URL の末尾部分)
      var sh      = ss.getSheetByName('hogehoge');  // 入力先シートの名前
      var values  = [deleteTsDate, deletedMessageTsDate, text];
      
      sh.appendRow(values);
}
```

2. 保存後は、ふたたびスクリプト エディター画面の上部にある [公開] から [ウェブ アプリケーションとして導入] を開き、プロジェクト バージョンの更新作業をおこないます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/430271/3a0e4af9-3098-d4c0-dc57-0b69db1b1fa9.png)
:bulb: このウェブ アプリケーションの更新作業は、スクリプト エディターの内容変更のたびに必要になります (よく忘れて動かない)

## テスト
1. Slack の IM チャンネルに ToDo メッセージを入力します。
2. ToDo が完了したタイミングで該当メッセージを削除します。
3. Google スプレッドシートへ自動的にアーカイブされます。
![2019-06-23_13h24_16.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/430271/db50aaa2-afec-cb40-a3a9-721c4a753a7f.gif)

#:checkered_flag: まとめ
今回はじめて Slack の Events API を利用してみましたが、リファレンスがわかりやすく、簡単に実装できました。他にも Slack 上で取れるイベント情報は様々あるので、夢が広がりまくりです。

あと、Slack での ToDo 管理ですが、Slack を「ハブ」として日常的に利用しているユーザーさんであれば、とても相性がよいのでおすすめしたいと思います。

・ToDo のためにわざわざ別のアプリーションやウェブ画面を立ち上げなくていい
・Slack 上でのやり取りで ToDo イベントが発生することが多いので、登録効率がよい
・思いついたらサッと登録して、終わったらサっとアーカイブできる操作の軽快さ
・スレッド返信機能の活用とアーカイブで見た目的に散らかりにくい

ToDo は開いたときの文字数 (情報量) が多ければ多いほど開けたときに心理的な抵抗が強くなってくるので、タスクの **散らかりにくさ**、そして継続して管理・利用し続ける **習慣** を身につけることがとくに重要かなと思いました。

また今回は IM チャンネルでの例ですが、パブリック チャンネルを 1 個作り、同じようにチームで ToDo 共有・管理をおこなうといった活用もできます。よかったら試してみてください。

#:memo: 追記
2019/06/25 「削除操作」ではなくて「絵文字リアクション」でアーカイブする [新しい記事](https://qiita.com/knorr03/items/429ea9fefbc0156f822b) を投稿しました。

#:link: 参考
[[GAS][Slack App]Outgoing Webhook の代わりとして Slack App... - etau the non programmer coder]
(https://etauthenonprogrammercoder.tumblr.com/post/185572851353/gasslack-appoutgoing-webhook-%E3%81%AE%E4%BB%A3%E3%82%8F%E3%82%8A%E3%81%A8%E3%81%97%E3%81%A6-slack-app)
[message_deleted message event | Slack](https://api.slack.com/events/message/message_deleted)
[Google Apps ScriptでのDateオブジェクトの各生成方法、日付と時刻を分ける - いつも隣にITのお仕事](https://tonari-it.com/gas-date-object/)