Line APIとGAS(Google App Script)でGoogleカレンダーを登録・取得する

Gasの初学者です
勉強の為にLine API を使ってGoogleカレンダーの追加・取得を開発しました
備忘録のために投稿します

何か改善点あればアドバイスいただけると嬉しいです
# 準備
Line Developerよりトークン取得
# 動作手順
●予定追加→日付入力→開始時間入力→終了時間入力→確認して"はい"ならカレンダーに登録,"いいえ"ならキャンセル
●予定確認(日付指定)→日付入力→取得期間入力→取得(ない場合は何もないことを返信)
●予定確認(月指定)→日付入力→取得(ない場合は何もないことを返信)
![Screenshot_20221030-064106.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2916541/9f64667a-5f56-2422-ea49-b2f43326de8c.png)
![Screenshot_20221030-064206.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2916541/e9f6cc94-81cd-6f68-a0be-bd8e5ddb0e7b.png)
![Screenshot_20221030-064235.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2916541/e87b307f-2cb8-fc68-083d-24140c4a24dd.png)
![Screenshot_20221030-065232.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2916541/b0260afb-3310-46b6-dff0-c4dcd3f749cc.png)

# 今後への改善点
- リッチテキストの追加
- キャンセル機能の追加
- ソースコードが長すぎる,変数名がわかりずらい
# ソースコード
```
//トークン
const token = "取得したトークン";

//リプライURL
const url = 'https://api.line.me/v2/bot/message/reply';

//-------------------------------------------------------------------------------------------
function doPost(e) {
  let eventData = JSON.parse(e.postData.contents).events[0];
  let replyToken = eventData.replyToken;
  if (typeof replyToken === 'undefined') {
    return;
  }
  let userMessage = eventData.message.text;
  let cache = CacheService.getScriptCache();
  let type = cache.get('type');　　　　　　　　　　　
  if (type === null) {
    if (userMessage == '予定追加') {             //予定追加メッセージで予定を追加する
      cache.put('type', 1);　　　　　　　　　　　　　
      reply(replyToken, '何日ですか？\n〇月〇日,〇/〇形式でお願いします');
    } else if (userMessage == '予定確認') {      //予定確認で予定を確認するフロー
      cache.put('type', 6);　　　　　　　　　　　　　
      reply(replyToken, '何日ですか？\n〇月〇日,〇月の形式でお願いします');
    } else {                                    
      reply(replyToken, '不正な値です\もう一度初めからお願いします');
      return;                                   　//予定追加以外は不正な値
    }
  }
  switch (type) {
    case '1': //予定追加の後の処理
      try {
        cache.put('type', 2);                       
        let userMessage1 = hankakuConv(userMessage);//送信した日付の数字を半角に直す
        let msgDate = userMessage1.match(/\d+/g);　 //日付数字部分だけ抽出
        cache.put('month', msgDate[0]);　　　　　　　 //月を格納
        cache.put('day', msgDate[1]);　　　　　　　　 //日を格納
        reply(replyToken, '開始時間は？\n16時30分,16：30形式でお願いします');
        break;
      } catch (error) {　//エラー処理　　　
        cache.remove('type');　　　　　　　　　　　　　　
        reply(replyToken, '不正な値です\もう一度初めからお願いします');
        break;
      }
    case '2': //開始時間を入力
      try {
        cache.put('type', 3);  
        let userMessage1 = hankakuConv(userMessage);//送信した日付の数字を半角に直す
        let startHour = userMessage1.match(/\d+/g); //日付数字部分だけ抽出
        if (startHour[1] == null) {　　　　　　　　　 //〇分がない場合は00を追加する
          startHour[1] = '00';
        }
        cache.put('starthour', startHour[0]);　　　　//時格納
        cache.put('startminutes', startHour[1]);　　//分格納
        reply(replyToken, '終了時間は？');
        break;
      } catch (error) {　//エラー処理　　　
        cache.remove('type');　　　　　　　　　　　　　
        cache.remove('month');
        cache.remove('day');
        reply(replyToken, '不正な値です\もう一度初めからお願いします');
        break;
      }
    case '3': //終了時間を入力
      try {
        cache.put('type', 4);　　　　　　　　　　　　　　
        let userMessage1 = hankakuConv(userMessage);//送信した日付の数字を半角に直す
        let endHour = userMessage1.match(/\d+/g);　 //日付数字部分だけ抽出
        if (endHour[1] == null) {　　　　　　　　　 　//〇分がない場合は00を追加する
          endHour[1] = '00';
        };
        cache.put('endhour', endHour[0]);　　　　　　//分格納　
        cache.put('endminutes', endHour[1]);　  　　//時格納
        reply(replyToken, '予定名を教えてください');
        break;
      } catch (error) {　//エラー処理　　　
        cache.remove('type');　　　　　　　　　　　　　
        cache.remove('month');
        cache.remove('day');
        cache.remove('starthour');
        cache.remove('startminutes');
        reply(replyToken, '不正な値です\もう一度初めからお願いします');
        break;
      };
    case '4': //予定名を入力
      cache.put('schedule', userMessage);　　　　　　　　 　      //予定名格納
      cache.put('type', 5);　　　　　　　　　　　　　　　　　　
      let month1 = cache.get('month');　　　　　　　　　　        //日付月格納
      let day1 = cache.get('day');　　　　　　　　　　　　 　      //日付日格納
      let starthour1 = cache.get('starthour');　　　　  　      //開始時間(時)格納
      let startminutes1 = cache.get('startminutes');　         //開始時間(分)格納
      let endhour1 = cache.get('endhour');　　　　　  　 　      //終了時間(時)格納
      let endminutes1 = cache.get('endminutes');　　　  　      //終了時間(分)格納
      cache.put('scheduleDate', month1 + '/' + day1);　        //予定日付〇/〇に成形して格納
      cache.put('startTime', starthour1 + ':' + startminutes1);//開始時間〇:〇に成形して格納
      cache.put('endTime', endhour1 + ':' + endminutes1);      //終了時間〇:〇に成形して格納
      reply(replyToken, '間違いないですか？\n' + '・' + month1 + '月' + day1 + '日\n・' + starthour1 + '時' + startminutes1 + '分' + '～' + endhour1 + '時' + endminutes1 + '分\n・' + userMessage + '\n\n〇はい\n〇いいえ');
      break;　　　　　　　　　　　　　　　　　　　　　　　　　　　
    case '5': //予定追加する
      if (userMessage === 'はい') {　　　　　　　　　　　　 //はいの場合
        let scheduleDate = cache.get('scheduleDate');　　//予定日付取得
        let startTime = cache.get('startTime');　　　　 　//開始時間取得
        let endTime = cache.get('endTime');　　　　　　　　//終了時間取得
        let schedule = cache.get('schedule');　　　　　　　//予定名取得
        calendarPush(schedule, scheduleDate, startTime, endTime);
        reply(replyToken, '追加しました');　　　　　　　　　　//カレンダーに追加
        cache.remove('type');　　　　　　　　　　　　　　　　　
        cache.remove('month');
        cache.remove('day');
        cache.remove('starthour');
        cache.remove('startminutes');
        cache.remove('endhour');
        cache.remove('endminutes');
        cache.remove('endhour');
        cache.remove('scheduleDate');
        cache.remove('startTime');
        cache.remove('endTime');
      } else {　　　　　　　　　　                  　　　　//いいえの場合
        cache.remove("type");　　　　　　
        cache.remove('month');　　　　　
        cache.remove('day');
        cache.remove('starthour');
        cache.remove('startminutes');
        cache.remove('endhour');
        cache.remove('endminutes');
        cache.remove('endhour');
        cache.remove('scheduleDate');
        cache.remove('startTime');
        cache.remove('endTime');
        reply(replyToken, 'もう一度初めからお願いします');
      };
      break;
    case '6': //予定確認後の後の処理
      try {　　//日付指定
        cache.put('type', 7);                       
        let userMessage1 = hankakuConv(userMessage);　　//送信した日付の数字を半角に直す
        let msgDate = userMessage1.match(/\d+/g);　 　　//日付数字部分だけ抽出
        cache.put('monthh', msgDate[0]);　　　　　　　　　//月を格納
        cache.put('dayy', msgDate[1]);　　　　　　　  　　//日を格納
        if (msgDate[1] == null) { //月指定で予定を取得する
          let replyEvent1 = mycalendarGet1(msgDate[0]);//予定取得
          reply(replyToken, replyEvent1);
          cache.remove('type');　　　　　　　　　　　　　　
          cache.remove('monthh');
          cache.remove('dayy');
          break;
        } else { //日時指定
          cache.put('monthhdayy', msgDate[0] + '/' + msgDate[1]);
        };                                             //〇/〇に成形
        reply(replyToken, '何日間必要ですか？');
        break;
      } catch (error) {　//エラー処理
        cache.remove('type');　　　　　　　　　　　　　　
        reply(replyToken, '不正な値です\もう一度初めからお願いします');
        break;
      };
    case '7': //日付と期間指定で予定取得
      try {
        let userMessage1 = hankakuConv(userMessage);//送信した日付の数字を半角に直す
        let startDay = cache.get('monthhdayy');     //日付取得
        let replyEvent = mycalendarGet(startDay, userMessage1);
        reply(replyToken, replyEvent);
        cache.remove('type');　　　　　　　　　　　　　　
        cache.remove('monthh');
        cache.remove('dayy');
        cache.remove('monthhdayy');
        break;
      } catch (error) { //エラー処理
        cache.remove('type');　　　　
        cache.remove('monthh');
        cache.remove('dayy');
        reply(replyToken, '不正な値です');
        break;
      };
  };
};

//-----------------------------------------------------------------------------------------------------
//メッセージ送信関数
function reply(replyToken, body) {
  let payload = {
    'replyToken': replyToken,
    'messages': [{
      'type': 'text',
      'text': body
    }]
  };
  let options = {
    'payload': JSON.stringify(payload),
    'method': 'POST',
    'headers': { "Authorization": "Bearer " + token },
    'contentType': 'application/json'
  };
  let replyMessage = UrlFetchApp.fetch(url, options);
  return replyMessage;
}
//-----------------------------------------------------------------------------------
//カレンダー登録関数
function calendarPush(title, scheduleDate, startTime, endTime) {
  let calendarGet = CalendarApp.getDefaultCalendar();
  let year = new Date().getFullYear();
  let start = new Date(year + '/' + scheduleDate + ' ' + startTime);
  let end = new Date(year + '/' + scheduleDate + ' ' + endTime);
  let calendarPush = calendarGet.createEvent(title, start, end);
  return calendarPush;
}
//---------------------------------------------------------------------------------------
//全角英数字を半角に直す関数
function hankakuConv(str) {
  return str.toString().replace(/[Ａ-Ｚａ-ｚ０-９]/g, function (s) {
    return String.fromCharCode(s.charCodeAt(0) - 0xFEE0);
  });
};
//---------------------------------------------------------------------------------------
//カレンダーから指定した日にちの予定取得
function mycalendarGet(startD, daySpace) {
  let myCalender = CalendarApp.getDefaultCalendar();
  let year = new Date().getFullYear();
  let start = new Date(year + '/' + startD);
  let end = new Date();
  let body = '';
  let body1 = '';
  for (let i = 0; i <= daySpace; i++) {
    end.setDate(start.getDate() + i);
    let endD = Utilities.formatDate(end, 'JST', 'MM/dd');
    let event1 = myCalender.getEventsForDay(end);
    if (event1.length !== 0) {
      for (let j = 0; j <= event1.length - 1; j++) {
        body = body + '\n' + event1[j].getTitle();
      };
      body1 = body1 + endD + body + '\n';
    };
    body = '';
  };
  if(body1 === ''){
    body1 = '何もありません';
  }else{
  body1 = body1 + '\n確認してください';
  };
  return body1;
}
//----------------------------------------------------------------------
//カレンダーから指定した月の予定取得
function mycalendarGet1(startD) {
  let myCalender = CalendarApp.getDefaultCalendar();
  let year = new Date().getFullYear();
  let start = new Date(year + '/' + startD + '/1');
  let daySpace = new Date(year, startD, 0).getDate();
  let body = '';
  let body1 = '';
  for (let i = 1; i <= daySpace; i++) {
    start.setDate(i);
    let endD = Utilities.formatDate(start, 'JST', 'MM/dd');
    let event1 = myCalender.getEventsForDay(start);
    if (event1.length !== 0) {
      for (let j = 0; j <= event1.length - 1; j++) {
        body = body + '\n' + event1[j].getTitle();
      };
      body1 = body1 + endD + body + '\n';
    };
    body = '';
  };
  if(body1 === ''){
    body1 = '何もありません';
  }else{
  body1 = body1 + '\n確認してください';
  };
  return body1;
};
```
# 開発してみて
ひとつのプログラムを組むのに色々なメソッドがあり、分からない事は調べながらしました
かなり勉強になりました
ひとつひとつのメソッドはわかっても組み合わせる事でひとつのプログラムになるので,とりあえずは最後まで作ってみるのが大事だと感じました
全角文字を半角に変換するところとカレンダー登録する際のDateオブジェクトの使い方が苦戦しました

# 参考にした記事
https://qiita.com/dekamintv/items/a4cb9a195f80ef4fbdfa
かなり参考にしました
ありがとうございます