GASを使って、Google Chat の勤怠連絡の情報をスプレッドシートに書き込んでみた。

GASをあまり触ったことがなかったため、Google Chatに投稿された勤怠連絡の詳細をスプレッドシートに書き込むChat bot アプリをGASで作ってみました。検証で動かしただけなので、実コードに突っ込みどころがたくさんあるかと思いますが、大目にみてください。

# Google Apps Script(GAS)とは
Googleから提供されているローコードプラットフォームで、Google WorkSpaceの統合、自動化、サードパーティサービスとの連携を簡単にできるサービスです。ブラウザから、Javascriptなどで簡単にアプリケーションコードを記述できます。スプレッドシートなどの連携するためのテンプレートが用意されているので、サクッと試すことができます。
※Google Workspaceの公式ドキュメント
[Apps Scripts]("https://workspace.google.co.jp/intl/ja/products/apps-script/")

※Sampleコード
[apps-script-samples]("https://github.com/googleworkspace/apps-script-samples")
[アドオンスターター](https://script.google.com/home/start)

# 今回やったこと
１．Google Chatに勤怠連絡を投稿する。
２．Botアプリケーションが自動応答したうえで、スプレッドシートに投稿者名、出勤・退勤ステータス、投稿日時を記録する。

# 前提
今回は公式ドキュメントの[Quickstarts](https://developers.google.com/chat/quickstart/apps-script-app)を使って進めていきます。事前にGCPでプロジェクトの作成、Google Chat APIの有効化、OAuth同意画面の設定が必要です。OAuth同意画面の補足だけしておくと、アプリケーションがGoogle APIを利用してユーザーデータにアクセスする際に、ユーザーに表示されるアクセス同意画面です。今回は、検証かつ組織内にのみ公開するので、特にスコープは設定していません。その他、GASの設定、GCPの設定は書いてある通りに実施するだけです。

また、Google ChatにBotアプリケーションとして、作成したアプリケーションを追加します。Google Chatへのアプリケーションの追加は、Google WorkSpaceの有償版でしかできないため、有償版を契約済みの前提で進めてまいります。
※Business Starterプランで試してみました。

# 設定と変更箇所
GASとGCPの設定は上述した通り、[公式ドキュメント]("https://developers.google.com/chat/quickstart/apps-script-app")に記載があるので、そのままやれば問題なくできるかと思います。テンプレートコードの変更箇所とデバック方法について、記載します。
## 変更箇所

onAddToSpace、onRemoveFromSpace関数は、日本語表記に変更したくらいなので割愛します。
OnMessageとスプレッドシートに書き込む関数を追加してます。
```
function onMessage(event) {
  var name = "";

  if (event.space.type == "DM") {
    name = "You";
  } else {
    name = event.user.displayName;
  }
  // ひっかけたい文字列を指定
  var morning = /おはよう|オンライン|こんにちわ|こんばんわ/;
  var leave = /お疲れ様|おつかれ/;
  var status = "";
  var username = event.user.displayName;

  // createTimeの表示がDateで表示されないため、一旦保留とし、current Dateを持ってくる。
  //https://github.com/googleapis/google-api-nodejs-client/issues/1587
  //var timestamp = event.message.createTime;
  var timestamp = new Date();
  var date = Utilities.formatDate(timestamp, 'Asia/Tokyo', 'yyyy-MM-dd');
  var hour = Utilities.formatDate(timestamp, 'Asia/Tokyo', 'HH:mm');

  if(event.message.text.match(morning)) {
    status = "出勤";
    AddingSpreadsheet(status, username, date, hour);
    var message = name + "  さん、おはようございます！";
    
  }else if (event.message.text.match(leave)){
    status = "退勤";
    AddingSpreadsheet(status, username,  date, hour);
    var message = name + "  さん、お疲れさまでした！";
  }else{
    var message = morning + "または、" + leave +"を含む形で入力してください。";
  }

  return { "text": message };
}

function AddingSpreadsheet(status, user, eventdate, eventetime){
  // 特定のシートのIDを入力
  var id = "シートID"
  var ss = SpreadsheetApp.openById(id)
  var currentSheet = ss.getActiveSheet();
  currentSheet.appendRow([user, status, eventdate, eventetime])
}
```

チャットに記録された時間を記録したかったのですが、event.message.createTimeを取得すると、{'seconds': number, 'nanos': number}のように、出力されるフォーマットと想定と異なる出力になってしまったため、GASの組み込み関数を使用して、OnMessageの処理が走ったタイミングの日時で記録しています。まあ、勤怠で分単位の記録なので、さほど問題ないでしょう。
Eventのスキーマは以下のリファレンスにあります。
https://developers.google.com/chat/api/reference/rest/v1/Event

また、今回は特定のスプレッドシートの最終行の下に書き込んでいく処理になっていますが、スプレッドシートの指定、シートの指定など、いろいろできそうです。
先ほど、紹介したサンプルにもスプレッドシートのサンプルがありますので、ご確認ください。
https://developers.google.com/apps-script/reference/spreadsheet/sheet

スペースへアプリケーション追加後、初回実行時に認証が走るので、許可し、投稿をするとスプレッドシートに書き込みがはじまります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/284877/275d1156-0787-517d-b4d6-23c760491a3f.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/284877/ce29c359-79ed-64c6-8ace-d3177d28e1a9.png)

## デバック
例えば、日付の表示の確認など、GASで完結する処理を切り出して、ブラウザ上で特定の関数を実行することでデバックすることができますが、
onMessageなど、Google Chat APIからのEventデータを引数としているため、ブラウザ単体でのデバックができません。
Eventデータの中身を確認するためには、console.logを使い、console.log(event.message.text);、console.log(event);のような形でコード内に記述し、以下のスクショのようにGoogle Chat APIの構成でCloud Loggingにエラーを記録するを有効にすると、GCP上のログエクスプローラから確認することができます。（上記の記載だと、ログ SeverityはDebugで出力されます。）
※Cloud Loggingは課金されますので、注意してください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/284877/46f85fe0-45da-187e-86c5-8f47f6872fac.png)
Console Classについては、こちらを参照してください。 （Stackdriver Loggingと記載がありますが、Cloud Loggingのことです。）
[Class Console](https://developers.google.com/apps-script/reference/base/console)

# 所感
・今回、スプレッドシートに吐き出すだけの単純な処理でしたが、やろうと思えばかなりできることがありそうでした。

・GCP上のGoogle Chat APIでの構成部分が単一のアプリケーションしか登録できないようで、複数のGoogle Chatアプリを作るときは、都度GCP側のプロジェクトを分けないといけないのか気になりました。単一プロジェクト内で、複数のGoogle Chat APIの構成ができる方法を知っている方がいましたら、教えてください。

・もちろんのこと、GAS内でhttpリクエストができるので、APIが公開されているサードパーティへの連携は簡単にできそう。

・チーム開発でコード管理をgithub上で行いたい場合は、こちらの記事が参考にできそうでした。
[【Google Apps Script】GitHubを活用したチーム開発手順の解説](https://qiita.com/ffggss/items/3aac232bdb0fb33c980a)

・GASとは関係ありませんが、Google Chatにはスペースという機能があり、SlackやTeamsでいうところのチャンネルにあたるのですが、スペース内でスレッドを使うためには、作成時にあらかじめ有効にする必要があります。そして、有効にしたスペースではスレッドしか使えないため、Slackの返信に慣れていると少々使いにくい感があります。