feat(scraper): map customer add_time from raw_json

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
浅念
2026-08-05 18:44:04 +08:00
parent b5733f15d2
commit 8494d564ef
3 changed files with 81 additions and 0 deletions
+26
View File
@@ -154,6 +154,28 @@ def _build_body(
return body
# WeChat ``addTime`` is captured as ``'YYYY-MM-DD HH:mm:ss'`` (the common live
# shape; confirmed in smoke.db raw_json). Some captures instead carry a numeric
# ms-epoch. Both formats are accepted; first match wins.
_ADD_TIME_FORMATS = ("%Y-%m-%d %H:%M:%S", "%Y-%m-%d %H:%M")
def _parse_add_time(value: Any) -> int | None:
"""Coerce a wechat ``addTime`` to a ms-epoch ``int`` (naive UTC).
Accepted shapes:
* ``int`` / ``float`` — treated as ms-epoch already, returned as ``int``.
* ``str`` matching one of :data:`_ADD_TIME_FORMATS` — parsed via the shared
:func:`app.scraper.parsers.parse_datetime_to_ms` (naive UTC, same
convention as ``lastUpdate`` / ``startTime`` elsewhere in this layer).
* numeric ``str`` (e.g. ``"1690000000000"``) -> ``int`` (no datetime
round-trip).
* ``None`` / empty / unparseable -> ``None`` (None-safe field).
"""
return parse_datetime_to_ms(value, _ADD_TIME_FORMATS)
def _normalize(record: dict[str, Any]) -> dict[str, Any]:
"""Map one upstream friend record to the ``Customer`` column shape.
@@ -181,6 +203,10 @@ def _normalize(record: dict[str, Any]) -> dict[str, Any]:
# Prefer friendHeadImageUrl; fall back to the legacy headImg field.
"head_image_url": record.get("friendHeadImageUrl") or record.get("headImg"),
"last_chat_time": record.get("lastChatTime"),
# addTime is delivered as 'YYYY-MM-DD HH:mm:ss' (confirmed in smoke.db
# raw_json); some captures carry a numeric ms-epoch instead. Both shapes
# collapse to a ms-epoch int via _parse_add_time; None when missing/empty.
"add_time": _parse_add_time(record.get("addTime")),
"send_num": record.get("sendNum"),
"receive_num": record.get("receiveNum"),
"message_count": record.get("messageCount"),