Documentation
¶
Overview ¶
Package chatmsg holds the shared, read-only projection helpers for DingTalk message-list responses (list_individual_chat_message, list_conversation_message_v2, search_at_me_message, search_messages_by_keyword, list_topic_replies, …). Several shortcuts reshape those raw responses into a clean speaker/text/time list; centralising the fiddly bits here keeps them consistent and fixed in one place:
- Sender: the display name lives under the bare "sender" key, forwarded entries carry the literal string "null", and some responses nest the speaker in a {name:…} object — all handled here.
- Text: out-of-office auto-replies / cards arrive as raw rich-content JSON, and card/robot messages arrive as undecryptable ciphertext; CleanText renders the former to readable text and marks the latter, WITHOUT ever rewriting ordinary text that merely contains a JSON fragment.
- Forwarded: a forwarded chat record ("聊天记录") hides its real per-message bodies in forwardMessages while the top-level content is a lossy summary.
Index ¶
- func ApplyMessagePagination(payload, data map[string]any, messages []map[string]any, direction string)
- func ApplyPagination(payload, data map[string]any)
- func CleanText(s string) string
- func ConversationID(m map[string]any) any
- func CreateTime(m map[string]any) any
- func Forwarded(m map[string]any, project func(map[string]any) map[string]any) []map[string]any
- func IsEncrypted(s string) bool
- func MessageID(m map[string]any) any
- func MessageType(m map[string]any) any
- func Pagination(data map[string]any) map[string]any
- func QuotedMessage(m map[string]any) map[string]any
- func Reactions(m map[string]any) map[string]any
- func Resources(m map[string]any) []map[string]any
- func Sender(m map[string]any) any
- func Text(m map[string]any) any
- func ThreadID(m map[string]any) any
- func UpdateTime(m map[string]any) any
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func ApplyMessagePagination ¶
func ApplyMessagePagination(payload, data map[string]any, messages []map[string]any, direction string)
ApplyMessagePagination publishes message-list completeness without claiming the lower response's nextCursor is a valid CLI input. DingTalk's executable message-list contract paginates with the boundary message createTime, so the resume object uses exactly that accepted parameter.
func ApplyPagination ¶
ApplyPagination carries lower-layer completeness facts into a projected Shortcut payload. It intentionally preserves cursor values only in the command output (where callers need them to continue); audit reports redact those values and retain only their presence.
func CleanText ¶
CleanText makes a message body human-readable WITHOUT ever rewriting ordinary text. It only transforms a body that is a genuine DingTalk structured message:
- Encrypted card/robot ciphertext (base64 + "||v||t||len" trailer) → a clear "[加密消息]" marker instead of the raw base64.
- A rich-content card (out-of-office auto-reply, link/preview card, …) whose lines include at least one recognised rich-content block → the readable text extracted from those blocks, with the card's decorative JSON lines and "empty" placeholders dropped.
Crucially, if NO line is a recognised rich-content block (e.g. ordinary text that merely embeds a `{"approved":false}` fragment), the original string is returned verbatim — a JSON line is never silently dropped.
func ConversationID ¶
ConversationID preserves the stable conversation identity carried by list and search responses.
func CreateTime ¶
CreateTime reads a message's create/send time under whichever candidate key is present, returning the raw value.
func Forwarded ¶
Forwarded projects the nested messages of a forwarded chat record. The caller supplies its own per-message projection so each command keeps its own row shape; project is applied recursively, so multi-level forwards expand too.
func IsEncrypted ¶
IsEncrypted reports whether a message body is a raw DingTalk encrypted-message ciphertext: a base64 blob (DingTalk wraps it across several lines) followed by the "||v||t||len" trailer. It is intentionally strict — both the trailer and a pure-base64 body are required — so ordinary text (CJK, punctuation, …) never trips it.
func MessageID ¶
MessageID preserves the stable message identity needed by follow-up reply, reaction, resource and deduplication operations.
func MessageType ¶
MessageType preserves the lower message type when present.
func Pagination ¶
Pagination extracts hasMore/nextCursor from the response root or a common result/data envelope. When hasMore is present it also emits the explicit inverse "complete", making truncation hard for an Agent to overlook.
func QuotedMessage ¶
QuotedMessage projects one level of quoted/replied-to context. It is deliberately non-recursive: a reply chain may be arbitrarily deep or even cyclic after gateway reshaping, while an Agent primarily needs the quoted message's stable identity, speaker, readable body and time.
func Reactions ¶
Reactions normalises DingTalk's inline emotionReplyList into one compact, Agent-friendly block. Unlike Lark, DingTalk already returns these reactions with message-list responses, so this projection performs no extra network request.
Output shape:
"reactions": {
"counts": [{"emoji": "赞", "count": 3}],
"details": [{"emoji": "赞", "replyUsers": ["..."]}]
}
func Resources ¶
Resources extracts actionable media references from both structured message fields and the textual mediaId notation returned by older DingTalk message APIs. Every reference publishes the exact Shortcut arguments already known from the message, plus ready=false and missing fields when a follow-up lookup is still required. This shared shape is used by list, search, mget, quoted messages and thread replies.
func Sender ¶
Sender reads a message's speaker display name, tolerating common sender-name keys. The message-list responses carry the display name under the bare "sender" key (verified live), so it is probed first; the remaining aliases and the *Id fallbacks keep the projection resilient to other shapes. The literal string "null" (forwarded entries) and the empty string are treated as absent, and a nested {name:…} sender object yields its display name rather than the raw object.
func Text ¶
Text reads a message's textual content (tolerating common text keys and one level of nesting) and runs it through CleanText.
func ThreadID ¶
ThreadID preserves the stable topic/thread identity needed to continue from a message-list result into the thread-replies command.
func UpdateTime ¶
UpdateTime reads an edited message's update time. Gateways sometimes echo createTime as updateTime even when the message was never edited; omit that duplicate so Agents do not infer a nonexistent edit.
Types ¶
This section is empty.