Google Chatにミーティング予定を通知

# この記事の読者
* Google Chatに通知を送りたい方
* Calendar API を使いたい/使える方

# きっかけ
自分の運営している団体でミーティングを忘れる人が続出したので、それを防止するためにBotを作成した。

# 前提条件
* Google Apps Scriptで開発
* 外部ライブラリを使うのは問題ない

# 結論
Google CalendarのMeetのリンク取得時のみCalendarAPIを使う必要がある。
したがって、以下のプログラム実行前にGoogle Cloudのプロジェクトと紐付けが必要。
また、6:00~7:00の間にトリガーを設定する前提。

# 詳細
~~~js:main.gs
function sendNotification() {
    //Set time and API etc.
    var now = new Date();
    var after = new Date(Date.parse(now) + (60 * 60 * 18 * 1000));
    let calendarID = "c_6mq00dcsmj4gheaan2trmjqt28@group.calendar.google.com";
    let calendar = CalendarApp.getCalendarById(calendarID);
    let events = calendar.getEvents(now, after);


    //If there are no events today, the program is stopped.
    if (events.length == 0) {
        console.log('There are not events. This program is finished.')
        return;

    };

    for (let i = 0; i <= 3; i++) {

        let eventId = events[0].getId().split("@")[0];
        let text = new Date();

        //Get event info
        let plan_date = Utilities.formatDate(new Date(), 'JST', 'MM/dd');
        let plan_title = events[0].getTitle();
        let plan_start_time = Utilities.formatDate(events[0].getStartTime(), 'JST', 'HH:mm')
        let plan_end_time = Utilities.formatDate(events[0].getEndTime(), 'JST', 'HH:mm');
        let plan_meet_link = Calendar.Events.get(calendarID, eventId).hangoutLink;
        let plan_location = events[0].getLocation();

        const plan_time = plan_start_time + '-' + plan_end_time;


        if (plan_location == "") {
            let plan_type = "ONLINE"
            var message =
            {
                "cardsV2": [
                    {
                        "cardId": "unique-card-id",
                        "card": {
                            "header": {
                                "title": '<b>' + plan_title + '</b>',
                                "subtitle": "<p style='color:#808080'>You have a meeting today. Do not forget to join!</p>"
                            },
                            "sections": [
                                {
                                    "header": "Meeting Info",
                                    "collapsible": true,
                                    "uncollapsibleWidgetsCount": 1,
                                    "widgets": [
                                        {
                                            "decoratedText": {
                                                "startIcon": {
                                                    "knownIcon": "DESCRIPTION",
                                                },
                                                "text": plan_type,
                                            }
                                        },
                                        {
                                            "decoratedText": {
                                                "startIcon": {
                                                    "knownIcon": "CLOCK",
                                                },
                                                "text": plan_time,
                                            },
                                        },
                                        {
                                            "decoratedText": {
                                                "startIcon": {
                                                    "knownIcon": "VIDEO_CAMERA",
                                                },
                                                "text": "<a href='" + plan_meet_link + "'>" + plan_meet_link + "</a>",
                                            }
                                        }
                                    ],
                                },
                            ],
                        },
                    }
                ],
            }
        } else {
            let plan_type = "IN PERSON"
            var message =
            {
                "cardsV2": [
                    {
                        "cardId": "unique-card-id",
                        "card": {
                            "header": {
                                "title": '<b>' + plan_title + '</b>',
                                "subtitle": "<p style='color:#808080'>You have a meeting today. Do not forget to join!</p>"
                            },
                            "sections": [
                                {
                                    "header": "Meeting Info",
                                    "collapsible": true,
                                    "uncollapsibleWidgetsCount": 1,
                                    "widgets": [
                                        {
                                            "decoratedText": {
                                                "startIcon": {
                                                    "knownIcon": "DESCRIPTION",
                                                },
                                                "text": plan_type,
                                            }
                                        },
                                        {
                                            "decoratedText": {
                                                "startIcon": {
                                                    "knownIcon": "CLOCK",
                                                },
                                                "text": plan_time,
                                            },
                                        },
                                        {
                                            "decoratedText": {
                                                "startIcon": {
                                                    "knownIcon": "MAP_PIN",
                                                },
                                                "text": plan_location,
                                            }
                                        }
                                    ],
                                },
                            ],
                        },
                    }
                ],
            }
        }


        //Configure Google Calendar & Google Chat ;
        const chat_url = "https://chat.googleapis.com/v1/spaces/AAAAPL961W0/messages?key=AIzaSyDdI0hCZtE6vySjMm-WEfRq3CPzqKqqsHI&token=2XkF37dxuIXVUGkAThvb-bvQPVwdEBiu9RRH1geeTF8%3D";

        let params = {
            'method': 'POST',
            'headers': {
                'Content-Type': 'application/json; charset=UTF-8'
            },
            'payload': JSON.stringify(message)
        };
      UrlFetchApp.fetch(chat_url, params);
    }
}
~~~

# 利点
* GASはGoogle系サービスとの連携が容易

# 改善すべきポイント
* 通知が何度も行くのは面倒なので、一つのCardsで収まるようにしたい。
* Google Cloudの設定をしなければいけないのは少し面倒。

# 筆者の戯言
みんながミーティングに忘れず出席してくれよ！