feat(groups): chat_group 补 6 群主/建群列 + 复合PK迁移修复 + 存量回填
对齐云客员工聊天窗口·微信群 tab(2026-08-25 真机验证 raw_json 键): - ChatGroup 加列 owner_name/owner_wxid/owner_alias/owner_avatar/ friend_count/create_time(全 nullable) - scraper _normalize_chat_group 同名提取;createTime 兼容 ms-int 与 'YYYY-MM-DD HH:mm:ss'(smoke.db 实测 1105 行全为后者),复用 _parse_add_time 归一 ms-epoch - 迁移 099ac2097fa2:加 6 列 + 修复 Task1 评审遗留 drift——PK 由单列 room_id 变更为复合 (room_id, channel, owner_account_id) 且 owner_account_id NOT NULL(对齐模型 8a99940;smoke.db 1105 行无 NULL, 未兜底编造数据);SQLite 走 batch 重建(copy_from 显式旧结构), MySQL 渲染为直接 ALTER(离线 --sql 已验证) - 回填脚本 scripts/backfill_chat_group_fields.py(幂等,逐列只补空); smoke.db 实跑 backfilled 1105/1105,重跑 0/1105 - GroupOut 加 6 字段(model_validate 自动输出,路由无改) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -32,7 +32,7 @@ from typing import Any
|
||||
import httpx
|
||||
import respx
|
||||
|
||||
from app.scraper.wechat import scrape_wechat_groups
|
||||
from app.scraper.wechat import _normalize_chat_group, scrape_wechat_groups
|
||||
from app.session.yunke_client import YunkeClient
|
||||
from tests.cassettes.wxFriends_fixture import make_friend_list_response
|
||||
|
||||
@@ -277,3 +277,50 @@ async def test_scrape_wechat_groups_stops_on_empty_first_page():
|
||||
|
||||
assert results == []
|
||||
assert route.call_count == 1
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# 群主/建群补充列提取(2026-08-25 对齐云客员工聊天窗口·微信群 tab)
|
||||
# raw_json 键: ownerName/ownerWchatId/ownerAlias/ownerImage/friendCount/createTime
|
||||
# smoke.db 实测: createTime 全部为 'YYYY-MM-DD HH:mm:ss' 字符串;ms int 直通。
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
|
||||
def test_normalize_chat_group_extracts_owner_fields():
|
||||
"""6 个补充键提取到同名列;date-str createTime 归一为 ms epoch。"""
|
||||
record = {
|
||||
"friendWxId": "123@chatroom",
|
||||
"friendWxNickname": "测试群",
|
||||
"friendNum": 25,
|
||||
"wxId": "wxid_x",
|
||||
"ownerName": "Q**e",
|
||||
"ownerWchatId": "RL3*****108",
|
||||
"ownerAlias": "Fr******er",
|
||||
"ownerImage": "https://wx.qlogo.cn/o/0",
|
||||
"friendCount": 22,
|
||||
"createTime": "2025-10-27 13:30:55",
|
||||
}
|
||||
out = _normalize_chat_group(record)
|
||||
assert out["owner_name"] == "Q**e"
|
||||
assert out["owner_wxid"] == "RL3*****108"
|
||||
assert out["owner_alias"] == "Fr******er"
|
||||
assert out["owner_avatar"] == "https://wx.qlogo.cn/o/0"
|
||||
assert out["friend_count"] == 22
|
||||
# 'YYYY-MM-DD HH:mm:ss' -> ms epoch(naive UTC,同 addTime 约定)
|
||||
assert out["create_time"] == 1761571855000
|
||||
|
||||
|
||||
def test_normalize_chat_group_owner_fields_none_safe():
|
||||
"""缺失全部 6 个键 -> 全 None(老 capture 不炸)。"""
|
||||
out = _normalize_chat_group({"friendWxId": "r@chatroom"})
|
||||
for key in ("owner_name", "owner_wxid", "owner_alias",
|
||||
"owner_avatar", "friend_count", "create_time"):
|
||||
assert out[key] is None
|
||||
|
||||
|
||||
def test_normalize_chat_group_create_time_ms_passthrough():
|
||||
"""ms-epoch int 直通(不做日期解析)。"""
|
||||
out = _normalize_chat_group(
|
||||
{"friendWxId": "r@chatroom", "createTime": 1740000000000}
|
||||
)
|
||||
assert out["create_time"] == 1740000000000
|
||||
|
||||
Reference in New Issue
Block a user