event_parsers — 飞书 JSON → FeishuMessageEvent

event_parsers — 飞书 JSON → FeishuMessageEvent#

源码:src/cclark/event_parsers.py

将原始飞书 WebSocket 事件 JSON 负载转换为类型化 Python 数据类。

FeishuMessageEvent#

@dataclass
class FeishuMessageEvent:
    chat_id: str       # "oc_xxxx"
    thread_id: str     # 非话题聊天时为 ""
    user_id: str       # 发送者的飞书 open_id
    text: str          # 去空格后的文本内容
    message_id: str     # 用于回复话题
    msg_type: str      # "text"(当前仅处理文本)
    app_name: str      # 多 app 模式下来源 app 名称

parse_message_event 解析逻辑#

payload = {"event": {
    "chat_id": "...",
    "thread_id": "...",
    "sender": {"sender_id": {"open_id": "..."}},
    "message": {"msg_type": "text", "message_id": "...",
                "content": "{\"text\": \"...\"}"}
}}
↓ 提取 event、sender、message
↓ msg_type != "text"? → 返回 None  [仅处理文本]
↓ json.loads(content) → {"text": "..."}
↓ text = parsed["text"].strip()
↓ FeishuMessageEvent(...)
↓ 任何异常 → 返回 None

飞书文本消息的 JSON content 字段本身又是一个 JSON 字符串, 所以需要双重解析。

支持的飞书事件 schema 版本#

Feishu 平台在 1.0 和 2.0 版本间演进:

parse_message_event 使用 or 链接受两者: message.get("message_type", "") or message.get("msg_type", "")

调用栈#

ws_client._dispatch_event(payload)
→ parse_message_event(payload)
    → payload["event"]["message"]["msg_type"] == "text"?
    → payload["event"]["message"]["content"] = '{"text": "hello"}'
    → json.loads → {"text": "hello"}
    → text = "hello".strip()
    → return FeishuMessageEvent(chat_id=..., user_id=..., text="hello", ...)
→ handle_message(event)  [handlers/message.py]