前回のあらすじ
【STEP 2】では6つの手順でSlackからGASへの記録リクエストを実現しました。
1. GASの追加実装
2. Slack App作成
3. Bot User作成
4. Events API設定
5. ワークスペースにAppをインストール
6. App表示情報の編集
前回の記事
参照:SlackとGASで水分摂取量を管理してみた【STEP 1】GAS編 | CCI TECH BLOG
参照:SlackとGASで水分摂取量を管理してみた – 【STEP 2】Events API編 | CCI TECH BLOG
今回はGASからSlackへ記録結果を返信する方法をご紹介します。
作成手順
【STEP 3】GASからSlackへ記録結果を返信
1. OAuth Token取得
Bot Userから記録結果を返信するために、OAuth Tokenを取得する必要があります。
https://api.slack.com/apps にアクセスし、 作成中のApp(今回はDrinkSupporter)を選択します。
左側のメニューから「OAuth & Permissions」を選択し、「Bot User OAuth Access Token」をコピーします。(手順2で使用)
2. GASの追加実装
【STEP 2】のコードに3点の変更を加えます。全体像は次のようになります。
function doPost(e) {
// パラメータ
var postData = JSON.parse(e.postData.getDataAsString());
// Slack Events API認証用
if (postData.type == "url_verification") {
return ContentService.createTextOutput(postData.challenge);
}
// 処理要否判定
var param = postData.event.text;
if (postData.event.subtype == "bot_message" || param == null) {
return;
}
// 記録用シート取得
var recordSheet = SpreadsheetApp.openById("スプレッドシートID").getActiveSheet();
// 日をまたいだ場合、記録と最終更新日を更新
var today = Utilities.formatDate(new Date(), "JST", "yyyy/MM/dd");
if (today != Utilities.formatDate(recordSheet.getRange(2, 4).getValue(), "JST", "yyyy/MM/dd")) {
recordSheet.getRange(2, 2).setValue(0);
recordSheet.getRange(2, 4).setValue(today);
}
// ★変更1(変数追加)
// 返信先のchannel ID
var channel = postData.event.channel;
// ★変更3
// 記録
if (/^-?\d+$/.test(param)) {
recordSheet.getRange(2, 2).setValue(recordSheet.getRange(2, 2).getValue() + Number(param));
reply("記録しました。本日の記録:" + recordSheet.getRange(2, 2).getValue() + "ml", channel);
// 目標値更新
} else if(/^goal\s\d+$/.test(param)) {
recordSheet.getRange(2, 1).setValue(Number(param.match(/\d+/)[0]));
reply("目標値を更新しました:" + recordSheet.getRange(2, 1).getValue() + "ml", channel);
// 記録確認
} else if (/^check$/.test(param)) {
reply("本日の達成状況:" + recordSheet.getRange(2, 3).getValue() + "% "
+ "(現在 " + recordSheet.getRange(2, 2).getValue() + "ml/目標 " + recordSheet.getRange(2, 1).getValue() + "ml)", channel);
// Help表示
} else {
var msg = "【Help】\r\n";
msg += "`[number]` 記録 (ml)\r\n";
msg += "`goal [number]` 目標値設定 (ml)\r\n";
msg += "`check` 記録確認";
reply(msg, channel);
}
}
// ★変更2(function追加)
// Slackへメッセージ送信
function reply(msg, channel) {
var payload =
{
"token" : "手順1でコピーしたOAuth Token",
"channel" : channel,
"text" : msg
};
var options =
{
"method" : "post",
"contentType" : "application/x-www-form-urlencoded",
"payload" : payload
};
UrlFetchApp.fetch("https://slack.com/api/chat.postMessage", options);
}
〇追加実装のポイント
・(変更1)返信先のchannel ID取得コードの追加
Bot Userの返信先を特定するため、channel ID取得のコードを追加します。
// 返信先のchannel ID
var channel = postData.event.channel;
・(変更2)Slackへメッセージを返信するfunctionの追加
手順1でコピーしたOAuth Tokenを使用して、doPostの下にreply functionを追加します。
// Slackへメッセージ送信
function reply(msg, channel) {
var payload =
{
"token" : "手順1でコピーしたOAuth Token",
"channel" : channel,
"text" : msg
};
var options =
{
"method" : "post",
"contentType" : "application/x-www-form-urlencoded",
"payload" : payload
};
UrlFetchApp.fetch("https://slack.com/api/chat.postMessage", options);
}
・(変更3)Slackへのメッセージ返信内容の追加
スプレッドシートの記録処理の下にメッセージ返信処理を「reply(メッセージ内容, channel)」の形式で追加します。
また、併せて目標値更新等の処理も追加します。
// 記録
if (/^-?\d+$/.test(param)) {
recordSheet.getRange(2, 2).setValue(recordSheet.getRange(2, 2).getValue() + Number(param));
reply("記録しました。本日の記録:" + recordSheet.getRange(2, 2).getValue() + "ml", channel);
// 目標値更新
} else if(/^goal\s\d+$/.test(param)) {
recordSheet.getRange(2, 1).setValue(Number(param.match(/\d+/)[0]));
reply("目標値を更新しました:" + recordSheet.getRange(2, 1).getValue() + "ml", channel);
// 記録確認
} else if (/^check$/.test(param)) {
reply("本日の達成状況:" + recordSheet.getRange(2, 3).getValue() + "% "
+ "(現在 " + recordSheet.getRange(2, 2).getValue() + "ml/目標 " + recordSheet.getRange(2, 1).getValue() + "ml)", channel);
// Help表示
} else {
var msg = "【Help】\r\n";
msg += "`[number]` 記録 (ml)\r\n";
msg += "`goal [number]` 目標値設定 (ml)\r\n";
msg += "`check` 記録確認";
reply(msg, channel);
}
〇ウェブアプリケーションの公開設定
外部からのリクエスト処理時に変更したコードが使用されるよう、公開設定を忘れずに行います。
その際「承認が必要です」のダイアログが再び表示されるので、承認を行います。
「許可を確認」をクリックします。
Googleアカウントを選択し、
「詳細」→「DrinkSupporterProject(安全ではないページ)に移動」→「許可」の流れで アクセス承認を行います。
【STEP 3】の作業はこれで完了です。
動作確認
Slackを開き、DrinkSupporterのダイレクトメッセージで確認を行うと、A~Dの動作が確認できます。
A. 水分摂取量を記録 …数値を入力した場合(例:200)
B. 目標値を更新 …「goal 数字」と入力した場合(例:goal 2500)
C. 本日の達成状況と目標値を返信 …「check」と入力した場合
D. ヘルプを返信 …上記以外の言葉を入力した場合(例:aaa)
まとめ
【STEP 3】では2つの手順でGASからSlackへの記録結果の返信を実現することができました。
1. OAuth Token取得
2. GASの追加実装
全くの初心者(Slack Appが何かもGASの開き方も知らない状態)からのスタートでしたが、
最初に目標として挙げた4機能(A~D)を実現することができました。
Appの機能やGASの実装方法など工夫できる部分はたくさんあるようなので、今後更に育てていきたいと思います。
前回の記事
参照:SlackとGASで水分摂取量を管理してみた【STEP 1】GAS編 | CCI TECH BLOG
参照:SlackとGASで水分摂取量を管理してみた – 【STEP 2】Events API編 | CCI TECH BLOG
(おまけ)
今回作成したAppは、常にGoogleスプレッドシートの2行目に記録するため、複数人での利用はできません。
Slackから受信するpostDataの中身を見るとユーザーIDが含まれているので、それを用いることで上述の問題を解消できます。
・ユーザーIDの取得とGoogleスプレッドーシートの行数を特定
// ユーザーID取得
var postData = JSON.parse(e.postData.getDataAsString());
var userId = postData.event.user;
// 行番号の取得
var recordSheet = SpreadsheetApp.openById("スプレッドシートID").getActiveSheet();
var rowNum = recordSheet.createTextFinder(userId).matchEntireCell(true).findNext().getRow();
・新規ユーザーの場合は、appendRowをすることで最下行に行を追加
// appendRowのイメージ(各列の情報を配列形式で挿入する)
recordSheet.appendRow([userId, 0, 0, today]);