mirror of
https://github.com/larksuite/cli.git
synced 2026-07-07 00:55:53 +08:00
- Pull messages now auto-call im.reactions.batch_query and attach a reactions block (counts + details) to each message. Stops AI from misjudging "user already reacted" as "no response yet" and re-sending duplicate reactions. Server caps queries[] at 20 per call, so messages are split into batches of size <= 20. - Edited messages additionally surface update_time. The server echoes update_time == create_time for unedited messages too, so the field is only emitted when updated == true; otherwise every message output would look "edited". The value is read via an explicit string assertion + TrimSpace so empty strings are filtered properly (the previous `v != ""` was a no-op for non-string types). - All four message-pulling shortcuts (+messages-mget, +chat-messages-list, +messages-search, +threads-messages-list) get a --no-reactions opt-out flag for callers that want to skip the extra round-trip. - Each shortcut declares im:message.reactions:read on its UserScopes/BotScopes (or Scopes for the user-only search command) so the auth flow covers the new dependency. - Each shortcut's --dry-run output now lists the reactions/batch_query call (or omits it when --no-reactions is set), so callers can audit the full set of API calls before execution. - Warnings go through runtime.IO().ErrOut (forbidigo lint requires IOStreams over os.Stderr in shortcut code). - Duplicate message_id inputs (e.g. mget --message-ids om_a,om_a) attach the reactions block to every entry while still querying the API only once per distinct id. - EnrichReactions walks msg["thread_replies"] recursively, and mget/ chat-messages-list call it after ExpandThreadReplies, so replies receive reactions in the same batched call as their parent message. - When the batch_query call fails or returns per-message failures, the affected messages get reactions_error=true (mirroring the thread_replies_error flag from thread.go) so consumers can distinguish "fetch failed" from "no reactions exist" by reading stdout alone, without depending on the stderr warning channel. - lark-im skill docs: the default-enrichment contract lives in a standalone references/lark-im-message-enrichment.md so the generated SKILL.md can't strand it on regeneration. The four read references and the raw reactions API reference link to it, and the template source skill-template/domains/im.md carries a durable pointer. Change-Id: Ia9ea74b11945644262bb25c6503fb9b2003c6c98
54 lines
3.3 KiB
Markdown
54 lines
3.3 KiB
Markdown
## Core Concepts
|
|
|
|
- **Message**: A single message in a chat, identified by `message_id` (om_xxx). Supports types: text, post, image, file, audio, video, sticker, interactive (card), share_chat, share_user, merge_forward, etc.
|
|
- **Chat**: A group chat or P2P conversation, identified by `chat_id` (oc_xxx).
|
|
- **Thread**: A reply thread under a message, identified by `thread_id` (om_xxx or omt_xxx).
|
|
- **Reaction**: An emoji reaction on a message.
|
|
- **Flag**: A bookmark on a message or thread.
|
|
|
|
## Resource Relationships
|
|
|
|
```
|
|
Chat (oc_xxx)
|
|
├── Message (om_xxx)
|
|
│ ├── Thread (reply thread)
|
|
│ ├── Reaction (emoji)
|
|
│ └── Resource (image / file / video / audio)
|
|
└── Member (user / bot)
|
|
```
|
|
|
|
## Important Notes
|
|
|
|
### Identity and Token Mapping
|
|
|
|
- `--as user` means **user identity** and uses `user_access_token`. Calls run as the authorized end user, so permissions depend on both the app scopes and that user's own access to the target chat/message/resource.
|
|
- `--as bot` means **bot identity** and uses `tenant_access_token`. Calls run as the app bot, so behavior depends on the bot's membership, app visibility, availability range, and bot-specific scopes.
|
|
- If an IM API says it supports both `user` and `bot`, the token type changes who the operator is. The same API can succeed with one identity and fail with the other because owner/admin status, chat membership, tenant boundary, or app availability are checked against the current caller.
|
|
|
|
### Sender Name Resolution with Bot Identity
|
|
|
|
When using bot identity (`--as bot`) to fetch messages (e.g. `+chat-messages-list`, `+threads-messages-list`, `+messages-mget`), sender names may not be resolved (shown as open_id instead of display name). This happens when the bot cannot access the user's contact info.
|
|
|
|
**Root cause**: The bot's app visibility settings do not include the message sender, so the contact API returns no name.
|
|
|
|
**Solution**: Check the app's visibility settings in the Lark Developer Console — ensure the app's visible range covers the users whose names need to be resolved. Alternatively, use `--as user` to fetch messages with user identity, which typically has broader contact access.
|
|
|
|
### Default message enrichment (reactions / update_time)
|
|
|
|
The four message-pulling shortcuts (`+messages-mget`, `+chat-messages-list`, `+messages-search`, `+threads-messages-list`) automatically attach a `reactions` block and (for edited messages) `update_time` to each returned message — no separate `im.reactions.batch_query` call is needed. Pass `--no-reactions` to opt out. For the full contract (output shape, the `im:message.reactions:read` scope requirement, and the "missing field ≠ fetch failure" data rules), read [`references/lark-im-message-enrichment.md`](references/lark-im-message-enrichment.md).
|
|
|
|
### Card Messages (Interactive)
|
|
|
|
Card messages (`interactive` type) are not yet supported for compact conversion in event subscriptions. The raw event data will be returned instead, with a hint printed to stderr.
|
|
|
|
### Flag Types
|
|
|
|
Flags support two layers:
|
|
|
|
- **Message-layer flag**: `(ItemTypeDefault, FlagTypeMessage)` — regular message bookmark
|
|
- **Feed-layer flag**: `(ItemTypeThread/ItemTypeMsgThread, FlagTypeFeed)` — thread as feed-layer bookmark
|
|
|
|
Item types for feed-layer flags:
|
|
- **ItemTypeThread** (4) = thread in a topic-style chat
|
|
- **ItemTypeMsgThread** (11) = thread in a regular chat
|