GASでLINEリマインダーを作る。(2)

##動機
大学サークルの日程調整をよくLINEで行い、リマインドを毎回行うのが面倒で｢自動化できたらな｣と思っていたので作成に至った。



##目標
学習の目標
GASの基本をマスター

Javascriptの書き方
Google Apps Scriptの書き方
動的型付け言語の書き方
プログラムの目標
予定の追加(Google Form)
予定の記録(SpreadSheet)
予定の確認(GAS)
予定のリマインド(LINE)
以上を有するLINEBotを作る。

##解説
https://qiita.com/1_s_n/items/7dc47e366fbf5acdb319
の続きです。
前回書ききれなかったリマインダーのコードを載せます。
前回より大幅アップデートをしました。
まずはコードを御覧ください

```javascript:remind.gs
///////////////////////////////////////////////////////////////////////////////////////////////////
//LINE送信部////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////


//配列用メモ
//0.タイムスタンプ
//1.メールアドレス	
//2.予定名	
//3.場所	
//4.予定の説明	
//5.イベントの長さ	
//6.開始日程	
//7.終了日程	
//8.開始日程	
//9.終了日程	
//10.登録者名	
//11.MARK

function pushMessage(e) {

//Date型に変換してから引数受け取り

  var userID=userid(); //UserIDをスプレッドシートから取得する関数を作成,めんどければ直指定でOK
  const endDate=e[0][7]; //Date型で日付格納
  const date1=Utilities.formatDate(e[0][6], "JST", "MM'/'dd");
  const date2=Utilities.formatDate(e[0][7], "JST", "MM'/'dd");
  var DateA;
  

 //当日のみの日程なら｢〜｣を使わないで日付のみ
  if (e[0][4] == "終日") {
    if (date1 != date2) {
      DateA = Utilities.formatDate(e[0][6], "JST", "MM'/'dd' '") + ' ~ ' + date2 + '\n';
    } else {
      DateA = Utilities.formatDate(e[0][6], "JST", "MM'/'dd' '") + '\n';
    }
  } else {
    if (date1 != date2) {
      DateA = Utilities.formatDate(e[0][6], "JST", "MM'/'dd' 'hh:mm") + ' ~ ' + Utilities.formatDate(endDate, "JST", "MM'/'dd' 'hh:mm") + '\n';
    } else {
      DateA = Utilities.formatDate(e[0][6], "JST", "MM'/'dd' 'hh:mm") + ' ~ ' + Utilities.formatDate(endDate, "JST", "hh:mm") + '\n';
    }
  }

  var postData;
  
//LINEのFLEXメッセージ(カードみたいなやつ)用JSON
  postData = {
    "to": userID,
    "messages": [{
      "type": "flex",
      "altText": '【リマインド】',  //既読付ける前の画面に表示されるやつ
      "contents": {
        "type": "bubble",
        "hero": {
          "type": "box",
          "layout": "vertical",
          "contents": [{
            "type": "text",
            "text": "☆リマインド☆",  //メッセージタイトル
            "weight": "bold",
            "position": "relative",
            "align": "start",
            "gravity": "top",
            "wrap": true,
            "size": "lg",
            "margin": "md",
            "decoration": "none",
            "offsetStart": "10px",
            "offsetTop": "5px"
          }, {
            "type": "text",
            "text": "明日です!",  //サブタイトル(前日にリマインドされる前提)
            "size": "xs",
            "offsetStart": "10px",
            "offsetTop": "2px"
          }]
        },
        "body": {
          "type": "box",
          "layout": "vertical",
          "contents": [{
            "type": "text",
            "text": e[0][2], //予定名
            "weight": "bold",
            "size": "xl"
          }, {
            "type": "box",
            "layout": "vertical",
            "margin": "lg",
            "spacing": "sm",
            "contents": [{
              "type": "box",
              "layout": "baseline",
              "spacing": "sm",
              "contents": [{
                "type": "text",
                "text": "場所",
                "color": "#aaaaaa",
                "size": "sm",
                "flex": 1
              }, {
                "type": "text",
                "text": e[0][3], //場所
                "wrap": true,
                "color": "#666666",
                "size": "sm",
                "flex": 5
              }]
            }, {
              "type": "box",
              "layout": "baseline",
              "spacing": "sm",
              "contents": [{
                "type": "text",
                "text": "日時",
                "color": "#aaaaaa",
                "size": "sm",
                "flex": 1
              }, {
                "type": "text",
                "text": DateA, //日時
                "wrap": true,
                "color": "#666666",
                "size": "sm",
                "flex": 5
              }]
            }]
          }, {
            "type": "box",
            "layout": "baseline",
            "spacing": "sm",
            "contents": [{
              "type": "text",
              "text": "詳細",
              "color": "#aaaaaa",
              "size": "sm",
              "flex": 1
            }, {
              "type": "text",
              "text": e[0][4],
              "wrap": true,
              "color": "#666666",
              "size": "sm",
              "flex": 5
            }]
          }]
        },
        "footer": {
          "type": "box",
          "layout": "vertical",
          "spacing": "sm",
          "contents": [{
            "type": "button",
            "style": "link",
            "height": "sm",
            "action": {
              "type": "uri",
              "label": "他の日程を確認",
              "uri": "--------------" //他の日程
            }
          }, {
            "type": "spacer"
          }],
          "flex": 0
        }
      }
    }]
  };

//push部
  
  var url = "https://api.line.me/v2/bot/message/push";
  var headers = {
    "Content-Type": "application/json",
    'Authorization': 'Bearer ' + CHANNEL_ACCESS_TOKEN,
  };

  var options = {
    "method": "post",
    "headers": headers,
    "payload": JSON.stringify(postData)
  };
  var response = UrlFetchApp.fetch(url, options);
  
}

```

