Skip to content

Commit 4db7806

Browse files
committed
feat(api): 支持自动实时数据源回退
- 聊天和服务号接口新增 source=auto,优先读取 WCDB realtime - realtime 不可用时自动回退 decrypted 快照数据源 - 服务号实时读取兼容 Name2Id 字段差异和 BLOB 内容 - 实时自动同步改为可选兼容能力,补充 source=auto 回归测试
1 parent d7b50f6 commit 4db7806

6 files changed

Lines changed: 860 additions & 163 deletions

File tree

src/wechat_decrypt_tool/chat_helpers.py

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@
2323

2424
logger = get_logger(__name__)
2525

26-
_OUTPUT_DATABASES_DIR = get_output_databases_dir()
2726
_DEBUG_SESSIONS = os.environ.get("WECHAT_TOOL_DEBUG_SESSIONS", "0") == "1"
2827
_SQLITE_HEADER = b"SQLite format 3\x00"
2928

@@ -33,11 +32,12 @@ def _is_valid_decrypted_sqlite(path: Path) -> bool:
3332

3433

3534
def _list_decrypted_accounts() -> list[str]:
36-
if not _OUTPUT_DATABASES_DIR.exists():
35+
output_databases_dir = get_output_databases_dir()
36+
if not output_databases_dir.exists():
3737
return []
3838

3939
accounts: list[str] = []
40-
for p in _OUTPUT_DATABASES_DIR.iterdir():
40+
for p in output_databases_dir.iterdir():
4141
if not p.is_dir():
4242
continue
4343
if _is_valid_decrypted_sqlite(p / "session.db") and _is_valid_decrypted_sqlite(p / "contact.db"):
@@ -58,8 +58,9 @@ def _resolve_account_dir(account: Optional[str]) -> Path:
5858
selected = str(account or "").strip() or accounts[0]
5959
if selected not in accounts:
6060
raise HTTPException(status_code=404, detail="Account not found.")
61-
base = _OUTPUT_DATABASES_DIR.resolve()
62-
candidate = (_OUTPUT_DATABASES_DIR / selected).resolve()
61+
output_databases_dir = get_output_databases_dir()
62+
base = output_databases_dir.resolve()
63+
candidate = (output_databases_dir / selected).resolve()
6364

6465
if candidate != base and base not in candidate.parents:
6566
raise HTTPException(status_code=400, detail="Invalid account path.")

src/wechat_decrypt_tool/chat_realtime_autosync.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
"""Background auto-sync from WCDB realtime (db_storage) into decrypted sqlite.
1+
"""Optional background auto-sync from WCDB realtime (db_storage) into decrypted sqlite.
22
33
Why:
4-
- The UI can read "latest" messages from WCDB realtime (`source=realtime`), but most APIs default to the
5-
decrypted sqlite snapshot (`source=decrypted`).
6-
- Previously we only synced realtime -> decrypted when the UI toggled realtime off, which caused `/api/chat/messages`
7-
to lag behind while realtime was enabled.
4+
- The chat UI now defaults to reading from WCDB realtime (`source=auto`), so it does not need a second
5+
always-updated decrypted copy for display.
6+
- This service is kept as an opt-in compatibility bridge for workflows that still require the decrypted
7+
sqlite snapshot to be incrementally updated.
88
99
This module runs a lightweight background poller that watches db_storage mtime changes and triggers an incremental
1010
sync_all into decrypted sqlite. It is intentionally conservative (debounced + rate-limited) to avoid hammering the
@@ -105,7 +105,7 @@ class _AccountState:
105105

106106
class ChatRealtimeAutoSyncService:
107107
def __init__(self) -> None:
108-
self._enabled = _env_bool("WECHAT_TOOL_REALTIME_AUTOSYNC", True)
108+
self._enabled = _env_bool("WECHAT_TOOL_REALTIME_AUTOSYNC", False)
109109
self._interval_ms = _env_int("WECHAT_TOOL_REALTIME_AUTOSYNC_INTERVAL_MS", 1000, min_v=200, max_v=10_000)
110110
self._debounce_ms = _env_int("WECHAT_TOOL_REALTIME_AUTOSYNC_DEBOUNCE_MS", 600, min_v=0, max_v=10_000)
111111
self._min_sync_interval_ms = _env_int(
@@ -181,7 +181,7 @@ def resume_account(self, account: str, reason: str = "") -> int:
181181

182182
def start(self) -> None:
183183
if not self._enabled:
184-
logger.info("[realtime-autosync] disabled by env WECHAT_TOOL_REALTIME_AUTOSYNC=0")
184+
logger.info("[realtime-autosync] disabled (set WECHAT_TOOL_REALTIME_AUTOSYNC=1 to enable)")
185185
return
186186

187187
with self._mu:

0 commit comments

Comments
 (0)