99 lines
4.1 KiB
Python
99 lines
4.1 KiB
Python
"""为什么每次 [待回复恢复] 之后都跟着 [页面校验] 点击前会话列表已变化?
|
||
|
||
定位器 _pending_rows_on_page 找到了行,click_session 用同一个 y 复核却不过。
|
||
两边的判据不一样,这里把 click_session 的三个子条件拆开单独打印,看是哪一个
|
||
把点击否掉的。纯读,不点击、不发送。
|
||
"""
|
||
import json
|
||
import os
|
||
import sys
|
||
|
||
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
||
|
||
import wechat_bot as bot_module # noqa: E402
|
||
from wechat_bot import ( # noqa: E402
|
||
_AVATAR_FP_BYTES,
|
||
_SESSION_FP_BYTES,
|
||
_LEGACY_SESSION_FP_BYTES,
|
||
)
|
||
|
||
|
||
def hamming(a: bytes, b: bytes) -> int:
|
||
if len(a) != len(b) or not a:
|
||
return -1
|
||
return (int.from_bytes(a, "big") ^ int.from_bytes(b, "big")).bit_count()
|
||
|
||
|
||
def main() -> None:
|
||
bot = bot_module.WeChatBot()
|
||
bot.safe_window_mode = True
|
||
bot.auto_activate_window = False
|
||
if not bot.connect(activate=False, wait_if_missing=False):
|
||
print("[-] 未挂载到企业微信窗口")
|
||
return
|
||
pending = dict(getattr(bot, "_pending_reply_sessions", {}))
|
||
print(f"待回复任务 {len(pending)} 个\n")
|
||
|
||
for key, state in pending.items():
|
||
target_fp = bytes.fromhex(key)
|
||
print("=" * 72)
|
||
print(f"任务 {key[:16]}… send_state={state.get('send_state')!r}")
|
||
found = bot._find_pending_session(target_fp)
|
||
if found is None:
|
||
incomplete = getattr(bot, "_pending_scan_incomplete", False)
|
||
print(
|
||
f" _find_pending_session: 没找到"
|
||
f"(扫描{'被时间预算截断,结论不可信' if incomplete else '已走完全部分页,确实不存在'})"
|
||
)
|
||
continue
|
||
_page, row_center = found
|
||
print(f" _find_pending_session: 命中 row_center={row_center}")
|
||
|
||
latest = bot.capture_session_list()
|
||
if latest is None:
|
||
print(" 重新截取列表失败")
|
||
continue
|
||
legacy = len(target_fp) == _LEGACY_SESSION_FP_BYTES
|
||
if legacy:
|
||
actual = bot._legacy_session_fingerprint(latest, row_center, row_center=True)
|
||
fp_ok = actual == target_fp
|
||
else:
|
||
actual = bot._session_fingerprint(latest, row_center, row_center=True)
|
||
fp_ok = bot._session_fp_matches(actual, target_fp)
|
||
|
||
print(f" 条件1 指纹匹配 = {fp_ok}")
|
||
if actual and len(actual) == _SESSION_FP_BYTES and not legacy:
|
||
name_ok, name_d = bot._name_fp_matches(
|
||
actual[_AVATAR_FP_BYTES:], target_fp[_AVATAR_FP_BYTES:]
|
||
)
|
||
print(
|
||
f" 头像距离={hamming(actual[:_AVATAR_FP_BYTES], target_fp[:_AVATAR_FP_BYTES])} "
|
||
f"(容差 {bot._FP_HAMMING_TOL_NAMED}/{bot._FP_HAMMING_TOL}) "
|
||
f"名称匹配={name_ok} 距离={name_d} "
|
||
f"名称有效={bot._name_fp_is_substantive(actual[_AVATAR_FP_BYTES:])}"
|
||
)
|
||
pair = tuple(sorted((actual.hex(), target_fp.hex())))
|
||
print(f" 别名已登记={pair in getattr(bot, '_live_session_fp_aliases', set())}")
|
||
|
||
pending_state = bot._pending_reply_state(target_fp)
|
||
allow_flat = bool(
|
||
(pending_state or {}).get("requires_visual_proof", False)
|
||
or bot._flat_session_is_known(target_fp)
|
||
)
|
||
allow_unrounded = bool(
|
||
len(target_fp) == _SESSION_FP_BYTES
|
||
and (pending_state or {}).get("requires_visual_proof", False)
|
||
and not bot._flat_session_rejected(target_fp)
|
||
)
|
||
shape_ok = bot._is_real_conversation(
|
||
latest, int(row_center), quiet=True, row_center=True, allow_flat=allow_flat
|
||
)
|
||
print(f" 条件2 会话形态 = {shape_ok} (allow_flat={allow_flat})")
|
||
print(f" 条件3 兜底放行 = {allow_unrounded}")
|
||
verdict = fp_ok and (shape_ok or allow_unrounded)
|
||
print(f" → click_session 会{'放行' if verdict else '取消这次点击'}")
|
||
|
||
|
||
if __name__ == "__main__":
|
||
main()
|