postdataの中のJsonはLINEMessageAPIにて使用を確認してください。
画像や地図データなども利用可能らしいです。

Utilities.formatDateメソッドは第1引数にDate型を指定しなければならないので、SpreadSheetから読み込んだ変数をそのまま利用してはいけません。
このコードを利用するならば、呼び出し元でDate型に変換しましょう。

###以下、蛇足(すっとばして結構)
```javascript:remind.gs
var date1=new Date(e[0][6]);
```
などで変換することができます。私は静的型付け言語しか学んだことがなかったので、当たり前といっちゃ当たり前なのですが、Web系のプログラミングしか行ったことのない方には疑問に思うかもしれません。


整数→int型
浮動小数点→float型 double型
文字→char型(1文字)
などがあります。これらは、C言語やJavaなどを学習すると必ずでてきます。抑えておきましょう。

```c:sample.c
#include <stdio.h>
int main(){
  int a;
  float b;
  char c;

  return 0;

}
```

など、javascriptでvarだけだった変数宣言がいちいち型を宣言しなければなりません。
変数宣言と違う型をその変数に代入しようとするとコンパイルエラーになります。

###プログラミング学習についての持論を展開･･･
静的型付け言語と呼ばれる部類のプログラミング言語は変数宣言時に必ず型を指定しなければなりません。
こちらが正攻法です。
javascriptなどの動的型付け言語は、型を推論しています。そのため自分の予測していなかった型の変数宣言となっていたり、変数値を変えることで値が型が変化する場合があります。ありがたいこともありますが、今この変数は何型だっけ？というようなことが度々起きます。

型を意識したプログラミングをしたい場合は、CやJavaなどをお勧めします。
持論ですが、CとC++をしっかりやった後に他のプログラミングをやった方が、プログラミング言語の基礎が身につくと思います。Cでプログラミングの基礎を学んで、C++でクラスについて学ぶと良いでしょう。



型については、以下のサイトをご覧ください。
https://www.sejuku.net/blog/25517


##後々、改善すべきだと思ったこと
###Formを投稿するとすぐに送信されてしまう。
トリガーをフォーム送信時としていることから、Google Formを送信した瞬間にそのデータを送信してしまします。
そのためわざわざLINEに流すまでもないことは鬱陶しいので防止する機能を実装する必要がありそうだと思いました。

###保守が複雑すぎる
このコード割と初期よりもコンパクトにしましたが、FlexメッセージのJsonの行数が多すぎて肥大化してしまいました。
また、MessageAPIのAPIキーや送信先のUSERID、情報記録SpreadSheetID、が変更になった場合全てのプロジェクトに設定し直さなければなりません。

###便利だと感じている人が少ない･･･
僕がリマインド忘れないようにやればいいだけなんですけどね


##追伸
投稿遅れてすいません。大学の春休み延長線で萎えておりました。
すいません。受験しようと思っていた基本情報技術者試験も中止になりましたので書きました。

いつまでコロナ騒動は続くのか。
情報技術でなんとか解決できないものですかね。