Skip to content

feat(im): add +chat-list and --exclude-muted to filter muted chats#820

Open
shifengjuan-dev wants to merge 1 commit into
larksuite:mainfrom
shifengjuan-dev:feat/im-chats-filter-muted
Open

feat(im): add +chat-list and --exclude-muted to filter muted chats#820
shifengjuan-dev wants to merge 1 commit into
larksuite:mainfrom
shifengjuan-dev:feat/im-chats-filter-muted

Conversation

@shifengjuan-dev
Copy link
Copy Markdown
Contributor

@shifengjuan-dev shifengjuan-dev commented May 11, 2026

Summary

  • Add im +chat-list shortcut wrapping GET /open-apis/im/v1/chats (previously not exposed via lark-cli).
  • Add --exclude-muted to both +chat-search and +chat-list: client-side filter that calls POST /open-apis/im/v1/chat_user_setting/batch_get_mute_status after each page and drops is_muted=true chats.
  • Introduce shortcuts/im/mute_filter.go with pure helpers and an orchestrator (MaybeApplyMuteFilter) shared by both shortcuts.

Design highlights

  • Pure A (transparent reporting, no top-up). Filtered pages may be smaller than --page-size; the JSON output adds a filter sub-object with applied/skipped/fetched_count/returned_count/filtered_count/hint so AI/scripts can chain page_token.
  • Invariant: fetched_count == returned_count + filtered_count always holds.
  • Bot identity (--as bot): batch_get_mute_status is UAT-only, so the filter is skipped with filter.skipped=true, skip_reason="bot_identity_no_mute_data". All chats returned unfiltered.
  • --search-types public_not_joined alone: pre-skipped with skip_reason="all_non_member_search_types" (the batch call would 100% return not_a_member).
  • Non-member chats (e.g. default query containing public_not_joined results): silently retained, not counted in filtered_count; surfaced in the hint text only.
  • No request-body pollution: --exclude-muted never injects search_types or any other field into the search/list request. Verified via dry-run tests.
  • No client-side metrics: server-side BatchGetChatMuteStatus already has metrics (mute_status.go:60-62). CLI does not duplicate.

Output schema (only when --exclude-muted is set)

{
  "chats": [...],
  "filter": {
    "applied": "exclude_muted",
    "skipped": false,
    "fetched_count": 20,
    "returned_count": 19,
    "filtered_count": 1,
    "hint": "Filtered out 1 muted chat(s) on this page (19 remaining, including 2 non-member public group(s)); use --page-token to fetch more."
  }
}

Hint is shown in --format json (field) and --format pretty (line below summary). Not shown in --format table/ndjson/csv — consistent with the existing pagination hint behavior.

Test plan

  • go test ./shortcuts/im/... — passes
  • go build ./... — clean
  • go vet ./... — clean
  • +chat-list --dry-run — endpoint + params correct
  • +chat-search --query foo --exclude-muted --dry-run — request body unchanged, no search_types injection
  • +chat-search --search-types public_not_joined --exclude-muted --dry-runsearch_types present as user requested, no auto-injection
  • +chat-list --help exposes --exclude-muted with correct description
  • Live UAT call against tenant once batch_get_mute_status is GA (currently UAT-only)
  • Live --as bot call confirms filter.skipped=true with bot_identity_no_mute_data

Risks

  • batch_get_mute_status is currently UAT-only (TAT/bot rejected at the API gateway). The CLI handles this gracefully (bot identity skips the filter), but the API itself must be GA before this feature is broadly usable.
  • im:chat:read scope is assumed to cover chat_user_setting reads. If the gateway requires a separate scope, users will see 99991679/99991672 and we will need a follow-up to add the right scope.
  • Coupling to v2 search response shape: implementation reads meta_data.chat_id from each item; if the v2 search response schema changes the wrapping, the filter helper needs updating.

Spec docs

  • Design: docs/specs/2026-05-09-im-chats-filter-muted-design.md
  • Plan: docs/specs/2026-05-09-im-chats-filter-muted-plan.md

