Skip to content

feat: 解析飞书 interactive 卡片内容到历史上下文 - #240

Merged
lishuceo merged 2 commits into
mainfrom
feat/claude-session-3f3f5f
May 23, 2026
Merged

feat: 解析飞书 interactive 卡片内容到历史上下文#240
lishuceo merged 2 commits into
mainfrom
feat/claude-session-3f3f5f

Conversation

@lishuceo

Copy link
Copy Markdown
Owner

Summary

历史消息中 interactive 类型卡片之前被 fetchRecentMessages 白名单直接 drop(reason: unsupported_type),导致 bot 拉历史时拿不到话题开头的卡片内容(如 SpaceX/XOVR 分享卡片),看到的只有空话题或 [卡片消息] 占位。

实现方案2:递归解析卡片 JSON 提取可读文本。

  • 新增 formatInteractiveCard():解析 header.title + elements(支持 div/markdown/note/column_set/action/img/hr,以及 v2 form 的 body.elements),未知 tag 走 content/text 字段递归兜底以兼容第三方 share-card 等格式
  • client.ts fetchRecentMessages 白名单加入 interactive,parsing 分支调用 formatInteractiveCard
  • message-parser.ts formatMergeForwardSubMessageinteractive 分支同步切换(之前固定返回 [卡片消息]

Test plan

  • interactive-card.test.ts 12 个新单测
  • merge-forward.test.ts 更新 interactive 用例
  • 全量 vitest run 无回归
  • tsc --noEmit 通过

🤖 Generated with Claude Code

lishuceo and others added 2 commits May 23, 2026 13:22
历史消息中 interactive 类型卡片被白名单 drop,导致 bot 拉不到话题开头的卡片内容(如 SpaceX/XOVR 分享卡)。

- 新增 formatInteractiveCard():递归解析卡片 header.title + elements (div/markdown/note/column_set/action),未知 tag 走 content 字段兜底
- client.ts fetchRecentMessages 白名单加入 interactive,parsing 分支调用 formatInteractiveCard
- message-parser.ts formatMergeForwardSubMessage interactive 分支同步切换

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
覆盖 header/div/fields/note/column_set/action 已知 tag,以及第三方卡片未知 tag 的兜底,共 12 个用例。同步更新 merge-forward.test.ts 的 interactive 用例。

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@github-actions

github-actions Bot commented May 23, 2026

Copy link
Copy Markdown
Contributor

Claude finished @lishuceo's task in 1m 42s —— View job


Claude Code Review

  • Check previous review comments (none found)
  • Read CLAUDE.md and PR context
  • Review src/feishu/message-parser.ts (formatInteractiveCard)
  • Review src/feishu/client.ts changes
  • Review test files
  • Post review summary

Verdict: ✅ Approved

PR 实现干净、目标明确,测试覆盖充分。formatInteractiveCard 对常见 element tag 都做了显式处理,未知 tag 走深度受限的递归 content 提取兜底,这是处理飞书 share-card 等第三方卡片的合理策略。

评估要点

正确性

  • src/feishu/message-parser.ts:5-33 标题双格式兼容({content} vs {text:{content}})、v1/v2 elements 位置兼容(elements vs body.elements) — 都正确处理
  • src/feishu/message-parser.ts:102-116 递归深度上限 6 防止过深结构爆栈;JSON.parse 不产生循环引用,无环检测风险
  • src/feishu/client.ts:620 白名单加入 interactive,与 interactive 分支调用 formatInteractiveCard(648) 一致;message-parser.ts:186 合并转发分支同步更新,前后行为统一
  • 全部失败路径都有兜底文案([卡片消息] / [卡片消息 - 解析失败]),不会抛到调用方

安全性

  • 仅做文本提取,不执行任何 url/action,无 XSS/注入风险
  • 解析全程包裹在 try/catch,不会因为恶意构造的 JSON 让进程崩溃

测试

  • interactive-card.test.ts 12 个用例覆盖: header 两种格式、div/markdown/note/column_set/action/img/hr、v2 body、未知 tag 兜底、空卡片、非法 JSON、组合场景
  • merge-forward.test.ts:243-257 同步更新了 interactive 用例,与新行为一致

次要观察(不阻塞合并)

🟡 低置信度提示formatMergeForwardSubMessageinteractive 分支会先 JSON.parse(contentJson) 一次得到 body(用于其他 msgType),然后调用 formatInteractiveCard(contentJson) 内部再 parse 一次。冗余开销极小,可忽略;仅记录为风格观察,不建议改动。
· Branch: feat/claude-session-3f3f5f

@lishuceo
lishuceo merged commit 88b0c67 into main May 23, 2026
4 checks passed
@lishuceo
lishuceo deleted the feat/claude-session-3f3f5f branch May 23, 2026 06:34
lishuceo added a commit that referenced this pull request May 24, 2026
PR #240 在 message-parser.ts 中加了 formatInteractiveCard 作为同问题
的局部修复。本 PR 的统一 extractCardText 设计是其超集,故:

- 删除 formatInteractiveCard,client.ts/interactive-card.test.ts 改用新 API
- 增强 extractCardText: v2 body.elements、嵌套 title.text.content、
  未知 tag 兜底递归(覆盖第三方 share-card)
- 更新 message-text.test.ts: 适配 main 已删除的 buildResultCard/
  buildSimpleResultCard,改用 buildOverviewCard/buildTextContentCard

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
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.

1 participant