📅

Google Calendar for Team EventのSlack通知が来なくなったので、Makeで代理通知するシナリオを作ってみた

2023/02/01に公開

事の発端

READYFORでは、リリース予定がバッティングすることを防ぐため、Googleカレンダーに「プロダクト開発カレンダー」という共有カレンダーを作り、リリース予定が決まったらプロダクト開発カレンダーに予定を登録する、という運用をしています。
プロダクト開発カレンダーの予定は、Slack 向け Google Calendar for Team Eventsを利用してSlackへ通知するようになっているのですが、2023年1月の2週目あたりから、急にSlackへ通知されなくなってしまいました。
過去にも度々通知されなくなることはあったものの、連携しなおしたり設定を更新することで対処できていたのですが、今回はどうにもうまくいきません。
2023年の3月には非推奨になるアプリでもあるので、もう望みは薄いだろうな…ということで、Make(integromat)を利用して、Google Calendar for Team Eventsの代わりにリリース予定を通知する仕組みを作ってみました。

Makeを採用するまで

条件

代替手段を探すにあたり、MustとWantの条件を定めます。
今までできていたことはMust、「多分今まではできていたんだろうなぁ」というところはWantにします。

Must

  • 複数人で管理ができること
  • 共有カレンダーを連携できること
  • 任意のパブリックチャンネルへ投稿できること
  • 開始時間のn分前に投稿できること
    • 今まではリリース予定の開始15分前に通知するようにしていたため、同様に開始5-15分ぐらい前に投稿できるようにします
  • 月200ぐらいの予定を通知できること
    • 直近3ヶ月にカレンダーに入っていた予定の平均を参考に、余裕を持たせたバッファを込みにすると大体これぐらいかな…のざっくり計算です

Want

  • 1ヶ月あたりMax1600の予定を通知できること
    • 雑に全営業日にぎっしりリリース予定が登録された場合を計算すると、
      • 1つの予定を30分枠、1日8時間の中にぎっしり予定を詰め込んだとして、1時間あたり2予定 * 8時間 = 16予定
      • 16予定 * 5営業日 * 月の営業日目安として20日 = 1600予定

代替手段の検討

Google Calendarアプリ

Google Calendar for Team Eventsのページにも

これに代わるツールをお探しの場合は、Google カレンダーアプリをお試しください。
https://slack.com/intl/ja-jp/help/articles/360047938054

と掲載されているため、ひとまずGoogle Calendarのアプリで同様の動きができるか確認します。

Must条件 対応可否
複数人で管理ができること
共有カレンダーを連携できること
任意のパブリックチャンネルへ投稿できること ×
開始時間のn分前に投稿できること
月200ぐらいの予定を通知できること

2023年1月現在、Google Calendarアプリでは任意のチャンネルへの投稿はできないようで、この時点で今回採用するのは厳しそうです。
もしかするといつか実装されるかもしれない…ので、期待をしつつ、いつまでも待つことはできないので、今回は見送ることにしました。
(今後に期待…!)

Google App Scriptで自作

元々コードの管理や運用のコストが懸念として上がっていたところもあったので、最終手段かなぁ…と考えていました。

Must条件 対応可否
複数人で管理ができること
共有カレンダーを連携できること
任意のパブリックチャンネルへ投稿できること
開始時間のn分前に投稿できること
月200ぐらいの予定を通知できること

コードを書く必要はありますが、複数人での編集も招待すれば可能で、他の条件もAPIでどうにかはできます。
条件としてはMustもWantも全て満たせるのですが、やっぱりコストがなぁ…ということで、一旦保留にして他のサービスを検討します。

Zapier

連携と言えばiPaaSかなと、とりあえず思い浮かんだZapierを見ていきます。

Must条件 対応可否
複数人で管理ができること
共有カレンダーを連携できること
任意のパブリックチャンネルへ投稿できること
開始時間のn分前に投稿できること
月200ぐらいの予定を通知できること

すごく良さそう…ではあるのですが、複数人での管理、月200ぐらいの予定を捌けるかどうかはプラン次第なところがあります。

「Slackに投稿」のようなアクションがZapierのタスクにあたり、Freeプランは月100タスクまでという制限があります。
Zapierを使う場合に想定される1回あたりのタスクは、Googleカレンダーの予定取得 + Slack投稿の2回なので、Freeプランの範囲内では、月50回しか通知ができなさそうです。
また、Teamプラン以上でないと複数人での管理ができないため、今回は見送りました。

