Skip to content

feat: 实现 issue #199 飞书 API 变动检测新增接口 (10 个 API)#200

Merged
foxzool merged 12 commits into
mainfrom
feat/issue-199-api-drift
Jun 15, 2026
Merged

feat: 实现 issue #199 飞书 API 变动检测新增接口 (10 个 API)#200
foxzool merged 12 commits into
mainfrom
feat/issue-199-api-drift

Conversation

@foxzool

@foxzool foxzool commented Jun 15, 2026

Copy link
Copy Markdown
Owner

概述

实现 issue #199 报告的 10 个新增飞书 API(完整强类型),并更新 api_list_export.csv 基准。

Closes #199

实现内容

Block 1:新建 openlark-bot crate(1 API)

  • POST /open-apis/bot/v4/bot/search 搜索机器人

Block 2:openlark-communication(1 API)

  • POST /open-apis/im/v2/chats/search 搜索群组

Block 3:openlark-mail(8 APIs)

API 方法 说明
profile GET 获取用户邮箱信息
search POST 搜索邮件(含 11 字段 filter)
send_status GET 查询邮件发送状态
recall POST 撤回已发送邮件
get_recall_detail GET 获取邮件撤回进度
cancel_scheduled_send POST 取消定时发送
get_signatures GET 列出邮件签名
multi_entity/search POST 多实体搜索

CSV 更新

api_list_export.csv 追加 10 行(1702 → 1712 基准)

