旅程をLINEに知らせてもらおう

#概要#
私の所属クラブで鉄道旅行をするということになりましたが、その際乗車する車両を確実にわかっている必要があります。しかし…

**私は、忘れんぼうなのです!!**

今まではいちいち計画表を取り出して見ていたのですが、正直、めんどくさいです。
この作業を、いつも握っていると言っても過言ではないスマホに、**自動**で、知らせてもらおうということです。

スマホに通知する方法はたくさんあると思います。今回は汎用性があったほうが良いと思ったので(汎用性があれば他の部員も使えるしね!)、**LINE Notify** を使った方法を取りました。

#構想#
はてさて、LINEから通知してもらおうと考えるのはいいものの、その方法、タイミングはどうしましょうか…

私が真っ先に思いついたのはかの有名なSNS・IoT統合サービス、**"IFTTT"**です。

IFTTTには、"that"にLINE Notifyにメッセージを送るコマンドがあります。
それを利用する方向で行きましょう。
![スクリーンショット 2018-08-08 22.08.45.png](https://qiita-image-store.s3.amazonaws.com/0/183170/8093920f-828c-44a7-6102-d0fc44b7ece8.png)
では"this"のほうのトリガーはどうしましょうか。
IFTTTには、"Date&Time"というトリガーがあり、`毎 年・月・週・日・時`から選ぶことができます。
![スクリーンショット 2018-08-08 22.01.46.png](https://qiita-image-store.s3.amazonaws.com/0/183170/7e3b229d-3cf0-8f11-3d00-3976dfd9822f.png)
しかし!!
乗車予定の全列車分を作るとなるとなかなか厳しいものです(なにせ2泊3日なので)。

さあどうしたものか…

##結論##
IFTTTには最強と言っても過言ではないトリガーがあります。
それが **"Webhooks"** です!!
![スクリーンショット 2018-08-17 19.21.18.png](https://qiita-image-store.s3.amazonaws.com/0/183170/6606a18e-1241-36bc-5d21-34687cac1816.png)
僕もまだまだ初心者なのでうまく説明できませんが、インターネット経由で要求を送る・受けることができる手法です。
これを今回はGAS(Google Apps Script)から送信させて見ることにします。

##図で説明##
![IMG_5163.JPG](https://qiita-image-store.s3.amazonaws.com/0/183170/a925e3d2-c2f3-3090-090a-feac354a9ccb.jpeg)
①Google Drive上にあるSpread sheetから情報を取得
②Google Apps ScriptによりIFTTTへPOSTを送信
③IFTTTがレシーブ
④-1 LINE Notifyによりメッセージを送信
④-2 IFTTTからIFTTTへ更新用のメールを送信させる
(これについては後で補足します)

#製作#
それでは過程を説明していきます。
##Google Spread SheetとGoogle Apps Script
まずは,Google DriveからGoogle Spread Sheetを作成します。
![スクリーンショット 2018-08-17 20.40.13.png](https://qiita-image-store.s3.amazonaws.com/0/183170/5605600d-d791-bcf4-4cf0-d41602c14e0f.png)
新規から空白のスプレッドシートを作成します。
次に、「ツール」から「スクリプトエディタ」を起動します。
![スクリーンショット 2018-08-17 20.43.39.png](https://qiita-image-store.s3.amazonaws.com/0/183170/6faaf766-913b-e652-6abe-469158e27bc9.png)

ここに以下のようなコードを書きます。

```js:コード.gs
function myFunction() {
  var ss = SpreadsheetApp.getActiveSpreadsheet();//Spreadsheetの情報の取得
  var sheet = ss.getSheetByName('シート1');//Sheetの指定
  var range = sheet.getRange('A1');//セルの指定
  var state = range.getValue();
  
  Logger.log("Spreadsheetは"+state+"です。");
  
  if(state=="ON"){
    var date = new Date();
    var NOWTIME=Utilities.formatDate( date, 'Asia/Tokyo', 'hh:mm');
    var TODAY=Utilities.formatDate( date, 'Asia/Tokyo', 'MM/dd');
    var AMPM=Utilities.formatDate( date, 'Asia/Tokyo', 'a');
    Logger.log(TODAY+" "+AMPM+" "+NOWTIME);
    
    var program=false;
    
    for(var fori=2;fori<=sheet.getLastRow();fori++){
      if((sheet.getRange(fori,2).getValue()==NOWTIME)&&(sheet.getRange(fori,3).getValue()==TODAY)&&(sheet.getRange(fori,1).getValue()==AMPM)){
        Logger.log("プログラムは実行されました");
        task(sheet.getRange(fori,4).getValue());
        task2();
        Writing("LOG" , SpreadsheetApp.getActiveSpreadsheet().getSheetByName("LOG").getLastRow()+1 , 1 , TODAY+" "+AMPM+" "+NOWTIME+" プログラムは実行されました。");
        program=true;
      }
    }
    
    if(program==false){
      Logger.log("E001 プログラムは実行されませんでした");
    }
  }
  else{
    Logger.log("E002 プログラムは実行されませんでした");
  }
}

function task(STRING){
  var Sendingmassage=STRING;
  
  // IFTTTにWebHookをPOSTする
  function sendIFTTTWebHook(endpoint, value) {
    var message = {
      "value1":value
    };
    
    var options = {
      "method":"POST",
      "headers": {
        "Content-Type":"application/json"
      },
      "payload":JSON.stringify(message)
    };
    
    UrlFetchApp.fetch("https://maker.ifttt.com/trigger/" + endpoint + "/with/key/XXXXX",options); 
 }
                      
 sendIFTTTWebHook("Railway",Sendingmassage);
}

function task2(){
  var Sendingmassage="";
  
  // IFTTTにWebHookをPOSTする
  function sendIFTTTWebHook(endpoint, value) {
    var message = {
      "value1":value
    };
    
    var options = {
      "method":"POST",
      "headers": {
        "Content-Type":"application/json"
      },
      "payload":JSON.stringify(message)
    };
    
    UrlFetchApp.fetch("https://maker.ifttt.com/trigger/" + endpoint + "/with/key/XXXXX",options); 
 }
                      
 sendIFTTTWebHook("Recieve",Sendingmassage);
}

function Writing(sheet_name,sheet_X,sheet_Y,Writing_String){
  var ss = SpreadsheetApp.getActiveSpreadsheet();//Spreadsheetの情報の取得
  var sheet = ss.getSheetByName(sheet_name);//Sheetの指定
  var range = sheet.getRange(sheet_X,sheet_Y);//セルの指定
  
  range.setValue(Writing_String);
}
```

申し訳ないですが全て説明しているとキリが無いのでざっくり説明しておきます。
それぞれのコードのわからない部分はGoogle先生に聞けばすぐわかります。

##コードの説明##
1. スプレッドシートの情報を取得する
2. 現在時刻と照らし合わせ、送信すべきか判断
3. 2がTrueならばIFTTTにPOST
4. 別のシートにLOGを残す

これにより
`列AにAMかPM`
`列Bに時刻`
(注:かなり特殊な12h制なのでご自身でlogを出して確かめてみてください)
`列Cに日付`
`列Dにメッセージ内容`
を書くことで、任意のタイミングでPOSTを送ることができます。
![スクリーンショット 2018-08-17 21.50.45.png](https://qiita-image-store.s3.amazonaws.com/0/183170/216d3969-8d1e-9fcc-1e28-6ea4962768c3.png)
(A1に関してはON/OFFを制御するセルになっています)

ただし、このスプレッドシートを常時監視(入力した時刻と合っているかを確かめるため)する必要があります。
そこでトリガーを毎分に設定しておきましょう
![スクリーンショット 2018-08-17 21.14.55.png](https://qiita-image-store.s3.amazonaws.com/0/183170/8b98fd59-861e-960d-424f-bd8c96b08582.png)
![スクリーンショット 2018-08-17 21.17.55.png](https://qiita-image-store.s3.amazonaws.com/0/183170/a754d281-1bba-807c-7d35-6d099ea2685e.png)

##IFTTT側の設定##
大まか流れは
1. `this`を**Webhooks**にし
2. `then`を**LINE Notify**にしたAppletを作る
3. Webhooksに必要なKeyをGASに書き加える

3についてですが、
![スクリーンショット 2018-08-17 21.34.02.png](https://qiita-image-store.s3.amazonaws.com/0/183170/9dada4cf-e3b3-e53d-b364-28f4c1809f72.png)
このアイコンのあたりをクリックすると
![スクリーンショット 2018-08-17 21.42.15.png](https://qiita-image-store.s3.amazonaws.com/0/183170/b63707a1-f6e4-1f44-75a3-f11a71e3c740.png)
こんなページに移動するので、ここで**"Documentation"**を押しましょう。
そうすると`Your key is: .......`てなことがでっかく書かれているページに飛びます。
そこのKeyをコピーし、先程のGASコードの`XXXXX`の部分を置き換えましょう。

同様に
1. `this`を**Webhooks**にし
2. `then`を**Gmail**にしたAppletを作る
3. Gmailで送信するアドレスの宛先はtrigger@Applet.ifttt.comに設定

これも作って起きましょう。

##LINE Notifyについて##
まず、LINE Notifyを友達として追加する必要があります。
ただ、よくある公式アカウントと全く同じ類であるため、検索すればすぐ出てきます。

個人で使いたい場合は、IFTTTで`1:1でLINE Notifyから通知を受け取る`を選択しましょう。
グループで使用する場合はIFTTTで任意のグループを選択。
また、事前に当該グループにLINE Notifyを招待しておきましょう。

##IFTTTに更新用のメールを送信する理由##
このプロジェクトの肝となるのが**リアルタイム性**です。
乗り遅れたりすると意味がないわけで、指定した時間どおりに送ってもらわなければ意味がありません。
しかし、私がテストしたところ、IFTTTにトリガーのチェックを掛けない限り、15分ほど経たないと実行されないことがわかりました。
これは困ったもんだ…
ここで思ったのは、

「じゃあ任意のタイミングでIFTTTがチェックするようにできれば良くね？」

そんな願いを叶えるべく、IFTTTにはメールを受信することで全Appletをチェックする機能があります。
ということで、完成した形が

1. GASからIFTTTのWebhookへPOST
2. IFTTTからGmailトリガーを使いIFTTTへとメールを送信(アドレス:trigger@Applet.ifttt.com)
3. 受信したIFTTTは全Appletをチェック
4. 本来動かしたい方のAppletが動作
5. LINEに通知が届く

というプロセスです。
trigger@Applet.ifttt.comにはIFTTTのアカウントと同じアドレスから送る必要があります。
一番楽なのは上記の通りIFTTTにはGmailアカウントで登録し、IFTTTのGmailトリガーを使う方法です。
Gmailトリガーには送信主を入力する項目がありませんが、それはIFTTTに紐づけたGoogleアカウントのメアドなので、問題ありません。

#まとめ#
ということで、今回上手く自分の作りたいものを作ることができました。
GASに関しては初心者なので下手だとは思いますが、プロセスだけでも、よかったら参考にしてみてください。