Skip to content

feat: resolve @user name and open_id from mentions in card format#1218

Merged
YangJunzhou-01 merged 1 commit into
larksuite:mainfrom
91-enjoy:feat/card_message_format
Jun 2, 2026
Merged

feat: resolve @user name and open_id from mentions in card format#1218
YangJunzhou-01 merged 1 commit into
larksuite:mainfrom
91-enjoy:feat/card_message_format

Conversation

@91-enjoy

@91-enjoy 91-enjoy commented Jun 2, 2026

Copy link
Copy Markdown
Contributor

Change-Id: I00f846d76482adba315d07361c35909b71ca74c7

Summary

Interactive card messages (msg_type: interactive) can contain @user elements in their card
body. The json_attachment.at_users field stores resolved user info, but the user_id there is
the sender-side platform user_id — not the reading app's canonical open_id. When the backend
populates a mention_key on each at_users entry, it signals that the API-level mentions[]
array carries a more authoritative open_id and display name for the reading context. This PR adds
support for this two-level lookup: it threads the raw mentions[] array into the card converter,
indexes it by mention_key for O(1) access, and renders the canonical open_id + display name
whenever the link is resolvable. All existing fallback paths (no mention_key, nil mentions) are
preserved without behavioral change.

Changes

content_convert.go

  • Add Mentions []interface{} field to ConvertContext
  • Populate it in FormatEventMessage and FormatMessageItem so the card converter can access the
    raw API mentions array alongside the existing MentionMap

card.go

  • Change signature convertCard(raw)convertCard(raw, mentions []interface{}) and pass
    mentions when the message contains a json_card
  • Add buildMentionsByKey(mentions) helper: produces a map[string]map[string]interface{} keyed
    by mention.key for O(1) lookup inside convertAt
  • Add mentionsByKey field to cardConverter; populate it before rendering begins
  • In convertAt: when at_users[key].mention_key is non-empty, look up the mention and use
    mention.name as the display name and mention.id (extracted via extractMentionOpenId) as the
    open_id
  • Updated @user render output:
    • Was: @Name (no ID shown)
    • Now (mention resolved): @Name(ou_xxx) — shows canonical open_id
    • Now (no mention_key, fallback): @Name(origKey) — shows the card element's at key
  • Fix json_attachment handling in convertCard: previously only accepted a JSON string; now
    also handles a pre-parsed cardObj value via a type switch

card_test.go

  • Update two existing TestConvertCard call sites to pass nil as the new mentions argument
  • Add TestConvertAtWithMentions with four cases:
    1. Mention resolved → @Name(ou_xxx)
    2. No mention_key@Name(user_id:xxx) (legacy path, unchanged)
    3. mention_key present but mentionsByKey nil → graceful degradation to at_users data
    4. Partial: name resolved from mention but open_id absent → name-only update, no label suffix

Test Plan

  • make unit-test passed
  • TestConvertAtWithMentions covers the four resolution paths above
  • Manual: receive or replay an interactive card containing @user, confirm
    lark im chat history renders @Name(ou_xxx) with the correct open_id

Related Issues

N/A

Summary by CodeRabbit

Release Notes

  • New Features

    • Interactive cards now properly resolve @mentions using provided mention data to display canonical user information, including names and IDs.
    • Enhanced @ label formatting in interactive cards for both concise and detailed display modes, with intelligent fallback when mention data is unavailable.
  • Tests

    • Added comprehensive test coverage for mention resolution behavior in interactive cards.

@coderabbitai

coderabbitai Bot commented Jun 2, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: f21e9ceb-3d58-4116-bc86-2ebf80216820

📥 Commits

Reviewing files that changed from the base of the PR and between 22dfb93 and 0a0caff.

📒 Files selected for processing (5)
  • shortcuts/im/convert_lib/card.go
  • shortcuts/im/convert_lib/card_test.go
  • shortcuts/im/convert_lib/content_convert.go
  • shortcuts/im/convert_lib/merge.go
  • shortcuts/im/convert_lib/merge_test.go
✅ Files skipped from review due to trivial changes (1)
  • shortcuts/im/convert_lib/merge_test.go
🚧 Files skipped from review as they are similar to previous changes (2)
  • shortcuts/im/convert_lib/content_convert.go
  • shortcuts/im/convert_lib/card_test.go

📝 Walkthrough

Walkthrough

Interactive card rendering now resolves @user mentions using API-provided mention data. The mentions flow through ConvertContext, get indexed by cardConverter for O(1) lookups, and enable convertAt to resolve display names and IDs from canonical mention data rather than relying solely on original identifiers.

Changes

Mention-aware interactive card rendering

Layer / File(s) Summary
Data flow - ConvertContext mentions field
shortcuts/im/convert_lib/content_convert.go
ConvertContext gains a Mentions field to carry raw API mention data; FormatEventMessage and FormatMessageItem populate this field when constructing context for card content conversion.
Card conversion entry point
shortcuts/im/convert_lib/card.go
Convert now passes mentions into convertCard; convertCard parses json_attachment whether it arrives as JSON string or object, then populates mentionsByKey when mentions are present.
Mention indexing infrastructure
shortcuts/im/convert_lib/card.go
New buildMentionsByKey helper creates a lookup map keyed by mention key; cardConverter struct adds mentionsByKey field to support O(1) mention resolution during element rendering.
@mention rendering with resolution
shortcuts/im/convert_lib/card.go
convertAt now uses mention_key from at_users to resolve canonical display name and open-id from indexed mentions, adjusting output formatting (user_id vs open_id labels) based on render mode and data source.
Testing mention resolution
shortcuts/im/convert_lib/card_test.go, shortcuts/im/convert_lib/merge_test.go
TestConvertCard updated for new convertCard signature; new TestConvertAtWithMentions and TestFormatMergeForwardSubTreeInteractiveCardUsesMentions validate mention resolution across modes and merge-forward subtree formatting.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

