Skip to content

feat: support card action trigger#1528

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

feat: support card action trigger#1528
YangJunzhou-01 merged 1 commit into
larksuite:mainfrom
91-enjoy:feat/card_action_trigger

Conversation

@91-enjoy

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

Copy link
Copy Markdown
Contributor

Summary

Add support for card.action.trigger, the event fired when a user interacts with an
interactive card (button click, form submit, dropdown, checkbox, input, date picker, etc.).
The handler flattens the V2 envelope into a structured output and auto-fetches the original
card content (card_content) at consume time, enabling a complete read-then-update workflow
without extra API calls.

Changes

  • Add events/im/card_action.go: processCardAction handler + CardActionTriggerOutput
    struct covering all interaction fields (token, action_tag, action_value, form_value,
    input_value, option, options, checked, timezone, card_content)
  • Register card.action.trigger in events/im/register.go with SubTypeCallback and
    SingleConsumer: true (token scoped to one updater, max 2 uses in 30 min)
  • Add skills/lark-im/references/lark-im-card-action-reply.md: reference for the
    card update workflow, action_tag decision table, Card 1.0/2.0 handling, and jq recipes
  • Update skills/lark-event and skills/lark-im skill docs to catalog the new event key
    and cross-link the card-action-reply reference

Test Plan

  • make unit-test passed
  • Added TestProcessCardAction_* with table-driven cases: button, form submit,
    multi-select, input, date picker, malformed payload passthrough,
    card_content fetch success / error-code / network failure / missing message_id
  • Manual verification: lark-cli event consume card.action.trigger --as bot
    correctly receives and displays card interaction payloads

Related Issues

N/A

Summary by CodeRabbit

  • New Features
    • Enabled the interactive card callback event card.action.trigger, covering buttons, form submits, inputs, multi-selects, and date pickers.
    • Event output is provided in a flattened, action-oriented format, with optional auto-fetched card_content when open_message_id is present.
  • Documentation
    • Added a dedicated reference for card.action.trigger, including action-tag field population rules and the delayed card update workflow.
    • Updated IM skill and event key catalogs to include the new callback.
  • Tests
    • Added unit tests for event registration, payload parsing across action types, malformed-payload tolerance, and card-content fetch outcomes.

@coderabbitai

coderabbitai Bot commented Jun 22, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds support for the card.action.trigger IM event with payload flattening, optional card content lookup, event registration, targeted tests, and documentation updates across the IM and event skill references.

Changes

card.action.trigger Event Support

Layer / File(s) Summary
CardActionTriggerOutput schema and processCardAction implementation
events/im/card_action.go
Defines the flattened output struct and implements payload unmarshalling, JSON-string serialization of action/form/value maps, comma-joining of options, and non-blocking card content enrichment via fetchCardUserDSL calling the IM messages GET API.
Event key registration and processing tests
events/im/register.go, events/im/card_action_test.go
Adds the card.action.trigger key definition with its schema, handler, scope, auth, and console event requirement, and covers registration plus action parsing, malformed payload handling, and card content fetch outcomes.
Documentation and skill reference updates
skills/lark-im/references/lark-im-card-action-reply.md, skills/lark-im/references/lark-im-messages-send.md, skills/lark-im/SKILL.md, skills/lark-event/references/lark-event-im.md, skills/lark-event/SKILL.md
Adds the card.action.trigger reference page with output fields, action_tag rules, delayed update workflow, CLI examples, and gotchas; updates IM event key catalog and shape documentation; cross-links from messages-send and both skill pages.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related issues

Suggested labels

feature

Suggested reviewers

  • YangJunzhou-01

Poem

🐇 A card clicked once, then fields unfurled,
JSON strings and options twirled.
The rabbit hops through callback light,
Fetches card content, swift and bright.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 11.76% 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 is concise and accurately summarizes the main change: adding support for card action trigger events.
Description check ✅ Passed The description matches the template with Summary, Changes, Test Plan, and Related Issues sections filled out.
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

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.

@github-actions github-actions Bot added domain/im PR touches the im domain size/L Large or sensitive change across domains or core paths labels Jun 22, 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.

Actionable comments posted: 2

🧹 Nitpick comments (3)
skills/lark-im/references/lark-im-card-action-reply.md (1)

103-103: 🧹 Nitpick | 🔵 Trivial | 💤 Low value

Add language specifier to fenced code block.

Line 103's code block opening should declare bash since the content is a bash workflow outline with numbered steps.

📝 Proposed fix
-```
+```bash
 1. Read action fields to understand what the user did:
