GASを使ってGoogleカレンダーにある特定のイベントをlinebotのflexメッセージで表示してみた

#本記事の内容
作成したlinebotにユーザーが特定のメッセージを送ると自分のGoogleカレンダーから一週間以内の特定のイベントだけ抽出してflexメッセージで表示するというプログラムを作りました。
(※コードを少しいじれば、linebotを登録したタイミングで自動的にイベントの日程を通知することもできます)
このことにより、linebotに登録した人に手動で日程を教える必要がなく、日程のお知らせを自動化できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/713434/8997a011-c026-7b0e-5fbf-48988986fb7d.png)

↑の画像はユーザーが「日程」とメッセージを送ると、連携したGoogleカレンダーに登録してある**一週間以内**の「説明会」の日程を表示しています。

#動作環境
* Windows10 Home
* GAS V8エンジン
* linebot
* flexメッセージ

#コード内容(GAS V8エンジン)

```gas.js
// googleカレンダーのIDを取得
const cal = CalendarApp.getCalendarById('連携したいGoogleアカウントのメールアドレス(Gmail)');

//チャネルアクセストークンを設定する
const channel_access_token = 'ここにlinebotのチャネルアクセストークンを入れる';

//現在時刻から7日後の同時刻までの間に存在する予定の中で追加条件に一致する予定をすべて取得してjsonに追加しそれを返す
function getEvents() {
  // json形式のオブジェクト
  const json = {
    "type": "flex",
    "altText": "this is a flex message",
    "contents": {
      "type": "bubble",
      "body": {
        "type": "box",
        "layout": "vertical"
      }
    }
  }
  const startTime = new Date();
  const endTime = new Date(Date.parse(startTime) + (7 * 60 * 60 * 24 * 1000));
  const options = {
    search: "Googleカレンダーから抽出したいイベントの名前"
   }
  const events = cal.getEvents(startTime, endTime, options);
  const contents = [];
  
  for (let i in events) {
    const date = Utilities.formatDate(events[i].getStartTime(), "JST", "MM月dd日"); /*それぞれのイベントの日付を○○月××日に変更*/
    const title = events[i].getTitle(); /*イベントのタイトルを取得*/
    
// jsonにcontentsを追加
    const contentsItem = {
      "type": "text",
      "text": date + title
    }
    
    contents.push(contentsItem);
   
    json.contents.body.contents = contents;
  }
  
  return json;
}

// post関数
function doPost(e) {
 const events = JSON.parse(e.postData.contents).events;
 const textMessage = getEvents();
 
 events.forEach(function(event) {
   const replyToken= event.replyToken;
   if (typeof replyToken === 'undefined') {
     return; // エラー処理
   }
   if(event.message.text === 'トリガーとなるlinebotに対してユーザーが送るメッセージ') { 
     // ユーザーからbotに特定のメッセージが送られた場合に起きる処理
     const ExplanationMessage = textMessage;
      const ExplanationMessageData = {
        "replyToken" : event.replyToken,
        "messages" : [ExplanationMessage]
      }
      const Eoptions = {
        "method" : "post",
        "headers" : {
          "Content-Type" : "application/json",
          "Authorization" : "Bearer " + channel_access_token
        },
        "payload" : JSON.stringify(ExplanationMessageData)
      };
      UrlFetchApp.fetch("https://api.line.me/v2/bot/message/reply", Eoptions);
   }
 })
}
```
#コードの内容の説明
gasは現在(2020年10月13日時点)V8エンジンが実装されており、jsに近い書き方ができるので、構文はほぼJavaScriptです。
まず、`CalendarApp.getCalendarById('連携したいGoogleアカウントのメールアドレス(Gmail)')`で抽出するGoogleのIDを取得します。
そして、`channel_access_token`にlinebot作成時に得られる(無い場合は別途発行する必要があります)**チャネルアクセストークン**を設定します。

##getEvents関数
この関数では、flexメッセージの情報となる`json`を設定し、ユーザーが特定のメッセージを送った時点から一週間以内にGoogleカレンダーに登録されている特定のイベントを抽出しています。
そのあとで`json`に抽出したイベントの情報を順次追加していき、最後に`json`を`return`で返します。

##doPost関数
この関数では、ユーザーが起こしたアクションを取得し、その中で行われたアクション内容(ユーザーがlinebotをフォローしたり、メッセージを送ったりなど)で条件分岐して処理を行います。
この関数の中で、前述した`getEvent`関数で返した`json`を使ってflexメッセージをユーザーに送信します。

#コードを書いた後に行うこと
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/713434/07b3aa92-75b4-7896-5a52-9c4a4c20951b.png)
コードをgas上で書いたら、「公開」の中の「ウェブアプリケーションとして導入」をクリックし発行されたwebアプリのURLをコピーします。
そして、「アプリへのアクセス権」を「全員（匿名含む）[anyone even anonymous]」に設定します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/713434/38a34c65-4ff7-c1b4-a677-eacfcea4d0b6.png)


その後、linebotの管理画面でwebhookに先ほどコピーしたwebアプリのURLを貼り付けます。
(※Use webhookにチェックを入れてください)

#感想
GASはJavaScriptベースなのでJavaScriptが書ける人は自然に書けると思います。
また、コードを書いてから実装までが簡単なのであまり大きい情報量を使うのでなければGASで十分だと思います。
あと、**めっちゃ楽しかった！自分が書いたコードがちゃんと動いてflexメッセージが表示された時の感動やばい！**
本記事を読んでいただきありがとうございました！