mcpField
G
google-calendar-sync

google-calendar-sync

github.com/timerise-ai开发03 次安装3 天前更新
代码仓库

关于 google-calendar-sync

google-calendar-sync 是用于在预约系统中实现或审查 Google Calendar 同步的技能。它将忙碌时段导入与预约事件写出分开,并提供 OAuth、存储、通知、频道和测试方面的指导。

主要功能

  1. 01通过完整时间窗重同步导入忙碌时段
  2. 02使用确定性 ID 写入预约事件
  3. 03处理 OAuth 连接与加密令牌
  4. 04续订监听频道并安排重同步
  5. 05提供 Firestore 和 Supabase 存储选项
  6. 06涵盖测试与运维指导

适用场景

  1. 01根据所选日历阻止主持人的可预约时段
  2. 02将已确认预约添加到主持人日历
  3. 03审查重复、过期或停止的同步
  4. 04在 Firestore 与 Supabase 之间迁移同步存储

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/timerise-ai/google-calendar-sync --skill google-calendar-sync

安装后在 Claude Code 中输入/google-calendar-sync确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

CHANGELOG.md
README.md
CLAUDE.md
LICENSE
.gitattributes
.github/workflows/
agent-eval.yml
evals/
prompts.md
references/
booking-events.md
adaptation.md
busy-sync.md
channels-and-settings.md
data-model.md
http-routes.md
operations.md
test-suite.md
google-api.md
oauth-and-tokens.md
firestore-backend.md
supabase-backend.md
provenance.md
testing.md

详细介绍

Google 日历同步

两个方向,各有一条规则。导入:Google 是了解主持人其他日程安排的事实来源,因此忙碌时间段只是某个时间窗口的临时镜像,会通过完整重新同步重建,绝不手动编辑。 导出:预订存储是预订信息的事实来源,因此写入 Google 的事件使用根据预订生成的 ID,绝不会被读回并作为忙碌时间。模板及其测试正是通过保持两个方向相互独立来确保这一点。

适用场景

  • 主持人连接 Google 日历,并选择会影响其可用时间的日历。
  • 预订会显示在主持人的 Google 日历中,可选择附带 Meet 链接,取消后会消失。
  • 审查现有的 Google 同步:重复项、残留项、同步停止或反复重连。
  • 将同步从 Firestore 迁移到 Supabase/Postgres,或反向迁移。

不适用场景

  • 生成可预订时段、扣除忙碌时间:使用 time-slot-generator。此技能会生成它所消耗的忙碌时间段。
  • Outlook 或 Microsoft 365:使用 microsoft-calendar-sync,它在 Microsoft Graph 上采用相同的架构和记录结构。
  • 显示日历 UI 或发送邀请:使用主持人自己的电子邮件;此方案写入事件,但不会发送 Google 邀请邮件。
  • 无需按用户 OAuth 的只读可用时间查询:使用 Google 的免费/忙碌查询搭配服务账号和全网域委派,这是另一种设计。

架构

          connect (PKCE, single-use state) -> callback -> encrypted tokens -> calendar rows
                                                                                  |
 inbound   Google -- X-Goog-* -> /notifications -> syncBusy (lease) -> list all pages -> toBusyBlock -> diffBusy -> busy blocks -> availability
              ^                                         ^
              +-- watch channel <-- cron: renew new-before-old, resync every busy calendar
 outbound  booking confirmed -> pushBookingEvent -> insert id=bk<sha256> (409: update) -> Meet link back
           booking cancelled -> removeBookingEvent -> delete by id (404/410 = done)
适配约定

adaptation.md 包含完整约定、主持人前置条件和工作顺序。重命名表见 data-model.md。

接口此技能提供宿主提供
身份验证authenticate(request): userId or null宿主的会话查询
数据Firestore 和 Supabase 上的 CalendarStore宿主的项目
预订BookingSource、pushBookingEvent、removeBookingEvent宿主预订状态流程中的调用
可用时间每位用户的忙碌时间段、listHostBusy宿主的时段引擎(time-slot-generator)
HTTPWeb Request 和 Response 处理器Next.js 路由处理器,或 Express 适配器
后台任务每 12 小时执行一次 renewChannels,defer 可选宿主的调度器、after()

