一週間前にめっちゃやる気出たので作ってました。
できること
シンプルにGaroonとGoogle Calendarでの予定の追加、更新、削除に関する同期が可能です。
注意点
メンバーは同期されない
garoonとgoogle calendarではメンバーが異なるので、基本的に1人用の設計となっています。
e.g. google calendarで予定を作っても自分しかいない等
削除と更新には制約がある
google calendarではundoができたりするので、影響範囲を小さくするため、自分以外の他のメンバーが入っている予定に対しては、デフォルトでGaroon側の予定を消さない and 更新できない仕様になっています。
もし制約を外したい場合は、.env
のSAFETY
をfalse
するとすべてのイベントに対してこの制約をなくします。
Garoonからの状態は反映に時間がかかる
中央のgaoogleに対しては、以下のように接続します。
- google calendarはwebhook
- garoonはcrontabでAPIを叩く
つまり、google calendarから予定を変更した場合はリアルタイムに反映されますが、garoonはcrontabによりキックされAPIを叩くため、指定した時間にしかgoogle calendarに反映されません。
モチベーション
自分の予定を入れるのに、2つのカレンダーに登録するのが面倒くさくなってきたのが主な理由です。(エンジニアっぽい。。)
以前、サイボウズの方で出ているJavaの試したのですが証明書周りで使えなかったと、
サイボウズの方はgaroonからgoogle calendarの一方向なので、google calendarから予定の登録できないのは辛いなって思ったので書きました。
自分も最初のコミット時には、garoon -> google calenadarの目的でしたが。。。
github.com
アーキテクチャ
構成
- app
- garoonをcrontabで動かし、google calendarのwebhookをwatchしています
- mysql
- metaデータと共有フォーマットな予定データを格納しています
- batch
- google calendarの
Events:watch
実行とチャンネル作成サーバー
- google calendarの
上記をdocker-compose内に入れて動かしています。
+-----------------+ +-----------------+ | | | | | Garoon | | Google Calendar | | | | | +----+------------+ +-----+-----+-----+ ^ | ^ | | | fetch | webhook | | post by crontab | +---------------------+ | for updating a channel | | | | | | +----+---v--+ +-----+-----+ | | | | | app | | batch | | | | | | | | | +-+--+------+ +-----+-----+ | ^ | | | get | insert insert | | events +-----------+ | the latest channel information nextSyncToken and events | | | | | | +---------+ mysql | | | | <---------+ +----------->+ | +-----------+
Google Calendar APIの流れ
Push Notifications | Calendar API | Google Developers
大きく分けて、2つ仕組みが必要です。
定期的にwebhookを動かすようにするためにgoogle calendar apiを叩くアプリ
webhookのチャンネルには、寿命がありそれが切れると送られなくなります。
なので、チャンネルの寿命が無くなる前に、別チャンネルを発行し、切り替える必要があります。
Events::watch
にユニークなチャンネルのIDを付け、POSTします。Events::watch- 使わなくなったチャンネルは
Channels::stop
を叩き、止めます。Channels::stop
上記の処理を定期的に実行する必要があります。
が、自分の場合、x-goog-channel-id
と x-goog-resource-id
の値を付けても404となってしまいstopできないので、放置しています。。。
webhookを監視するためのアプリ
- google calendarに登録した、コールバックのURLが叩かれる
- headerに入っている
x-goog-resource-state
にはその2つの種類があり、sync
とexist
がある - 前回保存したnextSyncTokenを付け、
Events::list
を叩く - nextSyncTokenを保存する
2の種類には、以下の種類があります。
sync
: チャンネルが作られたexist
: 予定が操作(作成、更新、削除)された
また、Events::list
というAPIは、普通に叩いてもすべてのデータが返ってくるので、前回との差分を出すには、offsetを指定する必要があります。
このAPIを叩くと、headerにnextSyncToken
というoffsetの値が入っているので、次回叩くときにこの値を付与します。
garoogle/google-calendar.js at master · hiroppy/garoogle · GitHub
所感
Google CalandarとGaroonみたいな2区間のプロパティを合わせるのは大変だなって思ったのと、webhookのデバッグ大変すぎる〜〜。
もし、google calendarとgaroonをつなぎたい人は使ってみてください:)