8d7774b9f5
Co-Authored-By: Claude <noreply@anthropic.com>
49 lines
1.6 KiB
Python
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())
|