日次でLINEBOTが動作するようにした

# 完成物
[初回の投稿](https://qiita.com/LunaChevalier/items/06706546762dfde04b44#%E8%A6%81%E4%BB%B6%E5%AE%9A%E7%BE%A9)の
> 当日にイベントがあったら，朝に通知

が完成しました．
思いの外，サクサク進んで現実的要件は達成してしまいました・・・
スケジュールが無い日は何も動作しません．
スケジュールがある時の動作が↓になります．
<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">とりあえず、朝の通知用の機能は出来ました<br>後は時間になったら動作するか確認ですね <a href="https://t.co/kkAht44wof">pic.twitter.com/kkAht44wof</a></p>&mdash; ルナ・チェバリー (@Luna_Chevalier) <a href="https://twitter.com/Luna_Chevalier/status/955461401069338624?ref_src=twsrc%5Etfw">2018年1月22日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

指定時間になったら，通知を送るメソッドを動かしています(リンクは手動で動かしています)

# 開発環境
* [Ruby](https://www.ruby-lang.org/ja/)(2.4.1)
* [google-api-client](https://github.com/google/google-api-ruby-client)(0.13.6)
* [line-bot-api](https://developers.line.me/ja/)(1.2.0)
* [Sinatra](http://sinatrarb.com/intro-ja.html)(2.0.0)
* [Apache](https://httpd.apache.org/)(2.4.6)
* passenger(5.1.8)

# 主なお話
GASを使って，日次でLINEBOTにPOST通信しました．

# 現在の実装完了機能
* 文字を送信したら，ランダムで何か返事してくれる
* 「スケジュール」と送信したら，今日から1週間のスケジュールを教えてくれる
  * ベースはGoogleカレンダー
  * 当日にイベントがあったら朝に通知してくれる←new!

# 今回の作業
GASからGoogleカレンダーのスケジュールを取得して，そのデータをLINEBOTにPOST通信で通知を送ります．

## GASからGoogleカレンダーのスケジュール取得
まずはGASからGoogleカレンダーのスケジュールを取得します．
[GASのカレンダー部分のリファレンス](https://developers.google.com/apps-script/reference/calendar/calendar)とJavascriptを利用して，できたのがこちら．
ちなみに，送信データの形式はJsonにしました(単に個人的に好きだからです)

```js:remind.gs
var CALENDAR_ID = 'カレンダーID'
var URL = 'POST通信するURL'

function sendMorning() {
  var options =
  {
    'method' : 'post',
    'contentType': 'application/json',
    'payload' : JSON.stringify(getSchedule(CALENDAR_ID))
  }
  Logger.log(options)

  // POST通信
  UrlFetchApp.fetch(URL, options);
}

function getSchedule(calendar_id) {
  // カレンダーのデータを取得
  var myCalendar = CalendarApp.getCalendarById(calendar_id)
  // その日のスケジュールを取得
  var myEvents = myCalendar.getEventsForDay(new Date())
  // スケジュールで欲しい情報だけ持ってくる(今回は開始時間とイベント名)
  myEvents = createJson(myEvents)
  return myEvents
}

function createJson(events) {
  var jsonArray = []
  for (var i = 0; i < events.length; i++) {
    var json = new Object()
    // イベント名
    json['summary'] = events[i].getTitle()
    // 開始時間
    var date = events[i].getStartTime()
    // そのまま時間を取得すると，標準時が協定世界時になるので，9時間加算して日本時間にする
    date.setHours(date.getHours() + 9)
    json['startDateTime'] = date
    jsonArray.push(json)
  }
  return jsonArray
}
```

Jsonを作成する部分は[こちら](https://qiita.com/kingpanda/items/8e60a64dc2454f6ae6b5#-gas%E3%81%A7json%E5%87%BA%E5%8A%9B%E3%81%99%E3%82%8B%E9%96%A2%E6%95%B0%E3%82%92%E6%9B%B8%E3%81%8F)のソースを参考にしました

## POSTされる側のURLの準備
LINEBOTをWebhook以外にルートを設定して無いので，他のURLが存在しません．
なので，通知を受け取る専用のURLを作成しました．
パスの名前はなんでもいいです．

### 諸注意(って言うほどでも無いけど引っかかったところ)
URL設定して，`remind.gs#sendMorning`を動かすと，正常にJsonは受け取れます．
しかし，特に何もしていなかったらASCII-8bitで受け取ります(私はそうなりました・・・)．
上記以外の文字コードでコーディングしていると，文字化けしてしまいます．
私はUTF-8で開発していたので，見事に文字化け，例外出ました・・・
なので，私の場合はGASかRubyのどちらかでUTF-8に文字コードを設定する必要がありました．
今回はRuby側で`force_encoding("utf-8")`を使って文字化けを解消しました．

## データを元にセリフを設定
受け取ったデータは下のようになっているはず・・・
`sample_data.json`はその日に3件あった場合になります

```json:sample_data.json
[
  {
    "summary": "深夜テスト",
    "startDateTime": "2018-01-23T01:00:00.000Z"
  },
  {
    "summary": "テストスケジュール",
    "startDateTime": "2018-01-23T10:00:00.000Z"
  },
  {
    "summary": "深夜テストスケジュール",
    "startDateTime": "2018-01-23T21:30:00.000Z"
  }
]
```

これを元に文字列編集してセリフを作成しました(作成したセリフが最初の動画になります)．

## 日次で動作するように設定
ここまで正しくコーディングしていれば，LINEBOTが話しかけてくれるかなと思います．
ですが，まだ日次で動作するようにはなってないので，その設定をする必要があります．
左上にあるアナログ時計の様なアイコン(画像の赤丸のアイコン)をクリックすると，現在のプロジェクトのトリガーが表示されるので，適宜設定します．
今回は毎朝，6時～7時に通知するように設定しました．

![image.png](https://qiita-image-store.s3.amazonaws.com/0/56006/079c6325-e061-2c82-2916-e0a9fbdfd1f1.png)

ちなみに，上の設定で一度時間になったら通知が来るか確認したら，6:23に来ました．

# 今後の予定
一応，現実的要件は達成しましたが，もうちょっとやりこみできる部分があるかなと・・・
例えば

* 場所が設定されていたら，その地図を出す
* 終日設定されたカレンダーの通知を設定する

とかですね・・・

中間的要件を着手するにしても，今のセリフのテンプレはソースコードに直書きしているので，データベースに管理させたらキャラが簡単に増やしたり，テンプレの管理もしやすくなるので，先にそれをしてから複数キャラ対応したほうがいいかなと思います．