🐰 I nibbled keys and built a map,
Hopped through cards with a little tap—
Now every @ finds its name,
No more mystery, no more game.
Hooray for mentions on the map!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: adding mention resolution support to render @user names and open_ids from the API-provided mentions array in card format.
Description check ✅ Passed The description comprehensively covers all required sections: summary explains the motivation, changes detail modifications across four files, test plan confirms unit tests and manual verification, and related issues are addressed.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
⚔️ Resolve merge conflicts
  • Resolve merge conflict in branch feat/card_message_format

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions github-actions Bot added domain/im PR touches the im domain size/M Single-domain feat or fix with limited business impact labels Jun 2, 2026

@coderabbitai coderabbitai 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.

🧹 Nitpick comments (1)
shortcuts/im/convert_lib/card_test.go (1)

28-42: ⚡ Quick win

Add one end-to-end card-conversion case for mention resolution.

These tests cover convertAt directly, but the new feature also depends on convertCard forwarding mentions and on the new json_attachment object branch. A regression in either layer would still pass here. Please add a case that calls convertCard(raw, mentions) with an object-valued json_attachment and asserts the rendered @... output.

Also applies to: 246-313

🤖 Prompt for 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.

In `@shortcuts/im/convert_lib/card_test.go` around lines 28 - 42, Add an
end-to-end test that verifies convertCard forwards mentions and handles
object-valued json_attachment: construct a rawCard string that includes a
json_card (with body text or element that will reference a mention id) and a
json_attachment object mapping that id to a person name, then call
convertCard(rawCard, mentions) where mentions is the map you expect convertCard
to forward (or nil if convertCard should use json_attachment), and assert the
output contains the rendered `@Name` (use the same pattern as existing assertions
in TestConvertCard). Reference convertCard, convertAt, json_attachment and
mentions to ensure the test exercises the mention-resolution path through
convertCard.
🤖 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.

Nitpick comments:
In `@shortcuts/im/convert_lib/card_test.go`:
- Around line 28-42: Add an end-to-end test that verifies convertCard forwards
mentions and handles object-valued json_attachment: construct a rawCard string
that includes a json_card (with body text or element that will reference a
mention id) and a json_attachment object mapping that id to a person name, then
call convertCard(rawCard, mentions) where mentions is the map you expect
convertCard to forward (or nil if convertCard should use json_attachment), and
assert the output contains the rendered `@Name` (use the same pattern as existing
assertions in TestConvertCard). Reference convertCard, convertAt,
json_attachment and mentions to ensure the test exercises the mention-resolution
path through convertCard.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: b66da286-0d1b-4c56-b425-ef83f19ac220

📥 Commits

Reviewing files that changed from the base of the PR and between 925ae5e and 22dfb93.

📒 Files selected for processing (3)
  • shortcuts/im/convert_lib/card.go
  • shortcuts/im/convert_lib/card_test.go
  • shortcuts/im/convert_lib/content_convert.go

@91-enjoy
91-enjoy force-pushed the feat/card_message_format branch 2 times, most recently from 0a0caff to c8ddaf6 Compare June 2, 2026 11:57
@github-actions

github-actions Bot commented Jun 2, 2026

Copy link
Copy Markdown

🚀 PR Preview Install Guide

🧰 CLI update

npm i -g https://pkg.pr.new/larksuite/cli/@larksuite/cli@b9e6a08535635e411ab0c9433cb92a27b7805945

🧩 Skill update

npx skills add 91-enjoy/cli#feat/card_message_format -y -g

Change-Id: I00f846d76482adba315d07361c35909b71ca74c7
@91-enjoy
91-enjoy force-pushed the feat/card_message_format branch from c8ddaf6 to b9e6a08 Compare June 2, 2026 12:32
@codecov

codecov Bot commented Jun 2, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 77.27273% with 10 lines in your changes missing coverage. Please review.
✅ Project coverage is 69.21%. Comparing base (0aa9e96) to head (b9e6a08).
⚠️ Report is 2 commits behind head on main.

Files with missing lines Patch % Lines
shortcuts/im/convert_lib/card.go 78.04% 8 Missing and 1 partial ⚠️
shortcuts/im/convert_lib/content_convert.go 50.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1218      +/-   ##
==========================================
+ Coverage   69.19%   69.21%   +0.01%     
==========================================
  Files         634      634              
  Lines       59482    59517      +35     
==========================================
+ Hits        41161    41194      +33     
- Misses      15007    15009       +2     
  Partials     3314     3314              

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@YangJunzhou-01
YangJunzhou-01 merged commit 6d7f8ba into larksuite:main Jun 2, 2026
17 checks passed
@liangshuo-1 liangshuo-1 mentioned this pull request Jun 2, 2026
1 task
tuxedomm pushed a commit to zhumiaoxin/cli that referenced this pull request Jun 6, 2026
Interactive card messages (msg_type: interactive) can contain @user elements in their card
body. The json_attachment.at_users field stores resolved user info, but the user_id there is
the sender-side platform user_id — not the reading app's canonical open_id. When the backend
populates a mention_key on each at_users entry, it signals that the API-level mentions[]
array carries a more authoritative open_id and display name for the reading context. This PR adds
support for this two-level lookup: it threads the raw mentions[] array into the card converter,
indexes it by mention_key for O(1) access, and renders the canonical open_id + display name
whenever the link is resolvable. All existing fallback paths (no mention_key, nil mentions) are
preserved without behavioral change.

Change-Id: I00f846d76482adba315d07361c35909b71ca74c7
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

domain/im PR touches the im domain size/M Single-domain feat or fix with limited business impact

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants