feat(sync): WA messages 自动同步(per-conversation 增量水位,镜像 sync_wechat_messages)
Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -67,6 +67,7 @@ from app.sync.orchestrator import (
|
||||
sync_wechat_voice_calls,
|
||||
sync_whatsapp_accounts,
|
||||
sync_whatsapp_friends,
|
||||
sync_whatsapp_messages,
|
||||
)
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
@@ -87,22 +88,23 @@ DEFAULT_MAX_CONVERSATIONS_PER_RUN = 200
|
||||
async def _discover_conversations(
|
||||
session: AsyncSession,
|
||||
*,
|
||||
channel: str = "wechat",
|
||||
limit: int = DEFAULT_MAX_CONVERSATIONS_PER_RUN,
|
||||
) -> list[tuple[str, str]]:
|
||||
"""Return distinct ``(owner_account_id, friend_id)`` WeChat pairs to sync.
|
||||
"""Return distinct ``(owner_account_id, friend_id)`` pairs to sync.
|
||||
|
||||
Source: the local ``customer`` mirror (where
|
||||
``channel='wechat'`` and ``owner_account_id`` is non-empty). Reading the
|
||||
already-mirrored table — instead of the upstream ``talkerList`` endpoint
|
||||
— keeps the discovery call off the risk-control budget and makes the
|
||||
incremental run purely a function of the customers we already know
|
||||
Source: the local ``customer`` mirror, filtered by ``channel``
|
||||
(default ``'wechat'``; pass ``'whatsapp'`` for WA conversations). Reading
|
||||
the already-mirrored table — instead of the upstream ``talkerList``
|
||||
endpoint — keeps the discovery call off the risk-control budget and makes
|
||||
the incremental run purely a function of the customers we already know
|
||||
about. Order is unspecified; ``limit`` caps work per run.
|
||||
"""
|
||||
from app.db.models import Customer
|
||||
|
||||
stmt = (
|
||||
sa.select(Customer.owner_account_id, Customer.friend_id)
|
||||
.where(Customer.channel == "wechat")
|
||||
.where(Customer.channel == channel)
|
||||
.where(Customer.owner_account_id.is_not(None))
|
||||
.where(Customer.owner_account_id != "")
|
||||
.distinct()
|
||||
@@ -208,6 +210,26 @@ async def _run_messages(
|
||||
return results
|
||||
|
||||
|
||||
async def _run_wa_messages(
|
||||
session: AsyncSession, client: YunkeClient, store: ObjectStore
|
||||
) -> list[SyncResult]:
|
||||
"""Incremental message sync across all locally-known WA conversations.
|
||||
|
||||
Mirrors :func:`_run_messages`: discovers ``(uid, friend_uid)`` pairs from
|
||||
the local ``customer`` mirror (``channel='whatsapp'``) and calls
|
||||
:func:`sync_whatsapp_messages` per conversation. ``store`` is accepted
|
||||
for signature parity with the other runners but is NOT used — WA media
|
||||
download is deferred to Phase 2.
|
||||
"""
|
||||
conversations = await _discover_conversations(session, channel="whatsapp")
|
||||
results: list[SyncResult] = []
|
||||
for uid, friend_uid in conversations:
|
||||
results.append(
|
||||
await sync_whatsapp_messages(session, client, uid, friend_uid)
|
||||
)
|
||||
return results
|
||||
|
||||
|
||||
async def _run_all_wechat(
|
||||
session: AsyncSession, client: YunkeClient, store: ObjectStore
|
||||
) -> list[SyncResult]:
|
||||
@@ -236,6 +258,10 @@ async def _run_all(
|
||||
# which ``_run_all_wechat`` seeds via sync_departments — so order matters.
|
||||
results.append(await sync_whatsapp_accounts(session, client))
|
||||
results.append(await sync_whatsapp_friends(session, client))
|
||||
# WA messages: per-conversation incremental sync, discovered from the
|
||||
# already-mirrored ``customer`` table (channel='whatsapp'). Must run
|
||||
# AFTER wa_friends (which seeds the customer rows the discovery reads).
|
||||
results.extend(await _run_wa_messages(session, client, store))
|
||||
results.append(await sync_phone_calls(session, client))
|
||||
results.append(await sync_sms(session, client))
|
||||
return results
|
||||
@@ -259,6 +285,7 @@ ENTITY_FUNCS: dict[
|
||||
"sms": _run_sms,
|
||||
"call_recordings": _run_call_recordings,
|
||||
"messages": _run_messages,
|
||||
"wa_messages": _run_wa_messages,
|
||||
"all_wechat": _run_all_wechat,
|
||||
"all": _run_all,
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user