跳转至

后端-飞书API-workday重复创建日程

问题现象

每次运行 workday --sync --overwrite,飞书日历上的日程数量持续增加,而非保持与本地一致。定时事件(19:00-21:00)尤其严重,单次同步可产生 7+ 重复。全量查询显示 24+ 条但本地只有 18 条。

核心问题

三个独立的 Bug 层层叠加:

1. Calendar ID 字面量错误(全天日程全部未创建)

build_event_cmd 中创建全天日程时使用字面量 "primary" 作为 calendar_id:

params = json.dumps({"calendar_id": "primary"})  # ← 错误
而飞书 events.create API 需要真实的 calendar ID(如 feishu.cn_xxx@group.calendar.feishu.cn)。删除操作使用 get_primary_calendar_id() 获取真实 ID 正常执行,但创建操作用 "primary" 无效 → 每次 sync 清空旧日程但不创建新日程 → 手动重新创建后累积重复。

2. query_events_for_date 只过滤 start.date,遗漏定时日程

search_event 返回的定时事件使用 start.date_time2026-07-18T19:00:00+08:00)而非 start.date。代码只检查 start.date

start_d = meta.get("start", {}).get("date", "")  # ← 定时日程此字段为空
导致定时事件在删除阶段未被发现 → 每次 sync 只增不删 → 单日最多积累 8 个重复。

3. search_event 响应结构解析偏移

events.search_eventevent_id 不在 item 顶层,而在 item.meta_data.event_id 内。代码从 item.get("event_id") 取值得到 None

eid = item.get("event_id", "")  # ← 应为 meta.get("event_id")
导致查询返回 0 条日程,即使是全天日程也未清除。

解决方法

  1. 修复 Calendar IDbuild_event_cmd 中统一调用 get_primary_calendar_id() 获取真实日历 ID:

    cal_id = get_primary_calendar_id()
    params = json.dumps({"calendar_id": cal_id})
    

  2. 修复定时日期提取query_events_for_date 同时检查 start.datestart.date_time

    start_d = start.get("date") or (start.get("date_time", "")[:10]) or ""
    

  3. 修复 event_id 提取路径:从 meta_data 内获取:

    eid = meta.get("event_id", "")
    

  4. search_event 替代 +agenda:改用 events.search_event --page-all 确保全量查询,避免分页遗漏:

    [lark, "calendar", "events", "search_event", "--as", "user",
     "--params", params, "--data", body, "--page-all"],
    

  5. 执行全量覆盖同步:修复后运行 python .codebuddy/skills/workday/scripts/workday.py --sync,清除全部 34 条旧数据,重新创建 18 条新日程。

下次防错措施

  • 定时日程验证:验证脚本需同时覆盖 start.datestart.date_time 两种格式
  • API 响应结构检查:调用任何新飞书 API 前,先执行 raw_api --format json 检查返回结构,确认字段路径
  • 重复检测:运行 python .codebuddy/skills/workday/scripts/workday.py --sync 后立即检查飞书日历总数是否等于本地扫描条数
  • 测试覆盖:单元测试中增加 test_filters_other_date(定时+全天混合场景)和 test_search_event_parse(meta_data 结构解析)