✅Google Calendarに自動で転記する (takker99/takker-scheduler)
現状
日刊記録sheetとGoogle Calendarを同期する機能を使ってtakker99/takker-schedulerのタスクを同期している
browserで手動で実行する機能
browserから直接Google APIを叩いて日刊記録sheetの中身をGoogle Calendarに書き込んでいる
本当はScrapboxのCSP制限に引っかかって叩けないはずなのだが、takker.iconの使っているFirefoxだと何故か叩けたので、そのまま使っている
多分CSP設定が何故かバグっている
Firefox Nightlyは正常だったけど
問題点
特定の状況でしか同期できない
laptopでFirefoxを使っているときのみ
smartphoneを使っているときは同期不可能
TamperMonkeyとかを入れられない
手動で同期しないといけない
上記のどちらかが解決してくれればいい
ほしいのはだいたい最新の情報がCalendarに反映されていること
どうするか
今考えている案
Google Apps Scriptで同期用serverを立てる
実行方法
定期実行
10分間隔くらいで指定したprojectの更新を確認し、もし日付ページが更新されていればそれらを読み込んで実行する
手動実行
web hook機能を使う
URL parametersに同期したい日付及び期間を渡してGETすると、指定した範囲のscheduleを更新する
web hook URLは秘匿する
勝手に使われると困る
とはいえ、使われても自分の個人情報を外部から盗めないのでそこまで問題ではない
やれることは「自分のprivate projectの日付ページのタスクと記録を自分のcalendarに転送」すること
それ以外の外部送信は不可能
使用するAPI
CalendarAppを使おうかと思ったけど、ちょっと検索能力が貧弱だな
private propertiesを指定した検索ができない
URLを埋め込めない
まあこれはdescriptionに埋め込めばいいだろうけど
Advanced Calendar Serviceが使えればいいのだが
あ、以前試して使えたっぽいな。ならこれを使うか。
てかGAS用のコードもtakker-scheduler-3/syncで少し書いていたんじゃん!
こりゃいい。少し流用させていただこう
実装
scrapboxで動かしているコードからGoogle APIを呼び出している部分を分離し、Advanced Calendar Serviceに置き換える
そもそも同期機能の処理の流れはどうなっている?
関係するファイル
./api/calendar.ts
replaceEvents()
特定ページに対応した全ての予定と記録を、渡された予定と記録におきかえる
特定ページに対応するeventsをsearchEvents()で検索する
置き換えはcreateEvent(), updateEvent(), deleteEvent()を組み合わせて行う
./sync.ts
syncPages()
scrapboxのページからテキストを取得し、syncTasks()に渡している
syncTasks()
analyze()で変換したEventsをreplaceEvent()でGoogle APIに送っている
analyze()
task line (takker-scheduler-3)→Event形式の予定と記録
これは使いまわせそうだな
APIに依存する関数と、任意のAPIと組み合わせられるロジックとが密結合しているな……
といってもこれ以上分けられないか……
2022-02-04 17:44:13 適当にコピペしつつ書き換えよう
18:15:30 こうした
parse.ts
parse()
task line (takker-scheduler-3)をEventに変換する
replace.ts
replace()
新しいeventsに置き換える
events.ts
eventsのCRUD関数群
search()
指定したページに紐付けられたeventsを探す
main.ts
entry point
scheduledTask()
定期実行する関数
前回の実行時から更新された日付ページがあれば、それを反映する
syncInterval()
web hookから呼び出す関数
特定期間の日付ページを全てカレンダーに反映させる
fetch.ts
getPages()
scrapboxのページデータを取得する
checkModifiedDiaryPages()
ある日時から更新された日付ページのタイトルを取得する
18:46:17 fetch.ts実装した
19:35:29 events.tsとreplace.tsを実装した
20:10:17 全部実装した
consoleで型エラーが出てしまうな
GASのconsoleと衝突する
まあ仕方ないか。
20:13:31 build.tsを作る
deno bundleしたあとgas-entry-generatorを通してファイルに書き込む
20:21:09 buildに失敗した
多分Optional chaining operatorを認識できていないんだと思う
どうすっかな……
?.や??を使わずに書く
esbuildでdowngradeする
--target=es2019で無効化できた
20:34:35 最終的にes2017まで落としてbuildした
20:39:12 GASに貼り付けてテストする
この規模のminified codeなら、負荷なく貼り付けられるみたい
20:45:11 02-03から02-04までを同期してみた
うまく動いているっぽい?
console.log()を挟んで進行状態を読み取れるようにしよう
21:01:46 あれ?おかしい。カレンダーに反映されていない?
実行はされているし、APIも叩いてある
エラーも特に出ていないのだが……
Google APIを実際には呼び出せていないとか?
minifyしていないコードにbreak pointを仕掛けて試そう
というかminifyしなくても普通に貼り付けられたな
やはり小規模なコードっぽいな
21:12:50 returnをcontinueに直すのに気づいていなかった
21:14:35 ええ……rate limit引っかかっちゃうのか……
code:errpr
GoogleJsonResponseException: API call to calendar.events.insert failed with error: Rate Limit Exceeded
21:25:40 もう一回実行したら全部通った
そんなにrate limitが厳しいわけではなさそう
15分に一回おきで定期実行させればいいかな
21:32:54 scrapboxで実行する同期機能を削除した
21:52:21 実際に更新したeventの数をlogに書き込むようにした
deploy先projectはここ
https://script.google.com/u/1/home/projects/1qT1T01PpAUVOGeoN95vQLKwjlGnR5OHQCEpcLbezKOtcBhRPPllbHfCv/edit
22:02:01 よし、mergeしておしまいだな。
22:18:40 merged
まだ実装していないこと
web hook
そういえばまだ作ってなかった
まあ今度でいいや
#2022-02-04 15:29:47