カレンダーの予定をラインに送ってみた

# 初めに
**LINEにカレンダーの予定をおくれないものか...**

ある記事を読んでこういう風に考えるようになりました。その記事とは

>- [ゴミ出しをGASとLINE Botで定期通知し母親に親孝行する](https://qiita.com/kanta_yamaoka/items/dd830cf23ff59353824d)

です。読んだときに「そんなことできるんだー、似たようなもの作ってみたいな」と感じ、じゃあ作るかという感じでLINEとカレンダーの組み合わせを思いつきました。
また、今絶賛就活中ということもあり、就活の予定を予定を忘れないようにという面も込めて、通知のツールを作りたかったのです。<font color="gray";>（Google Calendarの通知機能もありますが、事前に予定を知っているだけで気持ちを切り替えやすいですよね。）</font>
**「LINE＋GoogleCalendar」**と調べてもらえば分かるのですが、めちゃくちゃ記事があります。
当記事は、**「何番煎じやねん」**というレベルです。とは言え、せっかく作ったので忘れないように記事に起こしていこうと思います。

# 実践
当初は上記で紹介した記事のようにLINE botとGASの組み合わせにしようかなと思ったのですが、LINEにはLINENotifyという便利な機能があったので今回はそれを使っていきます。
ちなみに、作成する上で参考にした記事を以下にまとめています。

>- [【GAS】Googleカレンダーの予定をLINEで受け取る](https://qiita.com/ikei/items/8c837444dcab6c0e4629)

上記の方が書いた記事のアイデアをかなり使わせていただいています。当記事では必要な要素だけのシンプルなスタイルのプログラムを組んでいるので、シンプルでいいのならば、作る際には当記事を参考にしてみてください。

## LINENotify
[こちら](https://notify-bot.line.me/ja/)からLINE Notifyのページにアクセスして、ログインをクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/654472/497daf98-222b-ce9b-be41-7f14b04159a9.png)
その後、自身のLINEに登録してある**「メールアドレス・パスワード」**を入力します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/654472/07635a33-3b22-a8c0-1296-8d4600698aac.png)
最後に、右上の名前をクリック　→　マイページをクリック　→　トークンを発行するをクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/654472/cce01d65-4e24-3b9e-86e7-c1896699bab8.png)
トークン名は適当につけて「1:1でLINE Notifyから通知を受け取る」を選択し、トークンを発行しましょう。
これでLINENotifyの連携の準備は完了です。
このトークンは、GASと連携をする際に使用しますので、コピーをするかタブを開いたままにするとスムーズに作業できます。

## GoogleAppsScript（GAS）
GASの準備を行っていきます。知っている人からしたら「またか...」と感じると思うので先に進んじゃってください。
「新規」　→　「その他」　→　「GoogleAppsScript」を選択します。
![2021-01-10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/654472/6bc2fc55-0163-c2f9-631f-6b325dfc60e7.png)
GASの用意はこれで完成です。

### GAS操作編（豆粒程度）
GASで関数を動かす際には、「関数を選択」のところで実行したい関数を選択し、**▶**で実行します。これさえ知っていれば今回は操作で困ることはないはずです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/654472/5286c860-d900-5cf8-6d8c-6a4f9960636e.png)

# GASとLINENotifyをコネクト
ここで全部のセットアップが終わったので、GASとLINENotifyを連携していきます。ちなみにこの連携方法も、上記の方がしてた方法のほうがわかりやすくミスをしにくそうなので、当記事でもその方法で行います。
>- [【GAS】Googleカレンダーの予定をLINEで受け取る](https://qiita.com/ikei/items/8c837444dcab6c0e4629)

「ファイル」から「プロジェクトのプロパティ」を選択し、
![2021-01-11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/654472/6d524c68-1459-af9d-9470-22566c1c0199.png)
次に「スクリプトのプロパティ」を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/654472/0c3910be-fd17-379e-a1fb-2c665c3ed1dd.png)
最後に「＋行を追加」をクリックして、TOKEN名とLINENotifyで発行したTOKENを入力して保存します。
ここで設定したTOKEN名はコード内で使用します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/654472/9ee30dfc-15d5-b5b5-5b93-e959cf281803.png)
ここまでで準備は完了です。
それではコードの紹介を行っていきます。

## コード
最初にコードをまとめたものを記載しています。
個別に少しだけコードの解説を行います。

### 全体

