【GASで作るslack bot】スプレッドシートと連携してシフト管理botを作る(予定の入力と確認通知)


はじめに

 歴も長いことからインターン先でチームのまとめ役を担うことになり、これまで手作業で行っていたシフト管理を自動化したいとの思いからシフト管理botを作ることにしました。
 本記事で紹介するのは一般的な「月一で次月の勤務希望日を提出する」シフト管理ではなく、「明日の勤務の予定時間を登録する」ものとなっています。ちょっと特殊な仕様かもしれませんが、見ていただいた方の一助となれば幸いです。

botアプリの構成

構成概念図

構成要素 用途
Slack 構成員による勤務予定時間の投稿、botによる投稿確認の通知
Spreadsheet 勤務予定時間の保存
Google Apps Script (GAS) botの動作の記述(JavaScript)
Incoming Webhook botからの通知
Outgoing Webhook Slackに投稿された特定のワード(トリガーワード)をトリガーとし、GASに記述したコードを実行する

アプリケーションの作成

Slack api のページからアプリケーションの作成を行います。Create New App を押すと図のような画面に移るので、
「App Name」にはbotにつける名前を設定し、「Development Slack Workspace」ではbotを導入したいWorkspaceを選択します。以上2点が設定されたらCreate Appを押します。遷移先の画面で先ほどつけた名前のアプリケーションが追加されていることを確認してください。

Google Apps Script (GAS)

 Google Drive 内で右クリックからその他Google Apps Scriptを選択します。すると新たなプロジェクトが生成され、アプリの挙動を記述するためのエディタが開きます。
 説明の都合上、ひとまずこのままウェブアプリケーションとして公開します(中身の記述は後半に記述します)。公開ウェブアプリケーションとして導入をクリックし、プロジェクトに名前をつけると、「Deploy as web app」というウィンドウが開きます。ここでは以下の2項目を設定します。

「version」→ デプロイするアプリのバージョンを指定。Newを選択。
「Who has access to the app」→ Anyone, even anonymous に設定。

そしてDeployを押すと、WebアプリケーションのURLが表示される(Outgoing Webhookの設定でこのURLを用います)。

Incoming Webhook の設定

Slack api のページで先ほど作成したアプリをクリックし、att_management_botに関する基本画面に移ります。Featuresの「Incoming Webhooks」をクリックし、遷移先のページでIncoming Webhooksをアクティベートします(画面右上のoffをクリックしonにする)。
 するとページ下方に「Webhook URLs for Your Workspace」が現れます。(Incoming Webhookは作動する状態になりましたが)botがどのチャンネルに投稿すれば良いかが設定されていないので、その設定を行います。Add New Webhook to Workspaceを押し、連携したいチャンネルを選択し許可するを押します。
 「Webhook URLs for Your Workspace」の部分が更新されていることを確認してください。「Webhook URL」が生成され、curlコマンドによって動作を確認することができます。

確認してみる


curl -X POST -H 'Content-type: application/json' --data '{"text":"Hello, World!"}' <incoming webhookの設定で得られるURL>


