【GAS】Googleカレンダから今日のイベントを拾ってWebex Teamsに通知する

#概要
Googleカレンダに登録されたイベントを毎朝`Webex Teams`に通知してくれるBotを作りました。
Googleカレンダ(に限らずGoogleのサービス全般)を扱うため、`Google Apps Script(以下GAS)`を使ってみることにしました。

#要素技術  

- Googleカレンダから予定を取得する  
[CalendarApp](https://developers.google.com/apps-script/reference/calendar/calendar-app)を使用する

```javascript
// IDを指定してカレンダを取得 
var calendar = CalendarApp.getCalendarById("【カレンダID】");

// カレンダからイベントを取得する期間
const startDate = new Date(2019,0,1); // 2019/01/01
const endDate = new Date(2019,11,31); // 2019/12/31
// イベントを取得
var events = calendar.getEvents(startDate, endDate);
``` 

- 外部APIを叩く  
[UrlFetchApp](https://developers.google.com/apps-script/reference/url-fetch/url-fetch-app)を使用する

```javascript
// リクエスト実行
var response = UrlFetchApp.fetch('【リクエスト先】');
```

#成果物  
アクセストークン等々は`プロジェクトプロパティ`に格納してあります。細かい仕様は[PropertiesService](https://developers.google.com/apps-script/reference/properties/properties-service)を参照

下記の`main`を毎朝実行するようスケジューリングしています。

```javascript:taskpost.gs
// Webex BOTのアクセストークン
var API_TOKEN =  PropertiesService.getScriptProperties().getProperty('API_TOKEN');
// Webex API
var WEBEX_API = 'https://api.ciscospark.com/v1/';
// 通知先のルームID
var ROOM_ID = PropertiesService.getScriptProperties().getProperty('ROOM_ID');
// messagesエンドポイント
var MESSAGES_ENDPOINT = 'messages'
// 予定を取得するGoogle Calendar ID
var CALENDAR_ID = PropertiesService.getScriptProperties().getProperty('CALENDAR_ID');

/**
 * main
 */
function main() {
  
  // 今日のタスク一覧を取得
  var taskList = getTodayTaskList();
  
  // 送信用の文字列を作成
  var sendText = makeSendText(taskList);
  
  // 送信処理を開始
  sendMsg(sendText);
}

/**
 * タスク一覧からWebexに送信する文言を作成する
 */
function makeSendText(taskList) {
  var sendText = "【自動お知らせBOT】\r\n";
  sendText += "今日の予定をお知らせします。\r\n";
  if(taskList.length > 0){
    sendText += 'スケジューリングされたタスクは以下の通りです。\r\n';
    sendText += '\r\n';
    taskList.forEach(function(t){
      sendText += t + '\r\n';
    });
  }
  else {
    sendText += '今日はスケジューリングされたタスクがありません。';
  }
  
  return sendText;
}

/**
 * Googleカレンダーから今日の予定を取得する
 */
function getTodayTaskList() {
  // 取得範囲を設定
  var startDate = new Date();
  var endDate = new Date();
  // 今日の00:00:00～明日の00:00:00にする
  startDate = new Date(startDate.getFullYear(), startDate.getMonth(), startDate.getDate());
  endDate = new Date(endDate.getFullYear(), endDate.getMonth(), endDate.getDate() + 1);
  
  var calendar = CalendarApp.getCalendarById(CALENDAR_ID);
  var events = calendar.getEvents(startDate, endDate);
  
  var taskList = [];
  
  for(var i = 0; i < events.length; i++){
    var title = events[i].getTitle();
    var startTime = new Date(events[i].getStartTime());     
    var endTime = new Date(events[i].getEndTime());
    var duration = (endTime.getTime() - startTime.getTime()) / (1000*60*60);
    var timeStr = "[" + Utilities.formatDate(startTime, 'Asia/Tokyo', 'HH:mm') + " ～ " + Utilities.formatDate(endTime, 'Asia/Tokyo', 'HH:mm') + "]";
    if(duration == 24){
      timeStr = '[終日]';
    }
    taskList.push(timeStr + " " + title);
  }
  
  return taskList;
}

/**
 * 投稿処理
 */
function sendMsg(text) {
  
  // 投稿内容を作成
  var data = {
    // 投稿先
    'roomId': ROOM_ID,
    // 本文
    'text': text
  };
  
  // オプション
  var options = {
    'method': 'post',
    'contentType': 'application/json',
    'headers': { 
      'Authorization': 'Bearer ' + API_TOKEN
    },
    'payload': JSON.stringify(data)
  }
  
  // 投稿処理を実行
  var response = UrlFetchApp.fetch(WEBEX_API + MESSAGES_ENDPOINT, options);
}

```

# 通知結果
![webex.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/435429/600bd414-42c0-228a-a477-23dca6b88ea5.png)

# 感想  
GASを触るのが初めてということもあり最初は戸惑いましたが、ほぼ`Javascript`の感覚でいけました。
今回は大したAPIアクセスもしないため問題に挙がりませんでしたが、`GASは実行時間を6分に抑えないといけない`縛りがあるようです。今後拡張する際は気を付けたいところです。
通知先を`Slack`等に変えたい場合も比較的簡単にできそうなのでよかったです(小並感)