fix: 改名/改备注/改群名时联系人缓存不刷新(issue #67)

之前 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) <noreply@anthropic.com>
This commit is contained in:
ylytdeng
2026-05-11 20:54:18 +08:00
parent 9764385617
commit 15cfdcd4cc

View File

@@ -627,6 +627,10 @@ def _convert_hevc_to_jpeg(hevc_path, jpeg_path):
# ============ 监听器 ============ # ============ 监听器 ============
class SessionMonitor: 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): def __init__(self, enc_key, session_db, contact_names, db_cache=None, username_db_map=None):
self.enc_key = enc_key self.enc_key = enc_key
self.session_db = session_db self.session_db = session_db
@@ -639,6 +643,43 @@ class SessionMonitor:
self.patched_pages = 0 self.patched_pages = 0
# 已显示消息去重: {(username, timestamp, base_msg_type), ...} # 已显示消息去重: {(username, timestamp, base_msg_type), ...}
self._shown_keys = set() 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): def resolve_image(self, username, timestamp):
"""解密图片: username+timestamp → 解密后的图片文件名,失败返回 None""" """解密图片: username+timestamp → 解密后的图片文件名,失败返回 None"""
@@ -1369,22 +1410,11 @@ class SessionMonitor:
is_new = prev and (curr['timestamp'] > prev['timestamp'] or is_new = prev and (curr['timestamp'] > prev['timestamp'] or
(curr['timestamp'] == prev['timestamp'] and curr['msg_type'] != prev.get('msg_type'))) (curr['timestamp'] == prev['timestamp'] and curr['msg_type'] != prev.get('msg_type')))
if is_new: if is_new:
# contact.db mtime 变化时刷新缓存:覆盖新增联系人、改名、改备注、群名
# 修改等场景issue #46, #67。受 cooldown 节流。
self._maybe_refresh_contacts()
display = self.contact_names.get(username, username) display = self.contact_names.get(username, username)
is_group = '@chatroom' in 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 = '' sender = ''
if is_group: if is_group:
sender = self.contact_names.get(curr['sender'], curr['sender_name'] or curr['sender']) sender = self.contact_names.get(curr['sender'], curr['sender_name'] or curr['sender'])