feat: support message receive event card format#1480
Conversation
📝 WalkthroughWalkthroughAdds ChangesInteractive Card Conversion
Sequence DiagramsequenceDiagram
participant ProcessImMessageReceive as processImMessageReceive
participant ConvertInteractiveEventContent
participant buildMentionMap
participant userDslConverter
participant convertElements
ProcessImMessageReceive->>ConvertInteractiveEventContent: rawContent + mentions
ConvertInteractiveEventContent->>buildMentionMap: mentions []interface{}
buildMentionMap-->>ConvertInteractiveEventContent: mention map
ConvertInteractiveEventContent->>userDslConverter: user_dsl + mentionMap
userDslConverter->>convertElements: body.elements or root elements
convertElements-->>userDslConverter: rendered text
userDslConverter-->>ConvertInteractiveEventContent: <card title>rendered</card>
ConvertInteractiveEventContent-->>ProcessImMessageReceive: human-readable text or [interactive card]
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
🚀 PR Preview Install Guide🧰 CLI updatenpm i -g https://pkg.pr.new/larksuite/cli/@larksuite/cli@d77fde5842c551153f7977468f647820c70478fc🧩 Skill updatenpx skills add 91-enjoy/cli#feat/event_card_format -y -g |
Change-Id: Id7ed87e907cc3159f479b217ce704c777c26e4e7
1f92f7c to
d77fde5
Compare
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@shortcuts/im/convert_lib/card_userdsl.go`:
- Around line 63-66: The resolveAtMentions function returns early when the
mentionAt map is empty, preventing the fallback parsing of <at id=...> and <at
ids=...> tags that should convert to `@id` format. Remove the early return
condition (lines 64-66) so the function continues to parse <at> tags and extract
the id or ids attributes as a fallback when no mention map is provided.
Additionally, add a unit test case to verify the fallback behavior works
correctly, such as testing that <at id=ou_x></at> converts to `@ou_x` when
mentionAt is nil or empty.
- Around line 117-126: The ConvertInteractiveEventContent function currently
returns the fallback "[interactive card]" when the JSON doesn't contain a
user_dsl field, even if rawContent itself is valid card DSL. When the unmarshal
succeeds but user_dsl is missing or empty in the content map, attempt to convert
rawContent directly as card DSL (using convertUserDslCard with the appropriate
mention map) before falling back to the "[interactive card]" message. This
ensures direct card JSON structures like {"header":{...}} are properly converted
to readable output. Additionally, add a test case to assert that direct
interactive card content is rendered correctly rather than replaced by the
fallback message, following the coding guideline that every behavior change
needs an accompanying test.
- Around line 158-160: The code currently only attempts to read the `zh_cn`
locale from the `i18n_header` object, which causes legacy cards that only have
`en_us` or `ja_jp` entries to lose their header content. Update the
`i18n_header` extraction logic to implement the same locale fallback mechanism
that `extractTextContent` already uses by trying to retrieve the header in order
from `zh_cn`, `en_us`, and `ja_jp`, returning the first one that exists instead
of only attempting `zh_cn`.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 083dc339-1f10-4097-9ad3-3f3f75393320
📒 Files selected for processing (3)
events/im/message_receive.goshortcuts/im/convert_lib/card_userdsl.goshortcuts/im/convert_lib/card_userdsl_test.go
🚧 Files skipped from review as they are similar to previous changes (1)
- shortcuts/im/convert_lib/card_userdsl_test.go
Summary
Previously,
im.message.receiveevents withmessage_type: interactivesurfaced the raw JSONpayload as
content, requiring callers to manually parse the card schema. This PR introduces auser_dslrenderer (ConvertInteractiveEventContent) that converts interactive card content intostructured human-readable text — consistent with how
text,post,image, and other messagetypes are already handled.
The output format is
<card title="..." subtitle="...">...</card>, with each card element typeserialised to a readable representation (markdown body, button links, table rows, chart summaries,
etc.).
Changes
events/im/message_receive.gomessage_type == "interactive"throughConvertInteractiveEventContentinstead ofreturning raw JSON
Contentfield description now that the interactive special-case is handled upstreamshortcuts/im/convert_lib/card_userdsl.go(new)ConvertInteractiveEventContent(rawContent, mentions)— entry point; extractsuser_dslstringfrom the event content envelope and delegates to the converter; falls back to
"[interactive card]"on malformed inputuserDslConverter— supports both card schema versions:schemafield): readsi18n_header.zh_cnor directheader, elements atroot
schema: "2.0"): readsheaderat root,body.elementsHandles 30+ element tags:
plain_text,lark_md,markdowndiv(text + fields + extra),column_set,column,hr,brimg/image,img_combination,audio,videobutton(URL / disabled / confirm),actions/action,overflowselect_static,multi_select_static,select_person,multi_select_person,input,date_picker,picker_date,picker_time,picker_datetime,checkertable,chart,form,collapsible_panel,interactive_containerperson,person_list,avatarnote,text_tag,select_img,repeat,fallback_textresolveAtMentions— replaces<at ...>tags in markdown content with@name(open_id);supports both quoted (
mention_key="k") and unquoted (mention_key=k) attribute formats tomatch real Lark event payloads, plus multi-mention (
ids=id1,id2,id3 mentions_key=k1,,k3);degrades gracefully to
@idwhen a mention key is absent from the mentions listshortcuts/im/convert_lib/card_userdsl_test.go(new)TestConvertInteractiveEventContent— invalid JSON, missing/empty/wrong-typeuser_dslallfall back to
"[interactive card]"; valid user-2 card renders<card title="...">body</card>TestConvertInteractiveEventContentMentions— quoted & unquotedmention_key/mentions_key,TestUserDslConverterSchema— user-1 (i18n_header), user-1 (direct header), user-2 schemas;empty card → fallback; title-only card → renders without body
TestUserDslConverterDispatch— table-driven, 30+ cases covering every element type routedthrough
convertElementTest Plan
make unit-testpassed (go test -race ./...)TestConvertInteractiveEventContent,TestConvertInteractiveEventContentMentions,TestUserDslConverterSchema,TestUserDslConverterDispatchwith 30+ sub-caseslark im receiveoutputs
<card title="...">text instead of raw JSONRelated Issues
Summary by CodeRabbit