GASを使ってGoogleSpreadsheetの内容を呼び出してSlackbotにしゃべらせる


やってみたいこと

これをslackコマンドで実現したい。

> /birthday
あなたの誕生日パートナーはXXさんだよ! 誕生日はY月Z日です。忘れないでね!

前提条件

  • GoogleSpreadsheetに、メールアドレス、名前、誕生日のリストがある
  • ユーザはSlackにGoogleSSOでログインしている(↑のメールアドレスと同一)

方針

  1. Slackのカスタムコマンドを作成し、GASを呼び出す
  2. GoogleSpreadsheetの該当列から必要な情報を取得
  3. Slackbotにしゃべらせる

実装

1. Slackのカスタムコマンドを作成し、GASを呼び出す

こちらの記事を参考にして、まずメッセージのやりとりができるかどうかテスト。
Slash CommandsとGASでSlackのオリジナルコマンドをつくる

エラー「http_client_error」により失敗しました
えーっ。

最初からつまづく。
↑の記事のコメント欄でも困っている方がいるようだ。

このエラーは権限エラーだと思われる。
うちのGSuiteは自組織内のみでアクセスを許しているため、アクセス権限に「全員」を選ぶことが出来ない。
自組織内の誰か、に設定したものの、ちゃんと動かない。

…で終わってしまうのも寂しいので、プライベートアカウントを使って実装までやってみる。
まずは固定で結果を返すプログラムを作る。

コード.gs
function doPost(e) {
  var birthday = get_birthday(e.parameter.text);
  var response = { text: Utilities.formatString("あなたの誕生日パートナーは%sさんだよ! 誕生日は%sです。忘れないでね!", birthday.name, birthday.date) };

  return ContentService.createTextOutput(JSON.stringify(response)).setMimeType(ContentService.MimeType.JSON);
}

function get_birthday(user_name) {
  var name = '山田太郎';
  var birth_date = '01/01';

  return {name: name, date: birth_date};
}

これで固定メッセージがでるようになった。

2. GoogleSpreadsheetの該当列から必要な情報を取得

公式リファレンス
https://developers.google.com/apps-script/reference/

このあたり、参考にさせていただく。
https://www.pre-practice.net/2018/01/blog-post_21.html

  • Slackから飛んでくるユーザIDを取得
  • そのユーザIDで検索し、列の名前、誕生日を取得
  • 誕生日パートナーは複数いるかもしれないので、その対応
  • パートナーがいない場合は悲しそうにお知らせする

等の要素を組み込み、最終的にこうなりました。

コード.gs
function doPost(e) {
  // パラメータ指定がある場合はその指定ID、なければログインID
  var birthday = make_message((e.parameter.text) ? e.parameter.text : e.parameter.user_name);
  var response = { text: birthday };

  return ContentService.createTextOutput(JSON.stringify(response)).setMimeType(ContentService.MimeType.JSON);
}

function make_message(user_name) {
  // 該当列取得
  var book = SpreadsheetApp.openById('XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX');
  var sheet = book.getActiveSheet();
  var finder = sheet.createTextFinder(user_name);
  var results = finder.findAll();

  // 結果を連結
  names = [];
  results.forEach(function(user_id) {
    index = user_id.getRowIndex();
    name = sheet.getRange(index, 5).getValue();
    date = sheet.getRange(index, 6).getValue();
    names.push(Utilities.formatString("%sさん (%s)", name, Utilities.formatDate(date, 'Asia/Tokyo', 'MM/dd')));
  });

  var birthday = names.join(', ');
  return (birthday) ? Utilities.formatString("あなたの誕生日パートナーは%sだよ。 忘れないでね!", birthday) : "あなたの誕生日パートナーは見つかりませんでした…。あれれ?";
}

結果

まとめ

Spreadsheetまわりの関数を調べるのに時間がかかったが、
それ以外はいたって簡単でした。
アプリ間連携がこんなに簡単になっているとは。

未だGsuiteの制約を突破できていないので、他に実現方法はないか引き続き情報収集していきます。