GASでGoogle Calendarの削除イベントを検知してLINE groupに通知するbotを作った

## 作った理由


<img width="414" alt="IMG_52A1BD61E625-1.jpeg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202653/bdfcd397-700f-a969-0137-b16b6f5c1756.jpeg">

僕は大学院で実験系の研究室に所属しています。
大学内の複数の研究室で共同で利用している実験装置があり、半年前までは深夜でも使うことができたのですが、安全管理が厳しくなって8:00-20:00までしか使えなくなってしまいました。
そのため、Google Calendarで管理しているその装置の予約がいつも埋まっていて1週間に2回くらいしか使えないので、みんなの実験が全然進まないという状態でした。

<img width="414" alt="IMG_F52576ADA638-1.jpeg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202653/983d354d-a3eb-2bda-013c-09c09ba836d4.jpeg">

こんな感じで1週間のほとんどの時間が埋まっているので、全然実験が進まない。。。

これを少しでも解決するために「Google Calendarで装置の予約が削除されたら研究室のグループLINEに通知するLINE Bot」をGASとLINE Botで作成しました。

## 要件

<img width="896" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202653/21001227-0347-dd7d-7813-fde952982e83.png">


- Google Calendarの実験装置の予約が削除されたらグループLINEに通知する。
- 予定変更イベントを検知してたら通知の嵐になりそうなので、削除イベントのみ検知する
- 無料で使えて管理も楽なGASで稼働させる。
- 卒業するときに引き継ぎしやすいように、研究室のGoogleアカウントでGASを使う
- 研究室のメーリスに流すより、グループLINEの方が簡単に見れるのでLINE Botを使う
- 通知内容は、「カレンダーのタイトル」、「カレンダーの開始時間と終了時間」

## 完成コード

```javascript
var scriptProperties = PropertiesService.getScriptProperties();
var nextSyncTokenKey = 'NEXT_SYNC_TOKEN';

function calendarUpdatedSample(e) {
  var calendarId = e.calendarId;

  // 予定取得時にsyncTokenを指定して差分イベントを取得
  var optionalArgs = {
    'syncToken': getNextSyncToken(calendarId),
    'showDeleted': true
  };
  var events = Calendar.Events.list(calendarId, optionalArgs);  
  // 差分イベントを処理
  for (var i = 0; i < events.items.length; i++) {
    var event = events.items[i];
    if (event.status === 'cancelled') {
      title = event.summary

      start = new Date(event.start.dateTime)
      start = start.toLocaleDateString() + ' ' + start.toLocaleTimeString();
      end = new Date(event.end.dateTime)
      end = end.toLocaleDateString() + ' ' + end.toLocaleTimeString();
      time = start.replace('JST', '') + '\n~\n' + end.replace('JST', '')
      
      message = '削除報告\n\n【タイトル】\n' + title + '\n\n【日時】\n' + time 
      sendLineNotification(message, scriptProperties.getProperty('LINE_GROUP_ID'));
    }
  }

  // 今回処理したイベントを対象外とするためsyncTokenを更新
  saveNextSyncToken(events.nextSyncToken);
}

function getNextSyncToken(calendarId) {
  // ScriptPropetiesから取得
  var nextSyncToken = scriptProperties.getProperty(nextSyncTokenKey);
  if (nextSyncToken) {
    return nextSyncToken
  }

  // ScriptPropetiesにない場合は、カレンダーから取得
  // 最後の予定を取らないといけないみたいなのでtimeMinを指定
  var events = Calendar.Events.list(calendarId, {'timeMin': (new Date()).toISOString()});
  nextSyncToken = events.nextSyncToken;
  return nextSyncToken;
}

function saveNextSyncToken(nextSyncToken) {
  scriptProperties.setProperty(nextSyncTokenKey, nextSyncToken);
}

function sendLineNotification(message, toId) {
  var url = 'https://api.line.me/v2/bot/message/push';
  var LINE_ACCESS_TOKEN = ScriptProperties.getProperty('LINE_ACCESS_TOKEN');

  UrlFetchApp.fetch(url, {
    'headers': {
      'Content-Type': 'application/json',
      'Authorization': 'Bearer ' + LINE_ACCESS_TOKEN,
    },
    'method': 'post',
    'payload': JSON.stringify({
      'to': toId,
      'messages': [{
        'type': 'text',
        'text': message,
        'notificationDisabled': false
      }],
    }),
    }
  );
}
```

## GASの使い方

GASの基本的な使い方はいろんな記事がググれば出てくるのでそちらを参考にしていただくとして。
今回作ったbotで重要なのはGoogle Calendarの削除イベントを検知するという機能です。

[GASにGoogleカレンダーのイベント変更検知機能が実装されたので試してみた](https://qiita.com/howdy39/items/b92c9ba0b050151a889b)

こちらの記事に詳細に纏まっていたので参考にしました。
今回は変更イベントは拾わずに、削除イベントのみ検知したかったので、その部分だけ書き換えました。
該当コードはここです。

```javascript
if (event.status === 'cancelled') {
```

```javascript

  var optionalArgs = {
    'syncToken': getNextSyncToken(calendarId),
    'showDeleted': true
  };
```

こうすることで削除イベントのみを検知して、大量の通知がグループラインに投下されないようにしました。
またoptionに`showDeleted: true`を入れないと削除されたイベントがレスポンスに含まれなくなります。



## LINEbotとの連携

LINE botとの連携に関してもかなり記事があります。
グループにメッセージを投稿するのにグループIDを取得する必要がありますが、これは個人アカウントにメッセージを投稿するのとほとんど変わりません。

[LINE Messaging APIでgroupIdを取得してPush APIでグループにメッセージを送る](https://qiita.com/kenichi_odo/items/18badf7c069334d9c3a2)


## 実際に使ってもらってどうだったか

<img width="414" alt="IMG_F64C606A9D66-1.jpeg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202653/af2fc3c7-5a47-a678-cdde-1af3330c334a.jpeg">

- 他の研究室の予約が消えたときに5分以内に開いた予約を取れるようになった
- 同じ研究室内でも予約を消したときにいちいち、報告しなくてよくなった

個人開発で人に使ってもらえるレベルのアプリを作ろうとすると、フロント、サーバーとかいろいろ用意する必要が出てきて大変です。
GASとLINE botやslackなどを組み合わせると、手軽に役に立つアプリが作れるので、息抜きに実装してみてください。

[Slackに翻訳botを足す](https://qiita.com/hotpepsi/items/3862618b38b463d37b53)
[鍵管理システムを作ったら褒められた話](https://qiita.com/ingk_124/items/228b44bbcb926b50174e)
[Hangout Chatで空調アンケート集計Botを作ったら色々学べた話](https://qiita.com/kehonda/items/14c9345be48b99459a14)