🤖 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 `@skills/lark-im/references/lark-im-card-action-reply.md` at line 103, The
opening code fence for the bash workflow outline needs to include the language
specifier. Locate the opening triple backticks that precedes the numbered steps
starting with "1. Read action fields to understand what the user did:" and add
bash as the language identifier immediately after the opening triple backticks
to properly declare the code block language.
events/im/card_action_test.go (2)

15-29: 🧹 Nitpick | 🔵 Trivial | ⚡ Quick win

Strengthen registration contract assertions in TestCardActionTriggerRegistered.

Line 15 currently validates only presence/basic fields. Please also assert the key contract fields (SubscriptionType, SingleConsumer, AuthTypes, RequiredConsoleEvents, and schema type) so registry regressions are caught.

Proposed test hardening
 func TestCardActionTriggerRegistered(t *testing.T) {
 	def, ok := event.Lookup("card.action.trigger")
 	if !ok {
 		t.Fatal("card.action.trigger should be registered via Keys()")
 	}
@@
 	if len(def.Scopes) == 0 {
 		t.Error("Scopes must not be empty")
 	}
+	if def.SubscriptionType != event.SubTypeCallback {
+		t.Errorf("SubscriptionType = %v, want %v", def.SubscriptionType, event.SubTypeCallback)
+	}
+	if !def.SingleConsumer {
+		t.Error("SingleConsumer must be true")
+	}
+	if len(def.AuthTypes) != 1 || def.AuthTypes[0] != "bot" {
+		t.Errorf("AuthTypes = %v, want [bot]", def.AuthTypes)
+	}
+	if len(def.RequiredConsoleEvents) != 1 || def.RequiredConsoleEvents[0] != "card.action.trigger" {
+		t.Errorf("RequiredConsoleEvents = %v", def.RequiredConsoleEvents)
+	}
 }
🤖 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 `@events/im/card_action_test.go` around lines 15 - 29, In the
TestCardActionTriggerRegistered function, add additional assertions to validate
the key contract fields of the event definition. After the existing checks for
Schema.Custom, Process, and Scopes, add new error checks that assert the
presence and correctness of SubscriptionType, SingleConsumer, AuthTypes,
RequiredConsoleEvents, and the schema type itself on the def variable to ensure
registry regressions are caught.

292-295: 🧹 Nitpick | 🔵 Trivial | ⚡ Quick win

MessageGetSuccess should assert exact payload propagation, not just non-empty content.

At Line 292, CardContent != "" can pass even when the returned content is wrong/truncated. Assert equality to cardContent and record call args in mockAPIClient to verify the fetch request contract too.

Proposed assertion upgrade
 type mockAPIClient struct {
 	resp    string
 	errResp bool
+	lastMethod string
+	lastPath   string
 }
 