terminalを開き、「Sample curl request to post to a channel:」以下の部分をコピーアンドペーストして実行してみます。すると先ほど指定したチャンネル(#test_kintai)にatt_management_botから「Hello, World!」という投稿が行われることが確認できます。

Outgoing Webhook の設定

ブラウザで「https://<ワークスペース名(小文字)>.slack.com/app」にアクセスします。検索欄に「Outgoing Webhook」と打ち込み、検索します。「Outgoing Webhook」のページに遷移したら、Slackに追加を押し、遷移先の画面でOutgoing Webhook のインテグレーションの追加を押します。

 すると、Outgoing Webhook の設定のページに移ります。ここでは以下の3項目を設定します。

「チャンネル」    → 連携したいチャンネル(#test_kintai)
「引き金となる言葉」 → botを作動させる合言葉(att_entry)
「URL」       → botの挙動を記述したGASのURL(WebアプリケーションのURL)

本説明では図のように設定しています。設定の保存を押して設定を完了します。

確認してみる

 ここで、#test_kintai チャンネルにトリガーワードである「att_entry」を投稿して、GASに記述した挙動が正しく行われるかを確認します。先ほどのGASには特にコードは記述していなかったので、現状何も起きません。GASに以下のようなコードを記述し、反応を見てみます。なお、< > の部分はincoming webhookの設定の際に得られたURLに変更してください。


postSlack("test");

function postSlack(text){
  var url = "<incoming webhook を設定した時のURL(botから投稿先のSlackのチャンネル)>";
  var options = {
    "method" : "POST",
    "headers": {"Content-type": "application/json"},
    "payload" : '{"text":"' + text + '"}'
  };
  UrlFetchApp.fetch(url, options);
}

test_kintai チャンネルにトリガーワードである「att_entry」を投稿してみましょう。att_management_bot から「test」というテキストが帰ってくれば成功です。これで、Slack → GAS → Slack の連携が取れるようになりました。

GASとスプレッドシートの連携

スプレッドシートの作成

Googleドライブ内で新たにスプレッドシートを作成します。今回は構成員が、①勤務するか否か(entry (yes or no))、②勤務を開始する時間(time)、を登録したいので、図のようなワークシートを作成しておきます。

構成要素 用途
input date 投稿日時
name 投稿した構成員の名前
command トリガーワード
entry (yes or no) 勤務するか否か
time 勤務開始予定時間

GASの記述

今回は以下のようなコードを作成しました。

function doPost(e) {
/*   //test(Slackからjson形式で以下のようにデータが送られてくる(一部分)。GAS上で実行テストを行う際にはこの部分のコメントアウトを外して実行してください。)
  e = {
    parameter : {
      user_name : "hoge_hoge",
      text : "att_entry yes 23:45",
    }
  }
*/
  var data = e.parameter.text // textを取得
  var username = e.parameter.user_name // user_nameを取得
  data = username + ' ' + data // dataの結合([user_name] [yes or no] [time])
  data = data.split(' ') // dataをスペース区切りで分割
  recordData(data);
}

// botからSlackへの投稿
function postSlack(text){
  var url = "<incoming webhook を設定した時のURL(botから投稿先のSlackのチャンネル)>";
  var options = {
    "method" : "POST",
    "headers": {"Content-type": "application/json"},
    "payload" : '{"text":"' + text + '"}'
  };
  UrlFetchApp.fetch(url, options);
}

// Spreadsheetへの入力
function recordData (data) {
  var spreadsheet = SpreadsheetApp.openById('<スプレッドシートのID>');
  var recordsheet = spreadsheet.getSheetByName('シート1');  
  var lastrow = recordsheet.getLastRow();
  var recordrow = lastrow + 1;
  var date = new Date();
  var formatdate = Utilities.formatDate(date, 'Asia/Tokyo', 'yyyy/MM/dd HH:mm:ss');

  // セルを指定してdataを入力
  recordsheet.getRange("A" + recordrow).setValue(formatdate);
  recordsheet.getRange("B" + recordrow).setValue(data[0]);
  recordsheet.getRange("C" + recordrow).setValue(data[1]);
  recordsheet.getRange("D" + recordrow).setValue(data[2]);
  recordsheet.getRange("E" + recordrow).setValue(data[3]);

  // 入力完了をSlackへ通知
  postSlack(data[0] + "さんの勤務予定を入力しました\n" + "勤務予定時間:" + data[3]);
}

2箇所のと<スプレッドシートのID>をそれぞれ書き換えてください。なお<スプレッドシートのID>は、スプレッドシートのURLの
https://docs.google.com/spreadsheets/d/[この部分]/edit#gid=0

[この部分]を渡します。
 GASにコードを入力したら保存し、ウェブアプリケーションとして公開します(公開の際にはversionをNewに設定)。

確認してみる

 Slackのtest_kintaiチャンネルに半角スペース区切りで「[トリガーワード] [勤務の有無(yes or no)] [勤務開始時間]」を投稿してみましょう。

すると上図のようにbotから勤務入力の確認の投稿が送信されてきます。また、スプレッドシートの方を確認してみると、投稿した予定時間が入力されていることが確認できます。なお、SlackからPOSTされたデータに含まれるuser_nameは、Slackの表示名ではありません。この部分はブラウザからアカウント設定を開き、「ユーザ名」の部分を編集することによって変更することができます(なお、Slackより「1時間に2回以上ユーザー名を変更することはできませんので、名前の選択は慎重に!」との記述あり)。
 以上でSlack、GAS、スプレッドシートの連携を確認することができました!

最後に

 今回作成した勤務時間管理のシステムはとてもシンプルなものです。同じ人が何回か登録すると、内容は上書きされずにシートにどんどん追加されていきます。この部分に関しては作成したいシステムの仕様に合わせて、GAS内のコードを追加・編集していただければと思います。

参考にさせていただいた記事

Slackとスプレッドシートを連携して筋トレ管理する