参考

Make

「なんか昔良いなーと思ったけど、初見での操作が難しくてすぐ離れちゃったのあったんだよなぁ」と思ってなんとか思い出したのがIntegromatです。
いつの間にか名称がMakeに変わっていました。

Must条件 対応可否
複数人で管理ができること
共有カレンダーを連携できること
任意のパブリックチャンネルへ投稿できること
開始時間のn分前に投稿できること
月200ぐらいの予定を通知できること

なにやら良い感じです。

Zapierではタスクと呼ばれていたものがMakeでは(ほぼ)オペレーションにあたり、Freeプランは月1000オペレーションまでという制限があります。
Makeを使う場合に想定される1回あたりのオペレーションも、Googleカレンダーの予定取得 + Slack投稿の2回なので、Freeプランの範囲内では月500回と、Wantの1600回までは難しいですが、超単純計算ではMust条件は満たしています。
(厳密にはカレンダーの予定が2つ取得されたら、Slack投稿は2回で計3回だったりと、タイミングによって前後します)

代理として使えるかどうかは、とりあえずFreeプランの範囲内で運用してみて考えようか、ということで、今回はMakeを採用することにしました。

参考

Makeで予定通知できるようにする

Templateを探す

今回のような「カレンダーに入っている予定を、n分前に特定のチャンネルへ投稿する」といった用途は多方面でニーズがありそうなので、まずはTemplateを漁ってみたものの、ドンピシャなものは見つけられませんでした。

近いもので「リマインダーをセットする」というテンプレートはあったので、自分にだけのリマインダーをセットする用途であれば使えるかもしれません。
MakeでのGoogle CalendarとSlackの連携テンプレート

シナリオを作る

なければ作るのみなので、Makeでモジュールを追加してシナリオを作っていきます。

ユーザーがカレンダーへ予定を追加した後、Makeでは作成されたイベントを拾い、Slackへ投稿する流れを作ります。
シナリオイメージ

作り方

  1. Google Calendarのアプリを選択
    シナリオを新規作成すると、真ん中に「+」のマークが表示されます。
    「+」を選択するとアプリ選択のポップが出てくるので、その中から「Google Calendar」を探し、選択します。
    アプリ一覧の中からGoogle Calendarを選択する

  2. 「Watch Events」を選択
    今回は追加された予定を取得して予約投稿できるようにしたいので、「Watch Events」を選択します。
    Watch Eventsを選択する

  3. 連携するカレンダーの設定

  • Connection
    連携するGoogle Calendarのアカウントを選択します
  • Calendar
    連携するカレンダーを選択します
  • Watch Events
    イベントの作成、更新、開始、が選択できるようになっていますが、今回は作成されたイベントを処理するため、「By Created Date」を選択します

Google Calendarの設定

  1. Slackのアプリを追加
    追加したGoogle Calendarモジュールの右側をホバーすると「add another module」という文字が表示されるので、選択します。
    Google Calendarのモジュールから、add another moduleの選択肢が表示される
    アプリ選択のポップが表示されるので、その中から「Slack」を探し、選択します。
    アプリ一覧の中からSlackを選択する

  2. 「Make an API Call」を選択
    「Create a Message」のモジュールではすぐにメッセージが投稿されてしまい、「n分後に投稿する」という挙動にできないため、Slackの予約投稿のAPIを利用します。
    選択できるモジュールの中には予約投稿はないですが、モジュール選択のポップの一番下に任意のSlack APIを実行できるモジュールがあるので、こちらを利用します。
    Make an API Callのモジュールを選択する

  3. POSTするSlack APIの設定
    SlackのScheduling messagesのドキュメントを参考に、POST内容等を設定していきます

  • Connection
    連携するSlackのアカウントを選択します
    Integromat Appのbotとして投稿するか、認証したユーザアカウントとして投稿するかを選択します
  • URL
    利用するAPIのパスを入力します
    今回は「/chat.scheduleMessage」のAPIを利用します
  • Method
    /chat.scheduleMessageのAPIはMethodがPOSTなので、「POST」を入力します
  • Headers
    Content-Typeはデフォルトでapplication/jsonが入っているので、そのままにします
  • Body
    表示したい内容と、投稿するSlackのチャンネルIDをJSONで記述します
    Slackの/chat.scheduleMessageのAPIを実行する設定
  1. フィルターを設定する
    過去の日時を/chat.scheduleMessageのAPIに送るとエラーになるので、Google Calendarから取得したイベントの開始日時が現在時刻+m分を切っている場合は、SlackへのPOSTを行わないようにしたいです。
    この場合「イベント開始日時 >= 現在時刻+m分」が条件になるので、フィルターのConditionのところに「1.start / Greater than equal to / add_minutes(now; m)」を設定します。
    1.start」はGoogle Calendarのイベント情報を参照できる変数、「now」は、Makeで利用できる関数です。
    今回、Slackに投稿されてほしい時間は予定の15分前ですが、タイミングによってAPIエラーになることを防ぐため、余裕を持たせて16分前にしています。
    イベント開始日時 >= 投稿予定日時(現在時刻+m分)の場合にSlackのAPIが叩かれるよう、フィルター設定する