设计决策

  • 完整强类型:请求体 + 响应体均用 serde 结构体(非 serde_json::Value
  • 字段可空性:全部 Option<T>(飞书字段非必返)
  • 类型不明内层:用 serde_json::Value 兜底(如 signatures 的 user_fields
  • 34 处字段变化零改动:经分析全是文档元数据噪声(url/docPath/meta.Resource/isCharge),涉及的 aily/okr/task/vc API 在 飞书 API 变动检测:2026-06-08 #195 已实现,代码用硬编码 URL 常量、不依赖 resource 名/isCharge
  • URL 用复数 user_mailboxes(与飞书文档 + 现有 send.rs 一致)

字段来源

通过飞书 document_portal/v1/document/get_detail 的 apiSchema 接口获取全部 10 个 API 的完整字段定义(含 6 个文档页尚未发布的 mail API)。

验证

  • cargo fmt --check
  • cargo build --workspace --all-features
  • cargo test --workspace --lib --tests(0 failed)
  • cargo clippy --workspace --all-targets --all-features(0 warning)
  • ✅ 代码审查 APPROVED(无 Critical/Important 问题)

设计文档

  • Spec: `docs/superpowers/specs/2026-06-15-issue-199-api-drift-design.md`
  • 计划: `docs/superpowers/plans/2026-06-15-issue-199-api-drift.md`

foxzool added 12 commits June 15, 2026 11:34
- 创建 openlark-bot crate 骨架 (lib/service/bot 模块层级)
- 注册到 workspace members + workspace deps
- 根 crate 添加 bot feature + 导出
- openlark-client 注册 bot feature + 导出 BotClient
- POST /open-apis/bot/v4/bot/search
- 强类型请求体 (query/filter) + 响应 (items/meta_data/分页)
- 6 个测试通过
- POST /open-apis/im/v2/chats/search
- 强类型请求体 (query/filter/sorter) + 响应 (items/meta_data/分页)
- 新增 IM_V2_CHATS_SEARCH 端点常量
- 2 个测试通过
- GET /open-apis/mail/v1/user_mailboxes/:id/profile (强类型)
- POST /open-apis/mail/v1/multi_entity/search (强类型)
- 挂载到 UserMailbox::profile() 和 MailV1::multi_entity()
- 2 个测试通过
- POST /open-apis/mail/v1/user_mailboxes/:id/search
- 强类型请求体 (query/filter: from/to/cc/bcc/subject/folder/label/has_attachment/is_unread/create_time)
- 强类型响应 (items/meta_data: title/from/分页)
- 挂载到 UserMailbox::search()
- 2 个测试通过
- GET  .../messages/:id/send_status (强类型, 含 recipient/details)
- POST .../messages/:id/recall      (撤回, recall_status/restriction_reason)
- GET  .../messages/:id/recall      (撤回进度, recall_result/items 逐收件人)
- 挂载到 Message::send_status() 和 Message::recall()
- 3 个测试通过
- POST .../messages/:id/cancel_scheduled_send (空响应)
- GET  .../settings/signatures (强类型, signatures/images/usages)
- 挂载到 UserMailbox::cancel_scheduled_send() 和 UserMailbox::get_signatures()
- 2 个测试通过
修复 missing_docs clippy warning:
- mail 7 个新 API 的 Response.code/msg/data 补文档注释
- communication im/v2/chat/search 的 Response 补文档注释
- 全量 clippy 0 warning
从飞书 catalog 拉取 issue #199 报告的 10 个新增 API:
- bot: 搜索机器人
- im: 搜索群组
- mail: 多实体搜索/搜索邮件/获取用户邮箱信息/查询发送状态/
        撤回邮件+进度/取消定时发送/列出邮件签名

CSV: 1702 → 1712 个 API 基准 (fixes #199)
修复 msrv CI 检查失败: cargo check --locked 因 pinned lockfile
缺少 openlark-bot 条目而报错。openlark-bot 的依赖 (openlark-core/
reqwest/serde 等) 都已在 lockfile 中, 仅需添加 crate 自身条目。

pinned lockfile: 395 → 396 包

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 793704e6c1

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +65 to +68
impl ApiResponseTrait for SearchChatsResponse {
fn data_format() -> ResponseFormat {
ResponseFormat::Data
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Model Data responses as payloads, not envelopes

For successful Feishu responses shaped as {code,msg,data:{...}}, ResponseFormat::Data makes Transport deserialize only the data object into SearchChatsResponse; because this type starts with required envelope fields like code/msg, deserialization fails and execute() returns 响应数据为空 for normal successes. The same envelope-as-payload pattern appears in the new mail and bot endpoints, so those APIs are likewise unusable until the response type is either the data payload or the format/deserialization is changed.

Useful? React with 👍 / 👎.

application = ["auth", "dep:openlark-application"]
helpdesk = ["auth", "dep:openlark-helpdesk"]
mail = ["auth", "dep:openlark-mail"]
bot = ["auth", "dep:openlark-bot"]

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Wire the bot feature into the Client entrypoint

Enabling this new openlark-client/bot feature only re-exports BotClient; crates/openlark-client/src/client.rs still has no bot entry in the declare_client! list, unlike mail, analytics, and the other service features. In the documented meta-entrypoint context, users enabling openlark = { features = ["bot"] } cannot access the new service through client.bot..., so the feature needs a Client field/init (and associated registry metadata if expected).

Useful? React with 👍 / 👎.

Comment thread api_list_export.csv
7645347118866549703,搜索清单,task,task,v2,tasklist,search,,basic,true,POST:/open-apis/task/v2/tasklists/search,/open-apis/task/v2/tasklists/search,1,"[""isv"", ""custom""]",[],1780976928,false,1,https://open.feishu.cn/document/server-docs/task-v2/tasklist/search
7646314141168291027,订阅纪要变更事件,vc,vc,v1,note,subscription,,basic,true,POST:/open-apis/vc/v1/notes/subscription,/open-apis/vc/v1/notes/subscription,1,"[""isv"", ""custom""]",[],1780976928,false,1,https://open.feishu.cn/document/server-docs/vc-v1/note/subscription
7646314141168307411,取消订阅纪要变更事件,vc,vc,v1,note,unsubscription,,basic,true,POST:/open-apis/vc/v1/notes/unsubscription,/open-apis/vc/v1/notes/unsubscription,1,"[""isv"", ""custom""]",[],1780976928,false,1,https://open.feishu.cn/document/server-docs/vc-v1/note/unsubscription
7649732836954606572,搜索群组,,im,v2,chat,search,,,true,/uAjLw4CM/ukTMukTMukTM/group/im-v2/chat/search,POST:/open-apis/im/v2/chats/search,1781084253389,"[""custom"", ""isv""]",[],,,1,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Populate the CSV columns in the current schema

The new catalog rows starting here are shifted relative to the header: bizTag is empty, the doc path is stored in url, and the real METHOD:/open-apis/... value is stored in fullPath. Because tools/validate_apis.py filters by row["bizTag"] and compares row["url"], these added APIs are invisible to crate coverage checks and URL contract validation even though code was added for them.

Useful? React with 👍 / 👎.

Comment thread Cargo.toml
# 专业服务
"crates/openlark-helpdesk", # 帮助台
"crates/openlark-mail", # 邮件服务
"crates/openlark-bot", # 机器人服务

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Add openlark-bot to the coverage mapping

Adding openlark-bot as a workspace crate without a matching [crates.openlark-bot] entry in tools/api_coverage.toml leaves the new service outside the repo's API validation tooling; python3 tools/validate_apis.py --crate openlark-bot currently exits with “映射文件中不存在 crate: openlark-bot”. This means future coverage reports and drift checks cannot validate the bot API even after this crate is enabled.

Useful? React with 👍 / 👎.

Comment on lines +148 to +149
let mut req: ApiRequest<SearchBotResponse> =
ApiRequest::post("/open-apis/bot/v4/bot/search");

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Restrict bot search to user access tokens

The official bot search API is authorized with user_access_token, but this request leaves the default supported token types in place. With token cache enabled and no explicit RequestOption, Transport prefers tenant auth for the default [User, Tenant] set, so execute() sends the bot search request with a tenant token and fails for a normal user-visible bot search.

Useful? React with 👍 / 👎.

Comment on lines +69 to +70
"/open-apis/mail/v1/user_mailboxes/{}/messages/{}/cancel_scheduled_send",
self.mailbox_id, self.message_id

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Use the scheduled draft id when cancelling

For scheduled-send cancellation, the current Lark CLI docs/schema expose this operation as user_mailbox.drafts cancel_scheduled_send with draft_id, and scheduled sends do not produce a usable message_id until delivery; building /messages/{message_id}/cancel_scheduled_send means callers only holding the scheduled draft id cannot cancel before it sends. This request should target the draft cancellation resource/id instead of requiring a sent-message id.

Useful? React with 👍 / 👎.

@foxzool foxzool merged commit 063918c into main Jun 15, 2026
131 checks passed
@foxzool foxzool deleted the feat/issue-199-api-drift branch June 15, 2026 04:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

飞书 API 变动检测:2026-06-15

1 participant