SlackとGASで水分摂取量を管理してみた - 【STEP 1】GAS編

はじまりは健康診断

8月中旬、健康診断で「水分が足りていない」と指摘されました。
所説あるようですが、「体重×40ml」を目安にお水を飲みなさいとのこと。(体重が50kgの場合、50kg×40mlで2,000mlの計算)
毎回計算するのが面倒だったので、チャット上で手軽に記録するSlack Appを作成してみました。

Appイメージ

下図のイメージでSlack Appを作成します。
SlackのBot Userを窓口とし、入力イベントの検知にSlackのEvents APIを使用します。
SlackとGoogleのアカウントさえあれば作成できる構成にしています。

大変お世話になったページ: https://teppay.hatenablog.com/entry/2018/09/23/024620

完成イメージ

4つの機能の実現を目標とします。

A. 水分摂取量を記録       …数値を入力した場合(例:200)
B. 目標値を更新         …「goal 数字」と入力した場合(例:goal 2500)
C. 本日の達成状況と目標値を返信 …「check」と入力した場合
D. ヘルプを返信         …上記以外の言葉を入力した場合(例:aaa)

実現のステップ

3つのステップに分けてAppを実現していきます。

今回は【STEP 1】の手順をご紹介します。

作成手順

【STEP 1】GASからGoogleスプレッドシートへの記録

※GASとGoogle スプレッドシートの新規作成方法:https://tonari-it.com/gas-script-editor/

1. 記録用スプレッドシートの作成

記録用のスプレッドシートを作成します。
今回は1行目に項目名を4つ、2行目に初期値を入力しました。(下図参照)
※進捗 (%) は目標達成率の計算式を入力:=B2/A2*100

スプレッドシートURLからIDを抜き出し、コピーしておきます。(下記太字の部分)
https://docs.google.com/spreadsheets/d/スプレッドシートID/edit#gid=0

2. GASの実装

手順1でコピーしたスプレッドシートIDを使用して、次のように実装します。

function doPost(e) {

  // パラメータ
  var postData = e.postData.getDataAsString();

  // 記録用シート取得
  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);
  }

  // 記録
  if (/^-?\d+$/.test(postData)) {
    recordSheet.getRange(2, 2).setValue(recordSheet.getRange(2, 2).getValue() + Number(postData));
  }
}

実装のポイント

・パラメータの取得
 今回は単純なテキスト1つをパラメータで受け取る想定のため、e.postDataをStringで取得します。

  // パラメータ
  var postData = e.postData.getDataAsString();

・記録用シートの取得
 スプレッドシートIDとシート名を指定することで、スプレッドシートへの記録の準備が整います。
 今回はスプレッドシートが1シートしかない前提で実装します。

  // 記録用シート取得
  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);
  }

・パラメータのチェック
 受け取ったパラメータが数値でない場合は記録の計算ができないため、正規表現でパラメータのチェックを行います。
 パラメータが数値のみだった場合はスプレッドシートに記録の加算を行います。
 誤入力を修正するケースを考慮し、マイナス値も可とします。

  // 記録
  if (/^-?\d+$/.test(postData)) {
    recordSheet.getRange(2, 2).setValue(recordSheet.getRange(2, 2).getValue() + Number(postData));
  }

実装したらCtrl + Sキーで保存します。

3. スプレッドシートへのアクセス承認

GASのプロジェクトからスプレッドシートへのアクセス承認が必要なため、導入前に一度テスト実行します。
「実行>関数を実行>doPost」をクリックするとダイアログが表示されるため、「許可を確認」から承認を行います。

Googleアカウントを選択し、
「詳細」→「DrinkSupporterProject(安全ではないページ)に移動」→「許可」の流れで承認を行います。

パラメータ(e)を渡していないためエラーメッセージが表示されますが、この時点では問題ありません。

4. ウェブアプリケーションの公開設定

上部のタブから「公開>ウェブアプリケーションとして導入」を選択します。

次のように設定し、「導入」ボタンを選択します。
・次のユーザーとしてアプリケーションを実行:自分
・アプリケーションにアクセスできるユーザー: 全員(匿名ユーザーを含む)

表示された「現在のウェブアプリケーションのURL」をコピーします。(動作確認で使用)

【STEP 1】の作業はこれで完了です。

動作確認

curlコマンドで確認を行います。(curlコマンドはWindows10から使用可能となったようです)
作成手順4でコピーしたURLを使用し、下記コマンドを実行します。

curl -X POST -H "Content-Type: text/plain" -d "100" -L "作成手順4でコピーしたURL"

※curlコマンド実行がうまくいかない場合は下記ページが参考になる可能性あり
・プロキシ設定(タイムアウトする場合):https://qiita.com/hamham/items/cb658f5a8c74f35255be
・文字コード設定(文字化けする場合) :https://qiita.com/user0/items/a9116acc7bd7b70ecfb0

記録用スプレッドシートを開くと、「-d」で指定した数値(100)が反映されたことが確認できます。

まとめ

【STEP 1】では4つの手順でGASからGoogleスプレッドシートへの記録を実現することができました。

 1. 記録用スプレッドシートの作成
 2. GASの実装
 3. スプレッドシートへのアクセス承認
 4. ウェブアプリケーションの公開設定

次回はSlackからGASへ記録をリクエストする方法をご紹介したいと思います。
参照:SlackとGASで水分摂取量を管理してみた【STEP 2】Events API編 | CCI TECH BLOG