【GAS】スポーツジムに行くようにLINEにせっついてもらう

#はじめに
ジムに一定の期間行っていなかったら自動で、「行かないんですか？」とLINEで受け取るというものをつくります。
今回はIFTTTと連携します。

なおLINE連携の設定に関しては割愛します。必要に応じて[こちら](https://qiita.com/i_kei/items/8c837444dcab6c0e4629#line%E3%81%A8%E3%81%AE%E9%80%A3%E6%90%BA%E8%A8%AD%E5%AE%9A)を参照していただければ。

#完成イメージ

|<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/394580/ee7c7133-d463-f36f-0961-c28d202be90e.png" width="500px">
|:-:|

①ジムのWi-Fiにつながったら、来たということと現在日時をスプレッドシートに入力する。
②ジムのWi-Fiが外れたら、帰ったということと現在日時をスプレッドシートに入力する。
③指定の時刻になったらスプレッドシートを読みに行き、記録された最終日時が一定期間以上前だったらLINEでメッセージを受け取る。

#準備
###IFTTTの設定
[IFTTT](https://ifttt.com/discover)にアクセスし、ログインを（まだの場合は会員登録も）します。

できたら、まずは
『もしスポーツジムのWi-FiにAndroid端末が接続したら、ConnectLogスプレッドシートにEnterと入力する』
というアプレットを作成していきましょう。

①New Applet

|![q_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/394580/317d9622-3eb1-78a1-d23a-6c100e986b46.png)
|:-:|

②this

|![q_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/394580/d79dca30-064e-3667-61b5-bb6b254ef4a2.png)
|:-:|

③Android Device

|![q_3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/394580/8509718a-904f-8e31-1e9f-5e4a9be11714.png)
|:-:|

④Connects to a specific WiFi network

|![q_4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/394580/1ce68258-e92b-32f9-2c02-d3f9d66f1675.png)
|:-:|

⑤スポーツジムのWiFiネットワーク名を設定 > ⑥Create trigger

|![q_5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/394580/885cd128-0a7a-80f6-e16a-cef3a4d45648.png)
|:-:|

⑦that

|![q_6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/394580/a0f1f674-2d6a-469a-6b75-4fdb785de7c3.png)
|:-:|

⑧Google Sheets

|![q_7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/394580/a50f5c13-20e8-600f-309d-a14aa662b9b0.png)
|:-:|

⑨Add row to spreadsheet

|![q_8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/394580/38428cdf-1d19-aef1-6b43-3d014ec016ef.png)
|:-:|

⑩Spreadsheet name：ConnectLog
⑪Formatted row：Enter
設定が完了したら > ⑫Create action

|![q_9.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/394580/628089ec-326f-8aba-2ae4-70bb892c3e6e.png)
|:-:|

⑬分かりやすいアプレット名に変更 > ⑭Finish

|![q_10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/394580/d22d94e0-c492-5706-367d-6372d00a2b3e.png)
|:-:|

▼▼▼

|![q_11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/394580/4e280825-8a07-a4b8-7c0c-0c3c5034d2bd.png)
|:-:|

次に
『もしスポーツジムのWi-FiがAndroid端末から外れたら、ConnectLogスプレッドシートにExitと入力する』
というアプレットを作成していきます。

①New Applet

|![q_12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/394580/80fd9016-535e-fd35-6206-e29dda56654d.png)
|:-:|

②this

|![q_13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/394580/bb52df9d-3890-264a-5ea4-6c37703bd17a.png)
|:-:|

③Android Device

|![q_14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/394580/07e0e4e8-57b4-3c78-d9b8-18e96d190d22.png)
|:-:|

④**Dis**connects from a specific WiFi network

|![q_15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/394580/5aac83bb-41ad-f4d7-acb5-ec44b663fd2d.png)
|:-:|

⑤スポーツジムのWiFiネットワーク名を設定 > ⑥Create trigger

|![q_16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/394580/159be893-cee7-2f18-f035-34bb7d25e4a5.png)
|:-:|

⑦that

|![q_17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/394580/d76e5f47-d959-5e8f-4219-2760d83516dc.png)
|:-:|

⑧Google Sheets

|![q_18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/394580/d2a07c63-5c12-0d42-c773-c895be5b6e71.png)
|:-:|

⑨Add row to spreadsheet

|![q_19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/394580/3459b7a5-05a6-2c0d-ac4e-2e7234155b26.png)
|:-:|

⑩Spreadsheet name：ConnectLog
⑪Formatted row：Exit
設定が完了したら > ⑫Create action

|![q_20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/394580/f2c3394e-44d4-77e7-b232-1ece898f6c36.png)
|:-:|

⑬分かりやすいアプレット名に変更 > ⑭Finish

|![q_21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/394580/bd2ba40b-e37f-01a8-4dd0-f663acb15f7e.png)
|:-:|

▼▼▼

|![q_22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/394580/d2b44db3-6217-a1c8-70b5-5375ed948627.png)
|:-:|

###Googleドライブのディレクトリ作成
当たり前のことなのですが、先ほどIFTTTで指定したディレクトリ（『Drive folder path』）がないとそもそもシートが作れません。
私が少し突っかかったので念のため書いておきます。

ということで、Googleドライブに IFTTT > Android Device ディレクトリを作っておきましょう。
もちろんIFTTT側の設定を変えても大丈夫です。

|![q_23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/394580/e7fae485-e47c-b43b-d470-e15e033df0a2.png)
|:-:|

###確認
設定ができたので動きを確認してみましょう。

設定したWifiにつなげてみて『ConnectLog』スプレッドシートにEnter、はずしてみてExitと入力されればＯＫです。

|![q_25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/394580/fa9f3f45-fb10-fcb3-7680-289d85b8f15e.png)
|:-:|

以上で準備が完了です。

#記録用スプレッドシートの設定
今回はシート側もごにょごにょします。

###コード
IFTTTでは現在日時の入力はできないので、スプレッドシートに組み込みます。

```js:コード.gs
function setDate() {
  const sheet = SpreadsheetApp.getActiveSheet();
  var lastRow = sheet.getLastRow();
  // 最終行の２列目に現在日付を設定します。
  sheet.getRange(lastRow, 2).setValue(new Date());
}
```
以上でコーディングが完了です。

###トリガーの設定
先ほどのsetDate()をシート変更時に自動で実行するように設定します。

このまま設定を進めていきましょう。
編集 > 現在のプロジェクトのトリガー > トリガーを追加
①実行する関数：setDate
②イベントのソース：スプレッドシートから
③イベントの種類：変更時
と設定 > ④保存
![q_24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/394580/53cd7907-aa7a-53e3-8aae-4bc985e3ac20.png)

以上でトリガーの設定が完了です。

#Standalone Scriptの設定
Standalone Script（以降、スタンドアロン）とは、Googleドライブ上に作る独立したGASプロジェクトを指します。
###コード

```js:main.gs
var week = 2;

function sendMessage() {
  if ( checkLog===true ) {
    var accessToken = PropertiesService.getScriptProperties().getProperty('LINE_TOKEN');
    var message = '最後にジムに行ってから' + week + '週間が経っています。そろそろ行きましょう！（最終日：';
    message += _formatDate(new Date(getLastDate())) + '）';
    var options =
     {
       'method'  : 'post'
      ,'payload' : 'message=' + message
      ,'headers' : {'Authorization' : 'Bearer '+ accessToken}
      ,muteHttpExceptions:true
     };
    UrlFetchApp.fetch('https://notify-api.line.me/api/notify',options);
  }
}

function checkLog() {
  var ret = false;
  var checkDate = new Date()
  checkDate = new Date(checkDate.getYear(),checkDate.getMonth(),checkDate.getDate() - week*7);
  checkDate = new Date(Utilities.formatDate(checkDate,'JST','yyyy/M/d') + ' 00:00:00'); // 一応時刻を揃えます
  var lastDate = new Date(getLastDate());
  lastDate = new Date(Utilities.formatDate(lastDate,'JST','yyyy/M/d') + ' 00:00:00');
  // 日付比較
  var dt = checkDate.getTime() - lastDate.getTime();
  var d = dt / (1000 * 60 * 60 * 24);
  // n週間前の日付が最終記録日時よりも大きい（新しい）場合、真とする
  if ( d > 0 ) ret = true;
  return ret;
}

function getLastDate() {
  var ssId = '********************************';
  var ss = SpreadsheetApp.openById(ssId);
  var sheet = ss.getSheetByName('シート1');
  // 打刻がうまくいっていなかったときのために
  // 念ため空を除きます
  var val = sheet.getRange('B:B').getValues().filter(String);
  return val[0,val.length-1];  // 最終行の値を返します
}

function _formatDate(dt) {
  const dow = ['日','月','火','水','木','金','土'];
  return Utilities.formatDate(dt,'JST','yyyy/M/d') + '(' +　dow[dt.getDay()]　+ ')';
}
```

コードはいたって単純です。先ほどの記録用スプレッドシートを読みに行き、日付比較してLINEにメッセージを送ります。
`var week = 2;` を変えれば3週間でも10週間でもそのまま使えます。
もっとストイックに6日以内にしたい場合もweekを使っているところを変えていきましょう。

さてsendMessage()を実行してみます。

|![line.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/394580/0ad5316e-6cb6-9761-ae53-4e5208ea8c7d.jpeg)
|:-:|

来ましたね！~~胃が痛い~~

以上でコーディングが完了です。

###トリガーの設定
こちらは時間でトリガーを引きます。

編集 > 現在のプロジェクトのトリガー > トリガーを追加
①実行する関数：sendMessage
②イベントのソース：時間主導型
③イベントの種類：日付ベースのタイマー
④時刻：午後１２時～１時
と設定 > ⑤保存

|![q_26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/394580/00520319-041a-32f5-83a3-6666fe893e03.png)
|:-:|

以上でトリガーの設定が完了です。

#まとめ
<details><summary>記録用スプレッドシートのコード</summary><div>

```js:コード.gs
function setDate() {
  const sheet = SpreadsheetApp.getActiveSheet();
  var lastRow = sheet.getLastRow();
  sheet.getRange(lastRow, 2).setValue(new Date());
}
```

</div></details>
<details><summary>スタンドアロンのコード</summary><div>

```js:main.gs
var week = 2;
/**
* メッセージ送信メイン処理
* @param none
* @return none
*/
function sendMessage() {
  if ( checkLog===true ) {
    var accessToken = PropertiesService.getScriptProperties().getProperty('LINE_TOKEN');
    var message = '最後にジムに行ってから' + week + '週間が経っています。そろそろ行きましょう！（最終日：';
    message += _formatDate(new Date(getLastDate())) + '）';
    var options =
     {
       'method'  : 'post'
      ,'payload' : 'message=' + message
      ,'headers' : {'Authorization' : 'Bearer '+ accessToken}
      ,muteHttpExceptions:true
     };
    UrlFetchApp.fetch('https://notify-api.line.me/api/notify',options);
  }
}
/**
* 設定日以降のログデータ有無を確認する。
* @param none
* @return {bool} 最終記録日時よりも新しい場合TRUE
*/
function checkLog() {
  var ret = false;
  var checkDate = new Date()
  checkDate = new Date(checkDate.getYear(),checkDate.getMonth(),checkDate.getDate() - week*7);
  checkDate = new Date(Utilities.formatDate(checkDate,'JST','yyyy/M/d') + ' 00:00:00');
  var lastDate = new Date(getLastDate());
  lastDate = new Date(Utilities.formatDate(lastDate,'JST','yyyy/M/d') + ' 00:00:00');
  // 日付比較
  var dt = checkDate.getTime() - lastDate.getTime();
  var d = dt / (1000 * 60 * 60 * 24);
  if ( d > 0 ) ret = true;
  return ret;
}
/**
* 最新記録日時を取得する。
* @param none
* @return {object} 最新記録日時
*/
function getLastDate() {
  var ssId = '***************************************';
  var ss = SpreadsheetApp.openById(ssId);
  var sheet = ss.getSheetByName('シート1');
  var val = sheet.getRange('B:B').getValues().filter(String);
  return val[0,val.length-1];
}
/**
* 日付整形
* @param {date} 日付
* @param {date} 整形後日付
*/
function _formatDate(dt) {
  const dow = ['日','月','火','水','木','金','土'];
  return Utilities.formatDate(dt,'JST','yyyy/M/d') + '(' +　dow[dt.getDay()]　+ ')';
}
```
</div></details>

あくまでも行くも行かないも自由なイベントが対象となるのであまり使う機会はなさそうですが、IFTTTとの連携をしてみたくてつくりました。~~便利というか、キケンな使い方が出来そうですね。~~

今回は行ったかどうかを判定するだけなので最後にいた日付だけあれば十分ですし、最大行数も気にしなくていいので上書きでいい気もしますが、どれくらいいたか記録したいような場合はこのままEnterとExitの時間を計算すればできますね。

また、GASをスタンドアロンと記録用スプレッドシートに分けましたが、記録用スプレッドシートにコードを全てまとめてしまっても大丈夫です。


#参考サイト
[お母さんは心配症 ? GASとIFTTTで出社と退社の状況をLINEに通知する ? - Qiita](https://qiita.com/sikkim/items/60eac02554b37b14e5a6)　とても参考になりました:bow:
[GoogleHome + IFTTTで睡眠時間を管理してみる - Qiita](https://qiita.com/siro33950/items/cc34bb516499c7fa67b0)

ありがとうございました。