From 15cfdcd4cc8d9316215ab45a59c8e3d9c48b236d Mon Sep 17 00:00:00 2001 From: ylytdeng Date: Mon, 11 May 2026 20:54:18 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E6=94=B9=E5=90=8D/=E6=94=B9=E5=A4=87?= =?UTF-8?q?=E6=B3=A8/=E6=94=B9=E7=BE=A4=E5=90=8D=E6=97=B6=E8=81=94?= =?UTF-8?q?=E7=B3=BB=E4=BA=BA=E7=BC=93=E5=AD=98=E4=B8=8D=E5=88=B7=E6=96=B0?= =?UTF-8?q?=EF=BC=88issue=20#67=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 之前 commit e86e00d 的修复只覆盖「新增联系人不在缓存」的场景: if username not in self.contact_names: refresh() 改名/改备注/改群名时 username 一直在缓存里,永远跳过刷新, 导致显示老名字。 改成检测 contact.db mtime 变化触发全量 reload,受 30 秒 cooldown 节流(避免微信高频写 contact.db 时 CPU 抖动)。三种变更场景统一覆盖: - 新增联系人(原 #46 / e86e00d 场景) - 修改备注名(issue #67) - 修改群名 Co-Authored-By: Claude Opus 4.7 (1M context) --- monitor_web.py | 58 ++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 44 insertions(+), 14 deletions(-) diff --git a/monitor_web.py b/monitor_web.py index ec5f275..83f3cda 100644 --- a/monitor_web.py +++ b/monitor_web.py @@ -627,6 +627,10 @@ def _convert_hevc_to_jpeg(hevc_path, jpeg_path): # ============ 监听器 ============ class SessionMonitor: + # 改名/备注变更场景的刷新最小间隔(秒)。低于此间隔的 mtime 变化不触发 + # 全量 reload,避免微信高频写 contact.db 时 CPU 抖动。30s 是经验值。 + CONTACT_REFRESH_COOLDOWN = 30 + def __init__(self, enc_key, session_db, contact_names, db_cache=None, username_db_map=None): self.enc_key = enc_key self.session_db = session_db @@ -639,6 +643,43 @@ class SessionMonitor: self.patched_pages = 0 # 已显示消息去重: {(username, timestamp, base_msg_type), ...} self._shown_keys = set() + # contact.db mtime + 上次刷新时间,用于检测改名/备注变更 + self._contact_db_mtime = 0 + self._last_contact_refresh = 0 + + def _maybe_refresh_contacts(self): + """检测 contact.db mtime 变化时全量 reload 联系人缓存。 + + 覆盖三种变更场景: + - 新增联系人(之前 commit e86e00d 只覆盖了这种) + - 修改备注名(issue #67) + - 修改群名 + + 受 CONTACT_REFRESH_COOLDOWN 节流,避免 contact.db 高频变更时反复 reload。 + """ + if not self.db_cache: + return + try: + contact_path = self.db_cache.get(os.path.join("contact", "contact.db")) + except Exception as e: + print(f" [contact] 实时解密 contact.db 失败: {e}", flush=True) + return + if not contact_path: + return + try: + curr_mtime = os.path.getmtime(contact_path) + except OSError: + return + now = time.time() + if curr_mtime <= self._contact_db_mtime: + return # mtime 没变,跳过 + if now - self._last_contact_refresh < self.CONTACT_REFRESH_COOLDOWN: + return # cooldown 中,等下次 + refreshed = load_contact_names(contact_path) + if refreshed: + self.contact_names.update(refreshed) + self._contact_db_mtime = curr_mtime + self._last_contact_refresh = now def resolve_image(self, username, timestamp): """解密图片: username+timestamp → 解密后的图片文件名,失败返回 None""" @@ -1369,22 +1410,11 @@ class SessionMonitor: is_new = prev and (curr['timestamp'] > prev['timestamp'] or (curr['timestamp'] == prev['timestamp'] and curr['msg_type'] != prev.get('msg_type'))) if is_new: + # contact.db mtime 变化时刷新缓存:覆盖新增联系人、改名、改备注、群名 + # 修改等场景(issue #46, #67)。受 cooldown 节流。 + self._maybe_refresh_contacts() display = self.contact_names.get(username, username) is_group = '@chatroom' in username - # 新群/新联系人不在缓存中时,通过 db_cache 实时解密 contact.db 后重新加载 - # (load_contact_names 默认读静态快照,新加的联系人不在里面,这里必须走实时解密) - if username not in self.contact_names: - fresh_contact_db = None - if self.db_cache: - try: - fresh_contact_db = self.db_cache.get(os.path.join("contact", "contact.db")) - except Exception as e: - print(f" [contact] 实时解密 contact.db 失败: {e}", flush=True) - refreshed = load_contact_names(fresh_contact_db) - self.contact_names.update(refreshed) - display = self.contact_names.get(username, username) - if username in refreshed: - print(f" [contact] 新增: {username} -> {display}", flush=True) sender = '' if is_group: sender = self.contact_names.get(curr['sender'], curr['sender_name'] or curr['sender'])