mirror of
https://github.com/larksuite/cli.git
synced 2026-07-03 14:02:43 +08:00
docs(lark-im): reconcile slimmed skill and thinned references with main
Rebased onto main v1.0.54, which added IM content after this branch forked. Fold main's new facts into the slimmed/gotcha-only form and fix drift: - SKILL.md: compact the newly-merged chat.user_setting / chat.managers / chat.moderation API resources to the api_compact `action`(identity) form (consistent with the rest; regen-equivalent), and note the opt-in `--download-resources` flag on the three message-pulling shortcuts. - chat-search: fix stale `--sort-by` -> `--sort`, add `--chat-modes`, and fold the "`--sort` is always descending" caution (#1302/#1317). - chat-messages-list: note `--order` is the only sort axis (no field sort). - messages-send: split @mention by message type; interactive cards are not normalized and need card-native `<at>` syntax (#1419). - flag-cancel: document best-effort double-cancel (feed layer skipped with a stderr warning when chat type is undeterminable). - feed-group-list-item / query-item: p2p cards omit chat_name; resolve via chats/batch_query -> p2p_target_id -> contact lookup. - message-enrichment: add the `--download-resources` contract (merge_forward container-id 234003 trap, fail-silent isolation, no extra scope) (#1245). Docs only; no Go/--help/Desc changes.
This commit is contained in:
@@ -24,7 +24,7 @@ lark-cli im +chat-messages-list --chat-id oc_xxx --as user # GOOD: sender = rea
|
||||
|
||||
### Default message enrichment
|
||||
|
||||
The four message-pulling shortcuts auto-attach `reactions` (+ `update_time` for edited messages) — no separate `reactions.batch_query` (needs `im:message.reactions:read`); `--no-reactions` opts out. Contract: [`references/lark-im-message-enrichment.md`](references/lark-im-message-enrichment.md).
|
||||
The four message-pulling shortcuts auto-attach `reactions` (+ `update_time` for edited messages) — no separate `reactions.batch_query` (needs `im:message.reactions:read`); `--no-reactions` opts out. `+chat-messages-list` / `+messages-mget` / `+threads-messages-list` also accept `--download-resources` (opt-in, off by default) to fetch message binaries into `./lark-im-resources/`. Contract: [`references/lark-im-message-enrichment.md`](references/lark-im-message-enrichment.md).
|
||||
|
||||
### Flag Types
|
||||
|
||||
|
||||
@@ -65,7 +65,7 @@ lark-cli im +chat-messages-list --chat-id oc_xxx --as user # GOOD: sender = rea
|
||||
|
||||
### Default message enrichment
|
||||
|
||||
The four message-pulling shortcuts auto-attach `reactions` (+ `update_time` for edited messages) — no separate `reactions.batch_query` (needs `im:message.reactions:read`); `--no-reactions` opts out. Contract: [`references/lark-im-message-enrichment.md`](references/lark-im-message-enrichment.md).
|
||||
The four message-pulling shortcuts auto-attach `reactions` (+ `update_time` for edited messages) — no separate `reactions.batch_query` (needs `im:message.reactions:read`); `--no-reactions` opts out. `+chat-messages-list` / `+messages-mget` / `+threads-messages-list` also accept `--download-resources` (opt-in, off by default) to fetch message binaries into `./lark-im-resources/`. Contract: [`references/lark-im-message-enrichment.md`](references/lark-im-message-enrichment.md).
|
||||
|
||||
### Flag Types
|
||||
|
||||
@@ -103,18 +103,15 @@ lark-cli im <resource> <method> [flags] # 调用 API
|
||||
|
||||
### chat.user_setting
|
||||
|
||||
- `batch_query` — 批量查询当前用户在群内的个人偏好设置 (e.g. `is_muted` mutes normal messages, `is_mute_at_all` mutes @all messages); up to 10 chats per request. Identity: `user` only (`user_access_token`); the caller must be in each target chat.
|
||||
- `batch_update` — 批量更新当前用户在群内的个人偏好设置 (e.g. `is_muted` mutes normal messages, `is_mute_at_all` mutes @all messages); up to 10 chats per request. Identity: `user` only (`user_access_token`); the caller must be in each target chat.
|
||||
`batch_query`(user) · `batch_update`(user)
|
||||
|
||||
### chat.managers
|
||||
|
||||
- `add_managers` — 指定群管理员。Identity: supports `user` and `bot`; only the group owner can add managers; max 10 managers per chat (20 for super-large chats), and at most 5 bots per request.
|
||||
- `delete_managers` — 删除群管理员。Identity: supports `user` and `bot`; only the group owner can remove managers; max 50 users or 5 bots per request.
|
||||
`add_managers`(user/bot) · `delete_managers`(user/bot)
|
||||
|
||||
### chat.moderation
|
||||
|
||||
- `get` — 获取群成员发言权限。Identity: supports `user` and `bot`; the caller must be in the target chat and belong to the same tenant.
|
||||
- `update` — 更新群发言权限。Identity: supports `user` and `bot`; only the group owner (or creator bot with `im:chat:operate_as_owner`) can update; the caller must be in the chat.
|
||||
`get`(user/bot) · `update`(user/bot)
|
||||
|
||||
### messages
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ Supports both `--as user` (default) and `--as bot`. Auto-resolves the p2p `chat_
|
||||
- **`--user-id` (DM by open_id) is user-identity only — and the constraint is silent until you hit it.** The p2p-resolution endpoint requires user identity; with `--as bot` it errors. For bot identity, look up the p2p `chat_id` yourself and pass `--chat-id`.
|
||||
- **`P2P chat not found for this user`** means no DM exists *for the current identity* with that user — not a bad ID. Confirm the DM relationship under the identity you're calling as.
|
||||
- **Resolve a chat name → `chat_id` via [`+chat-search`](lark-im-chat-search.md) first**, then pass `--chat-id`. **Do NOT use `im chats search` or `+chat-list`** — those are not search APIs and won't locate the target.
|
||||
- **`--order` defaults to `desc`** (newest first); pass `--order asc` for chronological reading. (Note: the flag is `--order`, not `--sort`.)
|
||||
- **`--order` defaults to `desc`** (newest first); pass `--order asc` for chronological reading. (Note: the flag is `--order`, not `--sort`.) It is the **only** sort axis — messages are always ordered by creation time. There is no field sort: `--sort sender` (or any field) is rejected. If asked to group/sort by sender, fetch with `--order` and aggregate client-side, and say so (local post-processing, not a CLI/API sort).
|
||||
- **Image content is a placeholder, not bytes**: images render as `[Image: img_xxx]`; files/audio/video carry resource keys. Nothing downloads unless you pass `--download-resources` (writes to `./lark-im-resources/`) or use [`im +messages-resources-download`](lark-im-messages-resources-download.md).
|
||||
|
||||
## Thread expansion (`thread_id`)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
> **Prerequisite:** Read [`../lark-shared/SKILL.md`](../../lark-shared/SKILL.md) first for authentication, global parameters, and safety rules.
|
||||
|
||||
Maps to `lark-cli im +chat-search`. **Run `lark-cli im +chat-search --help` for the authoritative flag list (`--query` / `--member-ids` / `--search-types` / `--sort-by` / `--page-size` / `--page-token` / `--is-manager` / `--exclude-muted` / `--disable-search-by-user`), limits, and enums.** This file covers only what `--help` cannot.
|
||||
Maps to `lark-cli im +chat-search`. **Run `lark-cli im +chat-search --help` for the authoritative flag list (`--query` / `--member-ids` / `--search-types` / `--chat-modes` / `--sort` / `--page-size` / `--page-token` / `--is-manager` / `--exclude-muted` / `--disable-search-by-user`), limits, and enums.** This file covers only what `--help` cannot.
|
||||
|
||||
## Gotchas
|
||||
|
||||
@@ -11,6 +11,7 @@ Maps to `lark-cli im +chat-search`. **Run `lark-cli im +chat-search --help` for
|
||||
- `--query` containing `-` is auto-wrapped in quotes.
|
||||
- **On empty results, do NOT fall back to `+chat-list` / `GET /chats`** — list is not a search API (returns all chats unfiltered, won't locate the target). Refine the keyword or check visibility under the current identity instead.
|
||||
- Supports `--as user` (default) and `--as bot` (bot needs bot capability enabled).
|
||||
- **`--sort` is always descending** (`create_time` / `update_time` / `member_count`, high→low). There is no ascending option. If the user asks for "fewest first / ascending / 从少到多", tell them the search API doesn't support ascending and re-sort the fetched page client-side — do **NOT** invent `member_count_asc` or pass `asc` (rejected).
|
||||
|
||||
## `--exclude-muted` (user identity only)
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ Maps to `lark-cli im +feed-group-list-item`. **Run `lark-cli im +feed-group-list
|
||||
## Gotchas
|
||||
|
||||
- **`chat_name` enrichment is unconditional → needs a second scope.** A v1 feed card's `feed_id` is always a chat ID (`oc_xxx`), so the shortcut always issues a follow-up `chats/batch_query` and injects `chat_name` into each entry of **both** `items[]` and `deleted_items[]`. There is no single-scope, un-enriched path — so this needs `im:chat:read` **in addition to** `im:feed_group_v1:read` (vs. `+feed-group-list`, which needs only the read scope).
|
||||
- **Unresolvable cards silently omit `chat_name`** — a soft-deleted chat or one you can't see just lacks the field; the command still exits 0. Do not treat a missing `chat_name` as an error.
|
||||
- **Unresolvable cards silently omit `chat_name`** — a soft-deleted chat or one you can't see just lacks the field; the command still exits 0. Do not treat a missing `chat_name` as an error. **p2p (direct) cards also omit it** (the server returns an empty `name`; clients show the partner's display name instead) — if you need a label, fetch the chat via `chats/batch_query`, read `p2p_target_id`, and resolve it with a contact lookup.
|
||||
- **Dual-list response.** Like `+feed-group-list`, results split into `items[]` (live) and `deleted_items[]` (soft-deleted); `--page-all` merges both. Incremental-sync consumers must read both.
|
||||
- **`--page-token` wins over `--page-all`** when both are set — you get exactly that one page.
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ Maps to `lark-cli im +feed-group-query-item`. **Run `lark-cli im +feed-group-que
|
||||
|
||||
- **Lightweight ID lookup — prefer it over the list methods when you already hold the IDs.** Use this when you have the `feed_id`s (the `oc_xxx` you passed to `batch_add_item`); reserve `+feed-group-list-item` (paginated, heavier) for discovering IDs you don't have. **No pagination** for this method.
|
||||
- **`chat_name` enrichment is unconditional → needs a second scope.** Resolves `chat_name` for each card exactly as `+feed-group-list-item` does (follow-up `chats/batch_query`, injected into both `items[]` and `deleted_items[]`). So this needs `im:chat:read` **in addition to** `im:feed_group_v1:read`; there is no un-enriched path.
|
||||
- **Unresolvable cards silently omit `chat_name`** — soft-deleted or no-permission chats just lack the field; the command still exits 0.
|
||||
- **Unresolvable cards silently omit `chat_name`** — soft-deleted or no-permission chats just lack the field; the command still exits 0. **p2p (direct) cards also omit it** (server returns an empty `name`); to label one, fetch the chat via `chats/batch_query`, read `p2p_target_id`, and resolve it with a contact lookup.
|
||||
|
||||
## HELP-GAP — not yet in `--help`/schema; keep until CLI adds it
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ Maps to `lark-cli im +flag-cancel`. **Run `lark-cli im +flag-cancel --help` for
|
||||
## Gotchas
|
||||
|
||||
- **Default is double-cancel (both layers)**: omitting `--flag-type` best-effort cancels both the message-layer flag `(default, message)` and the feed-layer flag `(thread, feed)` or `(msg_thread, feed)`. The server treats cancel of a non-existent flag idempotently — no error — so double-cancel is safe even when only one layer has a flag.
|
||||
- **Feed-layer `item_type` is determined by `chat_mode`**: `topic` chat → `item_type=thread`; regular `group` chat → `item_type=msg_thread`. The double-cancel path auto-detects this (requires `im:chat:read`). When calling single-layer feed cancel with `--flag-type feed`, you must supply `--item-type` explicitly.
|
||||
- **Feed-layer `item_type` is determined by `chat_mode`**: `topic` chat → `item_type=thread`; regular `group` chat → `item_type=msg_thread`. The double-cancel path auto-detects this (requires `im:chat:read`). **Best-effort, not all-or-nothing**: the message layer is always removed; the feed layer is removed only when the chat type can be determined — otherwise a warning is printed on stderr and the feed layer is silently skipped (the command still exits 0). When calling single-layer feed cancel with `--flag-type feed`, you must supply `--item-type` explicitly.
|
||||
- **Idempotent**: repeated cancel calls on an already-unflagged message succeed silently.
|
||||
- **Do NOT call `+flag-list` for verification**: a success response means the flag was removed. Paginating `+flag-list` to confirm is expensive and unnecessary.
|
||||
- **Finding a message ID**: use `+messages-search --query "<keywords>"` to locate the message and extract `message_id`. Do NOT use `+flag-list` — it requires full pagination and won't reliably locate the message.
|
||||
|
||||
@@ -13,6 +13,15 @@ Cross-cutting behavior shared by the message-pulling shortcuts. `--help` documen
|
||||
- **Requires `im:message.reactions:read`.** Declared in each shortcut's scopes, so the pre-flight surfaces `missing_scope` before sending. Bots registered before this scope existed need an incremental authorization in the developer console (a user re-login picking up the scope is enough for user identity).
|
||||
- **High-N pulls are batched, not serialized.** Reaction lookups split into batches of ≤20 ids (server cap) dispatched with bounded concurrency (≤4 in flight), so e.g. 550 ids → 28 batches finish in a few round-trips, not tens of seconds. Don't add your own throttling/looping on top.
|
||||
|
||||
## Resource auto-download (`--download-resources`, opt-in)
|
||||
|
||||
`+chat-messages-list` / `+messages-mget` / `+threads-messages-list` accept `--download-resources` (**off by default** — omitted = no `resources` block and zero extra requests). When set, eligible resources (`image`/`file`/`audio`/`video`/`media` + post-embedded; **stickers excluded** — Feishu can't fetch them) download into `./lark-im-resources/`, and each message gains a `resources` array of `{message_id, key, type, local_path, size_bytes}`.
|
||||
|
||||
- **`merge_forward` trap**: for a resource inside a forwarded message, `message_id` is the **top-level container** id, not the sub-item's — the download endpoint rejects sub-item ids with `234003 File not in msg`. Thread replies each get their own block.
|
||||
- **Fail-silent isolation**: one resource that fails to download is flagged `"error": true` + a single stderr `warning: resource_download_failed: …`; the message and other resources are unaffected (exit 0).
|
||||
- Deduped by `(message_id, file_key)`, bounded concurrency (≤3), output confined to `./lark-im-resources/` (path-separator / `..` / absolute `file_key` rejected).
|
||||
- **No extra scope**: uses `im:message:readonly`, already declared by the listing commands; works under user and bot identity. For one-off fetches use [`+messages-resources-download`](lark-im-messages-resources-download.md).
|
||||
|
||||
## Thread-replies expansion caps (mget / chat-messages-list only)
|
||||
|
||||
Any returned message carrying a `thread_id` triggers a fetch of that thread's replies, attached as a `thread_replies` array on the host (distinct threads fetched with ≤4 concurrent). Two caps gate it:
|
||||
|
||||
@@ -31,10 +31,13 @@ For multi-line text, indentation, code blocks, or literal backslashes, use shell
|
||||
lark-cli im +messages-send --chat-id oc_xxx --text $'Build failed\nBranch: feature/x\nAction: check logs'
|
||||
```
|
||||
|
||||
## @Mention format (text / post)
|
||||
## @Mention format (differs by message type)
|
||||
|
||||
- Recommended: `<at user_id="ou_xxx">name</at>`; @all: `<at user_id="all"></at>`.
|
||||
- The shortcut normalizes `<at id=...>` / `<at open_id=...>` into `user_id`, but author your examples with `user_id`.
|
||||
The shortcut only normalizes mentions for `text` and `post`; **`interactive` card content is passed through verbatim**, so cards must use the card-native syntax — this asymmetry is the trap.
|
||||
|
||||
- **`text`**: `<at user_id="ou_xxx">name</at>` (inner name optional); @all: `<at user_id="all"></at>`. The shortcut also normalizes `<at id=...>` / `<at open_id=...>` into `user_id`, but author examples with `user_id`.
|
||||
- **`post`**: same inline form inside a `text`/`md` element, or a dedicated node `{"tag":"at","user_id":"ou_xxx"}` (`"all"` for everyone).
|
||||
- **`interactive` (card)**: NOT normalized — use card-native `<at>` inside a `lark_md`/`markdown` element: single `<at id=ou_xxx></at>`, multiple `<at ids=ou_xxx1,ou_xxx2></at>`, by email `<at email=user@example.com></at>`.
|
||||
|
||||
## Common mistakes (the non-obvious ones)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user