Files
yunke/yunke-server/scripts/backfill_customer_add_time.py
T
2026-08-05 18:45:55 +08:00

49 lines
1.6 KiB
Python

"""Backfill Customer.add_time from raw_json.addTime (no re-scrape).
Iterates existing customer rows, parses raw_json.addTime (str or epoch) →
add_time ms-epoch, updates in batches. Idempotent: skips rows where add_time
is already set. WeChat rows have addTime; WhatsApp rows do not (createTime is
owner-staff, not customer-add) — those stay NULL.
"""
import asyncio
import time
from sqlalchemy import select, update
from sqlalchemy.ext.asyncio import async_sessionmaker, create_async_engine
from app.db import models # noqa: F401
from app.db.models import Customer
from app.scraper.wechat import _parse_add_time
BATCH = 200
async def main(db_url: str = "sqlite+aiosqlite:///./smoke.db") -> None:
engine = create_async_engine(db_url)
sm = async_sessionmaker(engine, expire_on_commit=False)
done = 0
async with sm() as s:
rows = (
await s.execute(select(Customer.friend_id, Customer.raw_json, Customer.add_time))
).all()
for fid, raw, existing in rows:
if existing or not raw:
continue
val = _parse_add_time(raw.get("addTime"))
if val is None:
continue
await s.execute(
update(Customer).where(Customer.friend_id == fid).values(add_time=val)
)
done += 1
if done % BATCH == 0:
await s.commit()
print(f"[{time.strftime('%H:%M:%S')}] {done} updated...")
await s.commit()
print(f"DONE — {done} customers got add_time")
await engine.dispose()
if __name__ == "__main__":
asyncio.run(main())