テストする

設定したモジュール単体でテストをしたい場合は、対象のモジュールを右クリックするといくつかメニューが表示されるので、「Run this module only」を選択します。
モジュールのメニューから、Run this module onlyを選択する

一連の流れを1回だけ流してテストしたい場合は、画面左下の「Run once」から実行できます。
画面左下のRun Onceを押すと、1回だけ通しで実行する

プロダクト開発カレンダーさんの代理として動いてもらうため、Google Calendarっぽい表示になるよう、Slack APIのリクエストBodyとして下記のようなJSONを設定しました。

{
  "channel": "SLACK_CHANNEL_ID",
  "text": "",
  "blocks": [
    {
      "type": "section",
      "text": {
      "type": "mrkdwn",
        "text": "*プロダクト開発カレンダー(代理)*\nEvent starting in 15 minutes:"
      }
    }
  ],
  "attachments": [
    {
      "color": "#f691b3",
      "blocks": [
        {
          "type": "section",
          "text": {
            "type": "mrkdwn",
            "text": "*<{{1.htmlLink}}|{{1.summary}}>*\n{{formatDate(1.start; "YYYY年MM月DD日")}} from {{formatDate(1.start; "HH:mm")}} to {{formatDate(1.end; "HH:mm")}}"
          }
        }
      ]
    }
  ],
  "post_at": {{formatDate(addMinutes(1.start; -15); "X"; "JST")}},
}

それっぽい表示になりました。
プロダクト開発カレンダー(代理)による投稿例

フィルター設定したときと同様に、「1.hogehoge」はGoogle Calendarイベントの変数、formatDateaddMinutesはMakeで利用できる関数です。
https://www.make.com/en/help/functions/date---time-functions

post_atは投稿する日時(未来の日時)をUNIX timeで指定する必要があるので、イベント開始時間 - 15分の日時を変換して指定しています。
https://api.slack.com/methods/chat.scheduleMessage#args
https://www.make.com/en/help/functions/tokens-for-date-time-formatting

block部分はSlackがbuilderを用意してくれているので、画像を入れる場合のjsonなども簡単に作れるようになっています。
https://api.slack.com/block-kit

スケジュール設定をする

テストして問題なければ、シナリオ編集画面左下の「SCHEDULING」のトグルをONに変更するだけで、15分毎にシナリオが実行されるようになります。
今回はFreeプランで動作させていることもあり、オペレーションのカウントを極力減らすため、平日の特定時間帯で15分毎に実行されるようにしました。
平日の8:00-18:00に実行するようスケジュール設定する

課題

とりあえず投稿できるようにはなりましたが、/chat.scheduleMessageのAPIへ投げっぱなしになっているので、予定の変更にとても弱いです。
そのため、変更前の予定でSlackに投稿されたり、削除した予定が投稿されることもあります。

また、Makeの実行スケジュールもFreeプランでは最低15分毎(有料プランは1分〜)だったり、設定したフィルターによる制限があったりと、時間による制約がいくつかあるので急な予定も対応できないことがあります。

MakeにはData storeがあるので、APIを投げた後、レスポンスをゴニョゴニョしてData storeに保存するようにし、カレンダーの予定更新をトリガーにして、予定が変更されていたらスケジュールし直す、ということもできるかもしれませんが…その分オペレーションのカウントを消費するので、様子見中です。
https://www.make.com/en/help/tools/data-store

あくまでも代理という位置付けなので、緩く運用しつつ、SlackのGoogle Calendarアプリが任意のチャンネルに流せるようになるか、Google Calendar for Team Eventsに変わる何かが現れるのを期待しておこうと思います。

READYFORテックブログ

Discussion