```main.js
//デフォのアカウントやないとカレンダーの権限を承認することができないみたい
//違うアカウントのカレンダーを使いたければ、そのアカウントで新しく作る必要あり

const CALENDAR_ID = '*******@gmail.com'; //カレンダーID

//メッセージテスト関数
function test(){
  var message = getTodayMessage(CALENDAR_ID,'今日');
  Logger.log('今日\n' + message);
}

//今日の予定を送る
//LINE_TOKENは「ファイル」→「プロジェクトのプロパティ」→「スクリプトのプロパティ」→「行の追加」で追加する
function getSchedule() {
  var accessToken = PropertiesService.getScriptProperties().getProperty('LINE_TOKEN'); //LINEのTOKENを取得
  var message = getTodayMessage(CALENDAR_ID,'今日'); //送信するメッセージの作成
  var options =
   {
     'method'  : 'post'
    ,'payload' : 'message=' + message
    ,'headers' : {'Authorization' : 'Bearer '+ accessToken}
    ,muteHttpExceptions:true
   };
  UrlFetchApp.fetch('https://notify-api.line.me/api/notify',options); //lineのapiと連携する
}

//lineに送るメッセージを作成
function getTodayMessage(calID,str){
  var startDate = new Date(); //今日の日付を取得（時間も同時に取得するため少し遅いかも　→　こんな感じ［Mon Jan 11 16:46:26 GMT+09:00 2021］）
  var content = '';
  //date = new Date(startDate.getYear(),startDate.getMonth(),startDate.getDate()); //年・月・日だけを取得することが可能だが、年がバグることあり
  var head = Utilities.formatDate(startDate,'JST','yyyy-MM-dd') + ' : ' + str + 'の予定\n'; //必要な形に時間を変換
  content = getTodayEvent(calID,startDate);
  if ( noEvent(content) ) {
    content = '予定はありません。';
  }
  return head + content;
}

//カレンダーに記載されているイベントを取得
function getTodayEvent(calID,date){
  var calendar = CalendarApp.getCalendarById(calID); //カレンダーを取得
  var events = calendar.getEventsForDay(date); //カレンダーのイベントを配列型で取得
  var line_event = '';
  var start_end = '';
  
  //予定を取得  
  for (var i in events){
    //予定ごとに改行して見やすくする
    if(!noEvent(line_event)){
      line_event += '\n';
    }
    var title = events[i].getTitle(); //イベント名
    var eventId = events[i].getId(); //イベントID
    var event = calendar.getEventById(eventId); //イベント時間を取得する用
    var start = time(event.getStartTime());// デフォルトの返り値　→　Mon Jan 11 17:00:00 GMT+09:00 2021
    var end = time(event.getEndTime());
    if (start === end){
      start_end = '終日';
    }else{
      start_end = start + '~' + end
    }
    line_event += '・' + start_end + '【' + title + '】' + '-';
  }
  return line_event;
}

//時間の表示を変更
function time(str){
  return Utilities.formatDate(str,'JST','HH:mm');
}

//予定がない時
function noEvent(event) {
  if ( event=='' || event===null || event===undefined ) {
    return true;
  } else {
    return false;
  }
}
```

### 個別解説.１

```.js
function getTdayMessage(calID,str){
  var startDate = new Date(); //今日の日付を取得（時間も同時に取得するため少し遅いかも　→　こんな感じ［Mon Jan 11 16:46:26 GMT+09:00 2021］）
  var content = '';
  //date = new Date(startDate.getYear(),startDate.getMonth(),startDate.getDate()); //年・月・日だけを取得することが可能だが、年がバグることあり
  var head = Utilities.formatDate(startDate,'JST','yyyy-MM-dd') + ' : ' + str + 'の予定\n'; //必要な形に時間を変換
  content = getTodayEvent(calID,startDate);
  if ( noEvent(content) ) {
    content = '予定はありません。';
  }
  return head + content;
}
```

JSの**Date()**では、【Mon Jan 11 16:46:26 GMT+09:00 2021】のように値が返されます。
流石にそのまま使うと見にくいので、**Utilities.formatDate()**でわかりやすいように形を変えています。
### 個別解説.２

```.js
  //予定を取得  
  for (var i in events){
    //予定ごとに改行して見やすくする
    if(!noEvent(line_event)){
      line_event += '\n';
    }
    var title = events[i].getTitle(); //イベント名
    var eventId = events[i].getId(); //イベントID
    var event = calendar.getEventById(eventId); //イベント時間を取得する用
    var start = time(event.getStartTime());//
    var end = time(event.getEndTime());
    if (start === end){
      start_end = '終日';
    }else{
      start_end = start + '~' + end
    }
    line_event += '・' + start_end + '【' + title + '】' + '-';
  }
  return line_event;
}
```

イベントの開始時間と終了時間を取得する際には**for**文で回して取得する必要があります。
また、時間の返り値は【Mon Jan 11 17:00:00 GMT+09:00 2021】となっているので、これも見やすいように変換を行っています。
その変換を以下の**time**関数で行っています。こちらのコードは[@ikei](https://qiita.com/ikei)さんのアイデアを参考にさせていただきました。

```.js
function time(str){
  return Utilities.formatDate(str,'JST','HH:mm');
}
```

### 初めて関数を実行する際に
初めてカレンダーを扱う関数を実行する際には許可が必要になってきます。
自分も初めて出てきたときはびっくりしたのですが以下のサイトに手順が載っています。参考にしてみてください。

>* [【初心者向けGAS】スクリプト実行時の「承認」でびっくりしないために](https://tonari-it.com/gas-script-approval/)


## 時間を設定する
GASには決まった時間に関数を動作させる機能があります。この機能を設定すれば、朝起きる前にLINENotifyに通知を送ることが可能なのです。

まず、「編集」　→　「現在のプロジェクトのトリガー」を選択します。
![2021-01-11 (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/654472/340cc767-7c03-2fb7-4996-5bc659d73e1f.png)
次に、「新しいトリガーを作成」あるいは「トリガーを追加」を選択します。
設定画面で

* 実行する関数を選択<font color="gray">（自分が実行したい関数）</font>
* 時間ベースのトリガーのタイプを選択
* 時刻を選択<font color="gray">（自分の好きな時間）</font>

を以下の写真のように設定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/654472/c0cc87df-a334-274e-1481-bc99162b1a71.png)
保存を押してトリガーの設定は終了です。

## 送られてきた通知
以下の写真が送られてきた通知です。しっかり、朝6～7時の間に送られてきており、予定も把握することができています。
試しに、送信してみたければ、送信用の関数を実行すると確認することができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/654472/8bb9761e-578d-787c-e8c3-0c927fb5e732.png)

# 最後に
今回はLINEでGoogle Calendarの予定を受け取れるものを作ってみました。特に手の混んだ部分はなく、比較的簡単に作れたかなと感じています。作りたいなと感じたものを作れるように、これからも日々研鑽し、技術力を挙げていきたいですね。