fix(scraper): 群抓取改用 friend_list/es+friendTypeYunke=2(替换 getChatroomList)
getChatroomList 在云客真机返回 0 行(已 Playwright 2026-08-10 验证)。 群与好友共用 /wechatweb/wxFriends/friend_list/es,仅以 friendTypeYunke 区分 (1=好友 / 2=群),响应信封一致(basicResult),复用 _parse_total/_parse_rows。 - 删除 CHATROOM_LIST_PATH / _parse_chatroom_total / _parse_chatroom_rows / _build_chatroom_body / _parse_member_ids(改写后已无引用) - 新增 _build_group_body(pageNum/pageSize/friendTypeYunke="2") - 重写 _normalize_chat_group 映射 friend_list/es 字段 (friendWxId->room_id, friendWxNickname->room_name, friendNum->member_count, wxId/ownerName/userId, phone||wechatPhone, messageCount/sendNum/lastChatTime) - friend_list/es 不返回成员明细,member_ids/member_ids_list 固定 None/[] (群列表可用;成员镜像延后) - 删除 tests/cassettes/chatroom_fixture.py,改复用 wxFriends_fixture 信封 - 重写 test_scrape_wechat_groups:断言新端点 URL + friendTypeYunke="2" body + 新字段映射;member_ids 边界用例改为"始终 None/[]" scrape_wechat_groups 签名不变(client + page_size),orchestrator/scheduler 未改。 Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -1,137 +0,0 @@
|
||||
"""Fixture payloads for ``POST /wechatweb/chatroom/getChatroomList`` (M2).
|
||||
|
||||
These records mirror the real field names captured from the live CRM (see the
|
||||
data dictionary §2: ``chatRoomId(@chatroom), chatRoomName, memberCount,
|
||||
memberIds(分号分隔全部成员wxid), headImageUrl, wechatId/wechatNickName(归属),
|
||||
userName/userPhone(群主员工), messageCount/ownMessageCount, lossMembers/
|
||||
addMembers, lastChatTime/updateTime``; total=1515).
|
||||
|
||||
The envelope is the same flat shape as ``wxUser/list`` (no ``basicResult``
|
||||
wrapper): pagination fields sit directly under ``data``::
|
||||
|
||||
{"message":"调用成功","code":"10000","success":true,"traceId":"...",
|
||||
"data":{"data":[...], "total":.., "page":.., "pageCount":..}}
|
||||
|
||||
The cassette ships three records across two pages so a test can drive the
|
||||
page-number paginator across the empty-page stop signal:
|
||||
|
||||
* page 1 -> 2 of the 3 fixture records, ``total=3``
|
||||
* page 2 -> the remaining 1 record, ``total=3``
|
||||
* (page 3 -> empty ``data`` array, served inline by the test)
|
||||
|
||||
Records carry every field with a target ``ChatGroup`` column so the test can
|
||||
assert a full mapping end-to-end. The ``memberIds`` field is the
|
||||
semicolon-joined member wxid list; record 2 deliberately includes a trailing
|
||||
empty segment (``"...;"``) so the parser's drop-empties path is exercised.
|
||||
"""
|
||||
|
||||
# The module name mirrors the upstream endpoint name (``chatroom``); the M2
|
||||
# spec mandates this exact filename.
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Capture-shaped chatroom records (3 total across 2 pages).
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
CHATROOM_RECORDS: list[dict[str, Any]] = [
|
||||
{
|
||||
"chatRoomId": "12345678901@chatroom",
|
||||
"chatRoomName": "VIP客户交流群",
|
||||
"memberCount": 3,
|
||||
# 3 members, no empties -> member_ids_list length 3.
|
||||
"memberIds": "wxid_member_a1;wxid_member_a2;csf7169708",
|
||||
"headImageUrl": "https://wx.qlogo.cn/room_12345678901.png",
|
||||
"wechatId": "wxid_staff_alice01",
|
||||
"wechatNickName": "Alice WeChat",
|
||||
"userId": "staff_user_001",
|
||||
"userName": "Alice Wang",
|
||||
"userPhone": "13800000001",
|
||||
"messageCount": 4521,
|
||||
"ownMessageCount": 1204,
|
||||
"lossMembers": 2,
|
||||
"addMembers": 5,
|
||||
"lastChatTime": 1700000000123,
|
||||
"updateTime": 1700000001000,
|
||||
"version": "v1.20260731.room1",
|
||||
},
|
||||
{
|
||||
"chatRoomId": "98765432109@chatroom",
|
||||
"chatRoomName": "华东销售大群",
|
||||
"memberCount": 2,
|
||||
# Trailing empty segment -> member_ids_list length 2 (empties dropped).
|
||||
"memberIds": "wxid_member_b1;wxid_member_b2;",
|
||||
"headImageUrl": "https://wx.qlogo.cn/room_98765432109.png",
|
||||
"wechatId": "wxid_staff_bob02",
|
||||
"wechatNickName": "Bob WeChat",
|
||||
"userId": "staff_user_002",
|
||||
"userName": "Bob Chen",
|
||||
"userPhone": "13800000002",
|
||||
"messageCount": 9821,
|
||||
"ownMessageCount": 211,
|
||||
"lossMembers": 0,
|
||||
"addMembers": 1,
|
||||
"lastChatTime": 1700000000456,
|
||||
"updateTime": 1700000000800,
|
||||
"version": "v1.20260731.room2",
|
||||
},
|
||||
{
|
||||
# A group whose owner has no resolved staff id (userId None) — the
|
||||
# scraper must still yield it; the repo must still upsert its members.
|
||||
"chatRoomId": "55555555555@chatroom",
|
||||
"chatRoomName": "External Coordination",
|
||||
"memberCount": 1,
|
||||
"memberIds": "wxid_member_c1",
|
||||
"headImageUrl": "https://wx.qlogo.cn/room_55555555555.png",
|
||||
"wechatId": "wxid_staff_orphan04",
|
||||
"wechatNickName": "Orphan WeChat",
|
||||
"userId": None,
|
||||
"userName": None,
|
||||
"userPhone": None,
|
||||
"messageCount": 12,
|
||||
"ownMessageCount": 0,
|
||||
"lossMembers": 0,
|
||||
"addMembers": 0,
|
||||
"lastChatTime": 1700000000789,
|
||||
"updateTime": 1700000000900,
|
||||
"version": "v1.20260731.room3",
|
||||
},
|
||||
]
|
||||
|
||||
# Default page size for the fixture (and the scraper). total=3 means the
|
||||
# fixture fills exactly 2 pages of size 2 plus a terminating empty page.
|
||||
TOTAL = len(CHATROOM_RECORDS)
|
||||
DEFAULT_PAGE_SIZE = 2
|
||||
|
||||
|
||||
def make_chatroom_list_response(
|
||||
records: list[dict[str, Any]],
|
||||
*,
|
||||
total: int,
|
||||
page_num: int = 1,
|
||||
page_size: int = DEFAULT_PAGE_SIZE,
|
||||
trace_id: str | None = None,
|
||||
) -> dict[str, Any]:
|
||||
"""Build a capture-shaped ``getChatroomList`` response envelope.
|
||||
|
||||
Shape (no ``basicResult`` wrapper; pagination fields directly under
|
||||
``data``)::
|
||||
|
||||
{"message":"调用成功","code":"10000","success":true,"traceId":"...",
|
||||
"data":{"data":[...], "total":.., "page":.., "pageCount":..}}
|
||||
"""
|
||||
return {
|
||||
"message": "调用成功",
|
||||
"code": "10000",
|
||||
"success": True,
|
||||
"traceId": trace_id or f"trace-{page_num}",
|
||||
"data": {
|
||||
"data": list(records),
|
||||
"total": total,
|
||||
"page": page_num,
|
||||
"pageCount": (
|
||||
(total + page_size - 1) // page_size if page_size else 1
|
||||
),
|
||||
},
|
||||
}
|
||||
Reference in New Issue
Block a user