見出し画像

【GAS, JavaScript, Slack API】古いポストから一定期間が過ぎたら自動削除するbotはGASが超簡単!

※ 旧ブログ、Frontend Life in DEのリライト記事。
※ 新ブログは Aiki x Developerhttps://aiki-developer.com)へ。

どうもー、ドイツでフリーランスのフロントエンドエンジニアをしています Arisa です。

今日はSlackに一定期間が過ぎたら古いポストから順に自動で消すボットを作成して導入したときの備忘録です。(2018年時点の情報です)

Slackの無料枠って、意外と100人以上の規模の活発な組織で使用すると8ヶ月ほどで上限を超えそうになるようで、無料枠に抑え続けるための秘策といえば、自動投稿削除ボット。

私が普段関わっているオンラインサロン、wasabiの海外フリーランス養成スクールの運営者であるwasabiさん( @wasabi_nomadik)が、サロンで使用しているSlackが無料枠上限に達しそうということで、担当させていただいたのが実はきっかけなんです。

GAS(Google App Script)やSlack API、JavaScript、ボット搭載に興味がある人向けの記事です。

吐き出されたエラーやハマったポイントも含んでます。

GASをJavaScriptで書くことができるのは今まで知らなかったので、なんでこんな便利な技術を知らなかったんだろうと思ったぐらい、目からウロコ情報でした!

JavaScriptで書くといってもそこまで難しいものではなく、for文、for each、do while、if文、ちょっとした比較演算子やANDが書ければ、あとはスプレッドシートにアクセスする関数と組み合わせればOKという感じです。

前書き

実装したい内容

まず実装したい内容は以下。

- 設定した期間で定期的に古いポストから順に自動削除
- 削除対象のチャンネルを指定できるようにする

制限

実装後に気が付いたんですが、やっぱりそれなりに制限はあるようです。


- #general チャンネルは無効だった
- 多分DMも無効
- スクリプトはES5仕様で書く

予備知識

Container Bound Script(スプレッドシートに紐付けたスクリプト)と独立したスクリプトの違い

これはGASでSlackボットを作成する内容のチュートリアル記事でよく省略されている内容で、知っていると超初歩内容なのですが、知らないとハマることも。(私だけかもですが)

まずContainer Bound Scriptは、Google スプレッドシートを先に作成してから、スクリプトを紐付けしてあります。

割とマニュアルですが、スプレッドシートをGoogle Docsで新規作成して、 Tools → Script Editor でGASのスクリプトを立ち上げます。

A列に書いてあるのは、紐付けさせるSlackの自動ポスト削除ボットを導入したいチャンネル名です。

スクリプトが立ち上がると、そこにコードを書き始めることができます。

この時点ですでにスクリプトファイルとスプレッドシートは、紐付けによりアクセスできる状態です。

反対に、独立したスクリプトというのは、以下のスクショのようにGASスクリプトファイルをスプレッドシートとはまずは紐付けせずに単独で作成するスクリプトです。

上記で Google App Script を選択して、GASスクリプトを立ち上げます。

この時点ではスプレッドシートとは何も紐付けはない状態なので、アクセスはできません。

どういうときに使い分けをするのが便利かということですが、

「スプレッドシートには他人に書き込み権限を与えたい。でもスクリプトに書き込めるのは自分だけにしたい」


という場合には、独立したファイルを作る必要があります。

そこまでこだわらない、もしくは他の人にむしろスプレッドシートでチャンネル名を管理させたいというときには紐付けされたスクリプトを作るのが良いですね。

ハマったポイント:Container Bound Scriptと独立したスクリプトはアクセスする書き方が違う

ハマったというと大げさですが、地味に上記のContainer Bound Scriptのことを知らず、「どうやってスプレッドシートにアクセスするのか?もしや関数が用意されている?」と、ちょっと時間を無駄にしてしまったので、これは知っておくと便利。

まずスプレッドシートにアクセスできなければGASスクリプトを書いてもお互い独立しているのであれば何も意味がないので、アクセスしている方法の違いに着目します。

Container Bound Scriptは、すでにスプレッドシートからGASスクリプトを新規作成しているので、アクセスはすでにできる状態。

なのでアクセスは以下の書き方になります。

var sheet = SpreadsheetApp.getActiveSpreadsheet();

一方まだ紐付けされていない独立スクリプトは、以下の書き方でアクセス。

var sheet = SpreadsheetApp.openById('<キー>'); // スプレッドシートのURLがキー

このアクセス方法の書き方が違うと、エラーログが吐き出されるので、Container Bound Scriptなのか、独立スクリプトなのかを把握する必要は大事。

手順1:Google スプレッドシート作成

Container Bound Scriptで作成する

さて、前置きが長くなりましたが早速ボットを作成していきましょう。

Container Bound Scriptが個人的には簡単だったので、まずは紐付けしたスクリプトをスプレッドシートから上記手順で作成

SlackAppをライブラリに追加する

Slack APIをGASから呼び出すので、そういったときにはSlackAppを使用するのが簡単で便利です。

まずは、こちらのSlackAPPのGithubにある Library Key をコピー。

GASスクリプトファイルの上部より、Resources → Libraries... を選択し、以下のスクショ画面で先ほどコピーしたライブラリ キーをペーストし、 Add を選択。

以下のように記入 & バージョンを選択して保存。