重要事实

  1. 忙碌时间同步是对完整时间窗口重新同步,而不是事件流。 通知只表示“有内容发生了变化”。必须列出 [now, now + horizon) 的所有页面并进行差异比较。列表不完整时必须中止,绝不能删除数据。
  2. 所有 ID 都是确定性的。 日历行、忙碌时间段和预订事件均由其所代表内容的哈希生成。因此,并发通知、重试和重复触发最终会收敛,而不会产生重复项。
  3. 自己的事件也会被读回来。 如果将预订写入同时启用了忙碌时间同步的日历,该事件就会被重新导入,除非它带有私有的 bookingId 标记并被跳过。对于按席位计费的服务,这会导致群组活动在首个预订后就无法再预订。
  4. 只有频道保持活动状态时,Google 才会告知你发生了哪些变化。 频道会过期,通知不一定会重试,而且时间窗口会向前移动。定时任务会续期频道并重新同步每个忙碌日历;没有它,忙碌时间就会停止更新,而且不会报告此情况。
  5. invalid_grant 是一种状态,不是错误。 访问权限被撤销、六个月未使用,或处于“Testing”模式七天,都可能导致此状态。将连接标记为 reauth_required 并向用户显示;重新连接同一账号时保留所有设置。
  6. 全天事件的范围从 start.date 到不包含在内的 end.date,两者均为日历时区的当地午夜。 定时事件包含时区偏移。导出时间点时要保留 Z;去掉它会导致事件时间发生偏移。
  7. 空闲和已拒绝的事件不会阻塞。 Google 自己的空闲/忙碌查询会忽略它们。节假日日历是例外:仅在启用它们以便阻塞时才使用。

严格规则

1. 绝不要从 OAuth 回调 URL 获取用户 ID。 state 是服务器端单次使用、有效期为 10 分钟的记录的键。否则,任何人都可以把自己的日历关联到别人的账户。

2. 在通道令牌针对其所关联的通道 ID 验证通过前,绝不要信任通知。 端点是公开的;令牌是唯一的凭据。

3. 新通道建立前,绝不要停止旧通道。 如果新监视失败,日历就没有通道,也没有任何机制续期,其忙碌时段将停止更新,而 UI 却显示为“已开启”。

4. 绝不要以明文存储令牌。 刷新令牌可以长期读取和写入日历。

5. 绝不要让 Google 故障导致预订失败。 外发写入只记录日志并返回;预订仍然有效。

快速开始

  1. 阅读宿主项目并填写适配契约:adaptation.md。
  2. 创建 Google Cloud OAuth 客户端和授权同意屏幕: oauth-and-tokens.md。
  3. 复制类型定义并决定重命名方式:data-model.md。
  4. 复制 Google 客户端:google-api.md。
  5. 复制入站同步 busy-sync.md;外发同步 booking-events.md;生命周期管理 channels-and-settings.md。
  6. 选择存储后端:firestore-backend.md 或 supabase-backend.md。
  7. 挂载路由和 cron:http-routes.md。
  8. 复制测试套件,并在两种 TZ 值下运行:testing.md、 test-suite.md。
  9. 为运维人员提供健康状态视图:operations.md。
  10. 正在修复现有集成?修复顺序见 provenance.md。

参考目录

场景触发关键词参考资料
接缝与工作顺序adapt, host probe, seam contract, non-negotiablesadaptation.md
实体、存储契约、重命名LinkedCalendar, BusyBlock, WatchChannel, CalendarStore, mutateCalendar, version, compare-and-swapdata-model.md
连接账户OAuth, PKCE, state, consent screen, scopes, refresh_token, invalid_grant, reauth, revoke, AES-256-GCM, Testing modeoauth-and-tokens.md
与 Google 通信fetch, calendarList, events.list, pageToken, events.watch, channels.stop, 409 duplicate, 410, rate limitgoogle-api.md
忙碌时段同步toBusyBlock, transparency, declined, all-day, end.date, DST, diffBusy, lease, resyncRequested, horizonbusy-sync.md
创建预订event id, base32hex, extendedProperties private, Meet, conferenceData, hangoutLink, sendUpdates, backfillbooking-events.md
通道与开关startChannel, renewChannels, make-before-break, orphan channel, holiday calendar, syncBusy, syncBookings, planTransitionschannels-and-settings.md
路由与 webhookX-Goog-Channel-ID, X-Goog-Resource-State, sync, exists, 204, callback redirect, cron secret, Next.js, Expresshttp-routes.md
Firestorefirebase-admin, runTransaction, batch 500, calendarBusyBlocks, composite index, security rulesfirestore-backend.md
Supabase / Postgresschema.sql, RLS, service role, optimistic concurrency, 23505, PostgREST 1000 rowssupabase-backend.md
验证node:test, memory store, fake Google, TZ=, mutation checktesting.md, test-suite.md
运行health, stale, channel-expired, env vars, quotas, dashboards, runbook, ngrok, localhostoperations.md
构建缘由audit, defect, kept deliberately, designed here, fix orderprovenance.md

此内容属于 Timerise Skills 索引的一部分,该索引列出了相关技能。

评论

支持 Markdown