fix: drop source header (breaks msg/chats) + context-aware talker_id
Live validation found two real bugs: - YunkeClient sent 'source: yunkepc' on every request; msg/chats binds source as Integer -> 500. Removed (cookie auth suffices, per Phase 0). - WeChat message talker_id used the masked 'talker' field; the timeline joins on the full peer id. Now: 1:1 -> oriTalker (full), group -> talker (member). ori_talker keeps the raw oriTalker (peer/chatroom). Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -346,11 +346,21 @@ def _normalize_message(record: dict[str, Any]) -> dict[str, Any]:
|
|||||||
if timestamp is None:
|
if timestamp is None:
|
||||||
timestamp = record.get("createTime")
|
timestamp = record.get("createTime")
|
||||||
|
|
||||||
|
# talker_id = the message's sender/peer FULL id (the timeline join key).
|
||||||
|
# 1:1 (empty roomid): upstream `talker` is masked, the full peer is
|
||||||
|
# `oriTalker`. group (roomid set): `talker` is the sending member, while
|
||||||
|
# `oriTalker` is the chatroom id — so the member is in `talker`.
|
||||||
|
roomid = record.get("roomid") or ""
|
||||||
|
if roomid:
|
||||||
|
talker_id = record.get("talker")
|
||||||
|
else:
|
||||||
|
talker_id = record.get("oriTalker") or record.get("talker")
|
||||||
|
|
||||||
return {
|
return {
|
||||||
"msg_id": record.get("msgSvrId"),
|
"msg_id": record.get("msgSvrId"),
|
||||||
"channel": "wechat",
|
"channel": "wechat",
|
||||||
"owner_account_id": record.get("wechatId"),
|
"owner_account_id": record.get("wechatId"),
|
||||||
"talker_id": record.get("talker"),
|
"talker_id": talker_id,
|
||||||
"ori_talker": record.get("oriTalker"),
|
"ori_talker": record.get("oriTalker"),
|
||||||
"room_id": record.get("roomid"),
|
"room_id": record.get("roomid"),
|
||||||
"is_send": is_send,
|
"is_send": is_send,
|
||||||
|
|||||||
@@ -42,10 +42,13 @@ from app.session.login import (
|
|||||||
pc_login,
|
pc_login,
|
||||||
)
|
)
|
||||||
|
|
||||||
# The 4 constant auth headers. ``userid`` + ``company`` come from the
|
# Constant auth headers. ``userid`` + ``company`` come from the LoginResult
|
||||||
# LoginResult and are merged in separately.
|
# and are merged in separately. NOTE: ``source`` is intentionally NOT sent —
|
||||||
|
# the real CRM session cookie authenticates data APIs (confirmed in Phase 0),
|
||||||
|
# and several endpoints (e.g. ``msg/chats``) bind a ``source`` parameter as
|
||||||
|
# Integer, so a ``source: "yunkepc"`` header makes them 500. Cookie-only auth
|
||||||
|
# works for all data endpoints.
|
||||||
_STATIC_AUTH_HEADERS: dict[str, str] = {
|
_STATIC_AUTH_HEADERS: dict[str, str] = {
|
||||||
"source": "yunkepc",
|
|
||||||
"channel": "4",
|
"channel": "4",
|
||||||
"content-type": "application/json",
|
"content-type": "application/json",
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -127,7 +127,10 @@ async def test_post_injects_auth_headers(client: YunkeClient):
|
|||||||
# The 5 known auth headers must be on every outgoing request.
|
# The 5 known auth headers must be on every outgoing request.
|
||||||
assert sent.headers["userid"] == USERID
|
assert sent.headers["userid"] == USERID
|
||||||
assert sent.headers["company"] == COMPANY
|
assert sent.headers["company"] == COMPANY
|
||||||
assert sent.headers["source"] == "yunkepc"
|
# NOTE: ``source`` is intentionally NOT sent — several endpoints (msg/chats)
|
||||||
|
# bind a ``source`` param as Integer, so ``source: "yunkepc"`` 500s. Cookie
|
||||||
|
# auth suffices for all data endpoints (Phase 0).
|
||||||
|
assert "source" not in sent.headers
|
||||||
assert sent.headers["channel"] == "4"
|
assert sent.headers["channel"] == "4"
|
||||||
assert sent.headers["content-type"] == "application/json"
|
assert sent.headers["content-type"] == "application/json"
|
||||||
# And the session cookie travels along too.
|
# And the session cookie travels along too.
|
||||||
|
|||||||
@@ -113,7 +113,7 @@ async def test_browser_headers_present_on_every_request(client: YunkeClient):
|
|||||||
assert sent["sec-ch-ua-platform"] == '"Windows"'
|
assert sent["sec-ch-ua-platform"] == '"Windows"'
|
||||||
assert sent["referer"] == "https://crm2.yunkecn.com/"
|
assert sent["referer"] == "https://crm2.yunkecn.com/"
|
||||||
# The existing auth headers still ride along unchanged.
|
# The existing auth headers still ride along unchanged.
|
||||||
assert sent["source"] == "yunkepc"
|
assert "source" not in sent # omitted: breaks msg/chats Integer binding
|
||||||
assert sent["channel"] == "4"
|
assert sent["channel"] == "4"
|
||||||
assert sent["userid"] == USERID
|
assert sent["userid"] == USERID
|
||||||
assert sent["company"] == COMPANY
|
assert sent["company"] == COMPANY
|
||||||
|
|||||||
Reference in New Issue
Block a user