ググると上記のスクショ箇所のバージョンを何も選択していない非表示で追加するように書いてある記事をいくつか見ましたが、2018年6月現在では ver. 22 がエラーログが吐き出されることなく、無事にSlackAppをライブラリに追加することができます。

これでライブラリにSlackAppが追加され、使用できるようになりました。

SlackのトークンをGASのスクリプトのプロパティへ追加

まだスクリプトを書く準備は最後に1つだけ残っています。

Slackでトークンを発行する必要があるので、まずはこちらのLegacy TokensページでSlackにログインした状態でトークンを発行します。

トークンが発行できたらGASスクリプトページに戻って、 File → Project Property... を選択し、以下のスクショのようにトークンを貼り付け、プロパティ名をつけて保存。

これでスクリプト内でトークンを呼び出せます。

GASでスクリプトを実装

ここからが実際のスクリプトを書いての実装です。

コメントアウトで機能の説明補助をしていますので参考にしてください。

function cleanChannels() {
   var sheet = SpreadsheetApp.getActiveSheet(); // Container Bound Scriptでスプレッドシートにアクセス
   var values = sheet.getDataRange().getValues(); // 値が入っているシートの全セルをRangeオブジェクトとして取得

   var channelNames = [];
   for (var i = 1; i < values.length; ++i) {
       channelNames.push(values[i][0]);
   }

   var token = PropertiesService.getScriptProperties().getProperty('SLACK_API_TOKEN'); // トークン
   var slackApp = SlackApp.create(token);

   for each(var channelName in channelNames) {
       cleanChannel(slackApp, channelName);
   }
}

function cleanChannel(slackApp, channelName) {
   var channelId = getChannelId(slackApp, channelName);
   if (channelId.length == 0) {
       return;
   }

   var date = new Date();
   date.setDate(date.getDate() - 5); // 5日前の投稿取得
   var timestamp = Math.round(date.getTime() / 1000) + '.000000';

   do {
       var optParams = {
           latest: timestamp,
           count: 1
       };
       var result = slackApp.channelsHistory(channelId, optParams);
       if (result.ok) {
           for each(var message in result.messages) {
               slackApp.chatDelete(channelId, message.ts); //5日前の投稿取得 → 削除のループ
           }
       }
   } while (result.ok && result.has_more)
}

function getChannelId(slackApp, channelName) { // チャンネル名からチャンネルIDの取得
   var channelId = '';
   var result = slackApp.channelsList();
   if (result.ok) {
       for each(var channel in result.channels) {
           if (channel.name == channelName) {
               channelId = channel.id;
               break;
           }
       }
   }
   return channelId;
}

スクリプトを承認

スクリプトを書いただけでは、関数 cleanChannels を実行のつもりで Run とGASスクリプトファイルから押しても実行されず、エラーログが出ます。

そもそもトリガーがまだないので、いつ実行していいかはGASには伝わっていないです。

ここでトリガーを設定したいのですが、その前に、スクリプトを実行しようとRunしてもエラーログが返ってくると書きましたが、このエラーログはどちらかというとトリガーの設定がないのもそうですが、先にトリガーを設定しても、サーバーエラーのログが出てトリガーも設定できません。(2018年6月現在)

まずすべきこととしては、スクリプトの実行Runを押下したときに出てくる以下のスクショ画面で、Googleの認証をする必要があります。

Review Permission をクリックしますが、ここでもエラー画面が出ます。

ただし、エラー画面といっても内容は承認をするための工程画面なので、 Advanced をクリック。

そうすると、表記は小さいのですが、スクリプトやスプレッドシートにつけたファイル名のアプリケーションにアクセス承認をするような誘導があるので、クリック。

持っているGoogleアカウントを選ぶように誘導があるので、使いたいアカウントを選択。

以下のスクショ画面になるので Allow で承認。

GASのスクリプト画面に戻ったら無事トリガーを追加できるようになりました。

これも実は結構省略されている内容の情報が多く、微妙にハマったポイントかもしれません。

トリガーを設定

あとはここでトリガーを設定するだけで、基本的にボットは使えるようになります。

トリガーの設定の仕方は非常に簡単。

Edit → Current Project Triggers をGASスクリプト画面から選択し、以下の様に Day Timer で設定します。

これで保存をし、スクリプトを実行すると完了です。

実際に反映をすぐ見たいという場合は、スクリプトを1日前の投稿を削除に変更し、トリガーを現在の時間に合わせると反映をすぐ確認できます。

ただし、事前に前日に何かしら #generalかDM以外のチャンネルに投稿している必要があります

投稿が削除の対象なので、画像ファイルとチャット両方が消えていることが確認できます。

まとめ

Slackはチーム開発だけでなく、もはやプロジェクト単位、はたまたオンラインサロンや企業、コミュニティなど幅広く使われるようになっています。

一定期間を過ぎた投稿から削除するボットだけでなく、ファイルだけを削除するボットや、自動応答するボットなど、Slack APIやGASの組み合わせで、とても手軽にJavaScriptが書ける人であれば導入することができるようです。

Slack APIもとてもたくさんのドキュメントが用意されているので、もっと効率よくチームがSlackで関わっていけるようにするためのカスタマイズがたくさんあるようです。

今回はSlackの無料枠を超えそうな時のメジャーな解決策としてのお役立ちボットですが、そのほかにもいろんなことができそうですね。

この記事がお役に立てれば幸いです。

では

ちゅーす


この記事が気に入ったらサポートをしてみませんか?