-func (m *mockAPIClient) CallAPI(_ context.Context, _, _ string, _ interface{}) (json.RawMessage, error) {
+func (m *mockAPIClient) CallAPI(_ context.Context, method, path string, _ interface{}) (json.RawMessage, error) {
+	m.lastMethod = method
+	m.lastPath = path
 	if m.errResp {
 		return nil, context.DeadlineExceeded
 	}
 	return json.RawMessage(m.resp), nil
 }
@@
 	out := runCardAction(t, payload, mock)
 
-	if out.CardContent == "" {
-		t.Error("CardContent should not be empty when message get succeeds")
+	if out.CardContent != cardContent {
+		t.Errorf("CardContent mismatch:\n got: %q\nwant: %q", out.CardContent, cardContent)
+	}
+	if mock.lastMethod == "" || mock.lastPath == "" {
+		t.Error("message-get API should be invoked on success path")
 	}
 }

Also applies to: 398-408

🤖 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 `@events/im/card_action_test.go` around lines 292 - 295, In the
MessageGetSuccess test function, replace the assertion that checks if
CardContent is non-empty with an exact equality check comparing out.CardContent
to the expected cardContent variable. Additionally, add assertions on the
mockAPIClient to record and verify the actual fetch request arguments passed
during the test execution, ensuring the complete payload contract is validated
rather than just checking for non-empty content. Apply the same fix to the
related test code mentioned at lines 398-408.
🤖 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 `@events/im/card_action.go`:
- Line 31: The Checked field has the omitempty tag in its struct JSON tag, which
causes false values to be omitted from the JSON output, making it impossible for
consumers to distinguish between an unchecked checkbox and a missing field.
Remove the omitempty tag from the Checked field struct tag (located in the
card_action.go file) so that explicit false values are included in the JSON
serialization. This same issue applies to all three occurrences of the Checked
field mentioned in the comment, so ensure all instances are updated
consistently.
- Around line 104-105: The messageID variable is being directly concatenated
into the URL path without proper encoding, which can cause malformed requests if
messageID contains special characters. Use Go's url.PathEscape function to
encode the messageID before inserting it into the path string in the path
construction that builds the "/open-apis/im/v1/messages/" endpoint. Apply the
escaping to messageID before the string concatenation to ensure all reserved
characters are properly encoded.

---

Nitpick comments:
In `@events/im/card_action_test.go`:
- Around line 15-29: In the TestCardActionTriggerRegistered function, add
additional assertions to validate the key contract fields of the event
definition. After the existing checks for Schema.Custom, Process, and Scopes,
add new error checks that assert the presence and correctness of
SubscriptionType, SingleConsumer, AuthTypes, RequiredConsoleEvents, and the
schema type itself on the def variable to ensure registry regressions are
caught.
- Around line 292-295: In the MessageGetSuccess test function, replace the
assertion that checks if CardContent is non-empty with an exact equality check
comparing out.CardContent to the expected cardContent variable. Additionally,
add assertions on the mockAPIClient to record and verify the actual fetch
request arguments passed during the test execution, ensuring the complete
payload contract is validated rather than just checking for non-empty content.
Apply the same fix to the related test code mentioned at lines 398-408.

In `@skills/lark-im/references/lark-im-card-action-reply.md`:
- Line 103: The opening code fence for the bash workflow outline needs to
include the language specifier. Locate the opening triple backticks that
precedes the numbered steps starting with "1. Read action fields to understand
what the user did:" and add bash as the language identifier immediately after
the opening triple backticks to properly declare the code block language.
🪄 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: fe3ff40f-9903-47c9-9680-46399705491f

📥 Commits

Reviewing files that changed from the base of the PR and between bba13cf and c1edb4f.

📒 Files selected for processing (8)
  • events/im/card_action.go
  • events/im/card_action_test.go
  • events/im/register.go
  • skills/lark-event/SKILL.md
  • skills/lark-event/references/lark-event-im.md
  • skills/lark-im/SKILL.md
  • skills/lark-im/references/lark-im-card-action-reply.md
  • skills/lark-im/references/lark-im-messages-send.md

Comment thread events/im/card_action.go Outdated
Comment thread events/im/card_action.go
@91-enjoy 91-enjoy force-pushed the feat/card_action_trigger branch from c1edb4f to 9b65b37 Compare June 22, 2026 06:50

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

Actionable comments posted: 1

🤖 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 `@skills/lark-im/references/lark-im-card-action-reply.md`:
- Line 103: The fenced code block starting at line 103 in the markdown file is
missing a language specifier. Since the content contains procedural workflow
steps rather than executable code, add a language identifier (such as `text` or
`plaintext`) immediately after the opening triple backticks on line 103 to
properly denote the code block format. Alternatively, you may remove the code
fence markers entirely and format the content as a numbered list if the
procedural steps are better represented without code block formatting.
🪄 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: 066fafc9-9b76-4667-b0f4-97b18153a22a

📥 Commits

Reviewing files that changed from the base of the PR and between c1edb4f and 9b65b37.

📒 Files selected for processing (8)
  • events/im/card_action.go
  • events/im/card_action_test.go
  • events/im/register.go
  • skills/lark-event/SKILL.md
  • skills/lark-event/references/lark-event-im.md
  • skills/lark-im/SKILL.md
  • skills/lark-im/references/lark-im-card-action-reply.md
  • skills/lark-im/references/lark-im-messages-send.md
✅ Files skipped from review due to trivial changes (4)
  • skills/lark-im/references/lark-im-messages-send.md
  • skills/lark-event/references/lark-event-im.md
  • skills/lark-event/SKILL.md
  • skills/lark-im/SKILL.md
🚧 Files skipped from review as they are similar to previous changes (3)
  • events/im/register.go
  • events/im/card_action.go
  • events/im/card_action_test.go

Comment thread skills/lark-im/references/lark-im-card-action-reply.md
@github-actions

github-actions Bot commented Jun 23, 2026

Copy link
Copy Markdown

🚀 PR Preview Install Guide

🧰 CLI update

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

🧩 Skill update

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

@91-enjoy 91-enjoy force-pushed the feat/card_action_trigger branch 3 times, most recently from fce0118 to 828e73b Compare June 24, 2026 09:38
Change-Id: I2fe266cefa75b209ce293f26f2993291df11037f
@91-enjoy 91-enjoy force-pushed the feat/card_action_trigger branch from 828e73b to a5e8a7d Compare June 24, 2026 12:41
@YangJunzhou-01 YangJunzhou-01 merged commit 3f9ace8 into larksuite:main Jun 24, 2026
18 checks passed
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/L Large or sensitive change across domains or core paths

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants