mirror of https://github.com/jackwener/wx-cli.git
fix: 修复短时间大量消息丢失问题
旧逻辑用 `if ts == prev_ts: continue` 粗暴跳过上轮时间戳的所有消息, 但同一秒内可能有多条不同消息(如连续转发公众号文章),导致只显示 最后一条,其余丢失。 改为用 (username, timestamp, msg_type) 精确去重: - 主消息和 hidden 消息显示后都记录到 _shown_keys - 过滤时精确匹配已显示的消息,不再按时间戳整体跳过 - _shown_keys 每轮清理过期条目(保留 5 分钟),防止内存泄漏 Fixes #20 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>feat/daemon-cli
parent
64b2c9fdef
commit
030680eb85
|
|
@ -540,6 +540,8 @@ class SessionMonitor:
|
|||
self.prev_state = {}
|
||||
self.decrypt_ms = 0
|
||||
self.patched_pages = 0
|
||||
# 已显示消息去重: {(username, timestamp, base_msg_type), ...}
|
||||
self._shown_keys = set()
|
||||
|
||||
def resolve_image(self, username, timestamp):
|
||||
"""解密图片: username+timestamp → 解密后的图片文件名,失败返回 None"""
|
||||
|
|
@ -860,11 +862,8 @@ class SessionMonitor:
|
|||
hidden_msgs = []
|
||||
for ts, lt, mc, ct in all_rows:
|
||||
base = lt % 4294967296 if lt > 4294967296 else lt
|
||||
# 跳过与 session 当前消息相同时间戳+类型的(已显示)
|
||||
if ts == curr_ts and base == curr_msg_type:
|
||||
continue
|
||||
# 跳过 prev_ts 的消息(上一轮已显示)
|
||||
if ts == prev_ts:
|
||||
# 跳过已显示的消息(精确匹配 username+timestamp+type)
|
||||
if (username, ts, base) in self._shown_keys:
|
||||
continue
|
||||
# 解压 zstd
|
||||
if isinstance(mc, bytes) and ct == 4:
|
||||
|
|
@ -883,6 +882,7 @@ class SessionMonitor:
|
|||
|
||||
global messages_log
|
||||
for ts, base, mc in hidden_msgs:
|
||||
self._shown_keys.add((username, ts, base))
|
||||
msg_data = {
|
||||
'time': datetime.fromtimestamp(ts).strftime('%H:%M:%S'),
|
||||
'timestamp': ts,
|
||||
|
|
@ -1303,6 +1303,7 @@ class SessionMonitor:
|
|||
}
|
||||
|
||||
new_msgs.append(msg_data)
|
||||
self._shown_keys.add((username, curr['timestamp'], curr['msg_type']))
|
||||
|
||||
# 图片消息: 后台异步解密(不阻塞轮询)
|
||||
if curr['msg_type'] == 3:
|
||||
|
|
@ -1353,6 +1354,10 @@ class SessionMonitor:
|
|||
|
||||
self.prev_state = curr_state
|
||||
|
||||
# 清理过期的去重 key(保留最近 5 分钟)
|
||||
cutoff = int(time.time()) - 300
|
||||
self._shown_keys = {k for k in self._shown_keys if k[1] > cutoff}
|
||||
|
||||
def monitor_thread(enc_key, session_db, contact_names, db_cache=None, username_db_map=None):
|
||||
mon = SessionMonitor(enc_key, session_db, contact_names, db_cache, username_db_map)
|
||||
wal_path = mon.wal_path
|
||||
|
|
|
|||
Loading…
Reference in New Issue