LINEでリマインダー的なものを作った話

#概要
GoogleカレンダーのスケジュールをLINEのグループで通知してくれる機能の作成を行いました。

#背景
私の家では、LINEを使って「明日飲み会で帰るの遅くなる」のような共有事項を共有しています。
しかし、側近の予定であれば良いのですが、1ヶ月後とかの予定だと当日になって忘れてしまうことがあり、無駄にご飯を作ってしまうなどのミスがありました。
そこで、slackでいうところの　/remind me 的なものをLINEで出来たら便利だなーと思い作ってみました。

# 共有事項のリマインド
LINEでリマインド的なものを実装するに当たってLINEのAPIを使いました。
LINEのAPIでアプリを実装するには大きく分けて２つのAPIがあります。

## LINE Messaging API
[LINE Messageing API](https://developers.line.me/ja/services/messaging-api/)　はBOTを作るためのAPIになります。
こちらも開発者向けであれば友達追加50人まで無料で使えます。
本来ならこっちを使うのが理想的ですが、私が調査をした段階で無料という情報を得ることができなかったため今回はLINE Notifyで実装して、
改良版として今後こちらを使ったものを作成したいと思います。

## LINE Notify
[LINE Notify](https://notify-bot.line.me/ja/)はWEBサービスからの通知を行なうAPIです。
通常はIFTTTとかGitHubとかと合わせて使うものになります。
しかし、keyを発行すればapiを簡単に叩くことができます。
メッセージの出力のみになりますが、個人向けに使う分には無料でシンプルなので入力方法は別途で用意してこちらを使うことにしました。

# 共有事項の入力
予定の入力にはGoogleカレンダーを用いました。
「ぇ、じゃぁGoogleカレンダーを見れば良いじゃん？」それは気にしたらダメです。

## Google Apps Script
Google Apps Script とは、JavaScriptをベースにしている、Googleオリジナルの言語になります。
基本的にjavaScriptの機能は使えて、Google独自の機能を簡単に使えるようにしたものです。
Googleカレンダーをプログラムから触るにはGoogleカレンダーAPIを叩く必要があります。
通常であればどこかにサーバーを立ててcronで動くスクリプトを作成してAPIを呼び出す必要があるのですが、
[Google Apps Script](https://developers.google.com/apps-script/)はGoogleアカウントがあれば簡単にバッチ処理を実現することが可能です。
しかも、GoogleのAPIであれば基本的にouth認証などのめんどくさい設定をしなくても使うことが出来てしまう優れものです。
長いので以降gasと記載します。


# 完成イメージ
以下のようなイメージで実装をしました。
![イメージ図.png](https://qiita-image-store.s3.amazonaws.com/0/206268/a8ebe44f-229d-880e-fdcb-8661938dc5dd.png)

# 実装
## 環境設定
初めに以下の環境設定を行っていきます。

 * LINE Notifyの設定
 * gasの設定

### LINE Notify
 [LINE Notiry](https://notify-bot.line.me/ja/)のページでログインしてアクセストークンを発行します。
 ![image.png](https://qiita-image-store.s3.amazonaws.com/0/206268/b201d31d-bfbc-239a-b7b9-b893a3a2404d.png)
トークンを発行するときは通知を行いたいグループで作成してください。

### Google Apps Script
Google Drive のマイページで右クリックしてgasを作成します。
※ない場合は新規で追加してください。

<br><br>
以上で環境設定は終了です。
あとは作成したgasにプログラムを記載していくだけです。

## LINE Notifyの送信処理
LINEでメッセージを送信するにはHTTPにkeyとmessageを貼ってあげるだけで簡単にできます。
実際の送信処理は、gasのライブラリの`UrlFetChApp.fetch`を使って以下のように書いてあげればメッセージを送信することが出来ます。

```js:LINEにメッセージを送信
 var token = LINETOKEN;
 var options =
 {
 "method"  : "post",
 "payload" : "message=" + sendText,
 "headers" : {"Authorization" : "Bearer "+ token}
  };
 UrlFetchApp.fetch("https://notify-api.line.me/api/notify", options);
```

これで、LINEにGoogle Apps Scriptからメッセージを送信することが可能になりました。

## 予定を取得してきて定時に起動する処理
あとは、送信するメッセージ（翌日の予定）をカレンダーから取得してくれば完了です。
実装する処理としては以下の3つになります。

* 23時に起動するようにセットする処理
* カレンダーから予定を取得する処理
* 出力メッセージを整形する処理

### 23時に起動するようにセットする処理
gasにはトリガーをセットする機能がありますが、
これがピッタシに起動してくれないので23時ちょうどに起動したい場合は自前で設定が必要です。
なので23時に起動するように設定する関数を1時間前に呼び出すような処理を追加します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/206268/4beee7d3-a491-cf74-4433-d0a59d769def.png)

```js:トリガー設定
// その日の23時00分にトリガーを設定
function setTrigger() {
  var triggerDay = new Date();
  triggerDay.setHours(23);
  triggerDay.setMinutes(00);
  ScriptApp.newTrigger("main").timeBased().at(triggerDay).create();
}

// その日のトリガーを削除する関数
function deleteTrigger() {
  var triggers = ScriptApp.getProjectTriggers();
  for(var i=0; i < triggers.length; i++) {
    if (triggers[i].getHandlerFunction() == "main") {
      ScriptApp.deleteTrigger(triggers[i]);
    }
  }
}
```

### カレンダーから予定を取得する処理
カレンダーから予定を取得するには`CalendarApp.getCalendarById(CALENDARID)`にカレンダーIDをセットすることでカレンダーの情報を取得することが出来ます。
カレンダーIDは[Googleカレンダー](https://calendar.google.com/calendar/render?hl=ja#main_7)のカレンダー設定で確認することが出来ます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/206268/7db51565-1d3d-038d-bf4e-062e5a9a057b.png)

![image.png](https://qiita-image-store.s3.amazonaws.com/0/206268/8033d0a7-f531-863c-16fa-7ec64d81fdd1.png)

カレンダーIDをセットしたオブジェクトにdata型で日付をセットすれば予定を取得することができます。

`var schedules = calendars.getEventsForDay(date.toDate());`
この`schedules`にリストで予定が入るのであとはfor文とかで最初から最後まで出力してあげれば良いです！
予定の詳細情報は[ドキュメント](https://developers.google.com/apps-script/reference/calendar/calendar-event)にあるメソッドでいい感じに取得できます。

### 出力メッセージを整形する処理
出力メッセージの連結は基本的に文字列連結で行っていますが、Data型のフォーマットだけ外部ライブラリを用いました。
javascriptってJavaとかみたいにData型フォーマットする機能がdefaultでないんですね…
gasで外部ライブラリを追加するには以下のリソースにあるライブラリで追加したいライブラリのIDを追加すれば追加が出来ます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/206268/1325b6a7-d5f7-c115-27b5-18152ddb37c1.png)

出力メッセージを作成する処理は以下のようになりました。

```js:メッセージ出力
//Momentライブラリ曜日を日本語にセット
Moment.moment.lang('ja', {
    weekdays: ["日曜日","月曜日","火曜日","水曜日","木曜日","金曜日","土曜日"],
    weekdaysShort: ["日","月","火","水","木","金","土"],
});

	//カレンダーの情報を取得する
	var calendars = CalendarApp.getCalendarById(CALENDARID);
  
    // Date型のオブジェクトの生成
  　var date = new Moment.moment();
　　// dateを翌日にセットする
   date.add(1, "days");
　　//date.setDate(date.getDate() + 1);
  
	//翌日の予定を取得する
	var schedules = calendars.getEventsForDay(date.toDate());

	/*
	* 予定を出力する
	*/ 
	var sendText = new String();
	sendText += "\n####### " + date.format("M月D日(ddd)") + " の予定 #######";
	//もし予定がない場合は
	if(schedules.length == 0) {
		sendText += "\n何も予定がありません";
	} else if(schedules.length > 0 ) {
      // 予定を繰り返し出力する
      for(var i = 0; i < schedules.length; i++) {
        sendText += "\n";
        var startTime = Moment.moment(schedules[i].getStartTime());
        var endTime = Moment.moment(schedules[i].getEndTime())
        sendText += startTime.format("HH:mm") + "〜" + endTime.format("HH:mm")
        sendText += " : "
        sendText += schedules[i].getTitle();
      }
    } 
```

最終的にはこんな感じで出力されます。
![lineスクショ.png](https://qiita-image-store.s3.amazonaws.com/0/206268/b39bf690-34be-8cab-b92b-5109b444a214.png)




# まとめ
Googleカレンダーの予定をLINEに通知する機能を実装しました。
作ってみてですが、

 * gasは簡単にスクリプトを作成することができるので業務で発生するような簡単なバッチなんかを作成するのにはありなのかなと感じました。
 * LINE NotiryはLINEに通知することが出来ますが、LINEは日常なコミュニケーションツールになるのでLINEで実装しても自己満足で終わってしまうかなという印象を受けました。
<br>※実際妹から「この通知うざいんだけど」というクレームが入りましたｗ
 
今後は入力の方もLINE上からできるようにしていければと思います。

さいごになりますが、長くなってしまいましたが、ご覧いただきましてありがとうございます。
ツッコミどころなどありましたら、ご指摘いただけたら幸いです。



#参考文献
[[超簡単]LINE notify を使ってみる](https://qiita.com/takeshi_ok_desu/items/576a8226ba6584864d95)
[Calendar Service  |  Apps Script  |  Google Developers](https://developers.google.com/apps-script/reference/calendar/)
[Google Apps Scriptの日毎のトリガーで時間をもっと細かく設定する](https://qiita.com/sumi-engraphia/items/465dd027e17f44da4d6a)
[日付＆時刻の便利ライブラリ「Moment.js」をGoogle Apps Scriptで使う方法](https://tonari-it.com/gas-moment-js-moment/)