GAS:Slackワークフローとスプレッドシートを使った時に使えるIncoming Webhooksでスレッドへの返信

必要なスキル

Slackのワークフロー、API設定、Google App Scriptの基本を理解をしていること

説明

このページのスクリプトではSlackワークフローを使ったケースです。
SlackワークフローとGoogle Sheetを連携させる事は簡単です。Tokenを使った複雑なスクリプトで投稿のタイムスタンプを取得するよりも簡単な処理で済む為、初級者に向いているかもしれません。

そのため、このページの設計では、Slackワークフロー、Incoming Webhooks、Google Sheet、App Scriptのみを利用します。SlackワークフローのステップにはGoogle Sheetへデータ送信する前に必ずチャンネルへ投稿するステップが必要です。その投稿のタイムスタンプを取得し、App Scriptがスレッド投稿する為です。

Slack側のApps設定、Incoming Webhooksを設定する説明は省きます。

  • Slack(ワークフロー、Incoming Webhooks)
  • Google(スプレッドシート、App Script)
Point

Thread_tsを取得するスクリプトで苦戦する場合もありますが、Slackワークフローを利用する事でtsを取得する事が容易です。また、桁数から算出がしやすい為、取得したURLからスプレッドシートの関数で加工ができます。

注意点としては、ワークフロー作成時には、Google sheetのスプレッドシートに追加するフローより前に、 チャンネルにメッセージを送信するフローがはいっている必要があります。チャンネルにメッセージ送信するフローがなければ、スプレッドシートへ入力する変数に表示されない、選択できない為です。

Google App Scriptのフロー

このApp Scriptは、スプレッドシートに変更があった場合に実行させています。

  1. スプレッドシートに変更が発生(Apps Scriptのトリガーをスプレッドシート変更時としている)
  2. スクリプトを実行
  3. A列を確認し、値が0ならばスクリプトを継続して実行、0以外の場合は処理中止
  4. B列へスクリプトが関数を入力。D列のPostURLの中にある値を取り出して変換し、Thread_tsを作成する関数
  5. スクリプトへ書かれたメッセージをB列のタイムスタンプを使ってスレッド投稿
  6. スクリプトが処理されたらA列の値を1へ変更

フローの3番目の処理は、Apps Scriptのトリガーでは制御しきれない処理停止の役割を持っています。この処理がない場合には、スプレッドシートに変更があると常に最終行をPostしてしまいます。あえてPostを再実行したい場合は最終行のA列を0にすると実行することもできます。

SheetA

SheetAには最低限のテーブルだけサンプルに書いています。実際にはSlackワークフローで色々な情報を取り扱えますし、GASからもそれらを利用してスレッドへ返信が行えます。
左からA,B,C,D,Eの列で構成しています。
A,C,D,EはSlackのワークフローが入力しており、Bはスクリプトが関数を入力します。

ScriptFlagThread_tsPostPostURLPostUserName

Sample Script

サンプルのスクリプトです。
エラー確認の為に少しログ出力も書いたままにしてあります。

function notifyReservationComplete() {
  var SampleSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("SheetA");
  var lastRow = SampleSheet.getLastRow();
  var flagCell = SampleSheet.getRange(lastRow, 1);
  var flagValue = flagCell.getValue();

  if (flagValue !== 0) {
    Logger.log("フラグが 0 以外のため、処理を中止します。");
    return;
  }

  // Thread_tsの値を取り出すための新しい式を設定
  var cellReference = 'D' + lastRow; // D列の最終行
  var formula = '=CONCATENATE(LEFT(RIGHT(' + cellReference + ',16),10),".",RIGHT(' + cellReference + ',6))';
  SampleSheet.getRange(lastRow, 2).setFormula(formula); // 2列目に式をセット

  // 一度スプレッドシートの計算を待つ
  SpreadsheetApp.flush();
  
  // 更新されたThread_tsの値を取得
  var threadTs = SampleSheet.getRange(lastRow, 2).getValue();
  var mentionUser = SampleSheet.getRange(lastRow, 5).getValue(); // E列のSlackメンション
  var slackURL = "https://hooks.slack.com/services/url"; // ここはIncoming WebhooksのURL
  var message = "ワークフローが送信完了です。<" + mentionUser + ">さん"; //スレッドへ返信するメッセージです。グループメンションを使いたい時は少し記述ルールが異なる。https://api.slack.com/reference/surfaces/formatting#mentioning-groups
  
  var payload = {
    "text": message,
    "thread_ts": threadTs
  };

  var options = {
    "method": "post",
    "contentType": "application/json",
    "payload": JSON.stringify(payload)
  };

  Logger.log("Payload: " + JSON.stringify(payload));
  Logger.log("Options: " + JSON.stringify(options));
  Logger.log("URL: " + slackURL);

  var response = UrlFetchApp.fetch(slackURL, options);
  Logger.log("Response: " + response.getContentText());
  
  flagCell.setValue(1); // フラグを 1 に設定
}