These reference the earlier exploration at docs/specs/2026-04-28-search-filter-muted-chats-design.md — this PR is the CLI-side variant (option D — pure transparent reporting) that does not block on the search-team-side option B.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Added +chat-list to list group chats with sorting, pagination, and user-ID type selection.
    • Added --exclude-muted (user identity only) to +chat-search and +chat-list to client-side filter muted/DND chats and surface a filter hint.
  • Documentation

    • Added docs for +chat-list and updated +chat-search docs with mute-filter behavior, JSON filter shape, and usage examples.
  • Tests

    • Added comprehensive tests covering list/search dry-run, validate bounds, and mute-filter behavior and hints.

Review Change Stack

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 11, 2026

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 a new +chat-list IM shortcut and implements a reusable client-side --exclude-muted mute-filtering system used by both chat-search and chat-list; includes validation, DryRun behavior, comprehensive tests, and updated documentation.

Changes

IM Chat List and Mute Filtering

Layer / File(s) Summary
Mute Filter Data Model and Constants
shortcuts/im/mute_filter.go
MuteFilterMeta type with applied/skipped status, skip reasons, and counters; batch API path and max batch size constants.
Mute Filter Building Blocks
shortcuts/im/mute_filter.go
BuildMuteFilterHint, BuildBatchGetMuteStatusBody, ParseBatchGetMuteStatusResponse, ExtractChatIDs, MuteFilterMetaToMap, and FetchMuteStatus wrapper with validation and error context.
Core Filter Logic and Orchestration
shortcuts/im/mute_filter.go
ApplyMuteFilter removes muted rows while preserving unknown/absent IDs and counters; MaybeApplyMuteFilter orchestrates skip conditions and batch fetch/apply/hint flow.
Mute Filter Unit Tests
shortcuts/im/mute_filter_test.go
Comprehensive tests for hint generation, batch request/response parsing, filter semantics and counters, ID extraction, meta mapping, orchestrator branches, and FetchMuteStatus edge cases.
Chat List Shortcut Implementation
shortcuts/im/im_chat_list.go
ImChatList shortcut with --user-id-type, --sort-type, --page-size (1–100), --page-token, and --exclude-muted; validation, DryRun, param builder, Execute with optional mute filtering, and output rendering including filter hint.
Chat List Validation and Tests
shortcuts/im/im_chat_list_test.go
Tests for Cobra-backed runtime context, buildChatListParams defaults and overrides, page-size bounds validation, and DryRun endpoint/param inclusion.
Chat Search Enhancement for Mute Filtering
shortcuts/im/im_chat_search.go
Adds --exclude-muted flag, detects public_not_joined pre-skip, applies MaybeApplyMuteFilter to search results, conditionally adds filter metadata to output, and prints filter hints; updates comments.
Shortcut Dry-Run and Helper Tests
shortcuts/im/builders_test.go
DryRun tests verifying ImChatSearch (exclude-muted) and ImChatList request shapes; TestDetectAllNonMemberPreSkip coverage.
Shortcut Registration
shortcuts/im/shortcuts.go, shortcuts/im/helpers_test.go
Registers ImChatList in Shortcuts() and updates test ordering expectation.
Skills and Reference Documentation
skills/lark-im/SKILL.md, skills/lark-im/references/*
Adds +chat-list reference page, documents --exclude-muted workflow and filter metadata, updates chat-search docs and cross-references, and refreshes SKILL front-matter.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Suggested reviewers

  • YangJunzhou-01
  • liangshuo-1

Poem

🐰 A fluffy chat command hops into view,
Filtering mutes as the cool bunnies do,
I fetch IDs, drop whispers, keep the known,
Print hints and pages as the list is shown,
Hop, hop — your chats are clearer now!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 45.95% 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 and concisely summarizes the two main changes: adding a new +chat-list shortcut and introducing the --exclude-muted flag to filter muted chats.
Description check ✅ Passed The PR description comprehensively covers all required template sections: Summary, Changes, Test Plan, and Related Issues. It includes detailed design rationale, output schema, test verification results, risks, and spec document references.
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 and usage tips.

@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 May 11, 2026
@shifengjuan-dev shifengjuan-dev force-pushed the feat/im-chats-filter-muted branch 5 times, most recently from 883d5bf to 7b081dc Compare May 13, 2026 09:49
Change-Id: I22221ac5835667f58cbd40b34de75825d2445d1c
@shifengjuan-dev shifengjuan-dev force-pushed the feat/im-chats-filter-muted branch from 7b081dc to cc80539 Compare May 13, 2026 10:35
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.

1 participant