更新
This commit is contained in:
@@ -1,98 +1,98 @@
|
||||
"""为什么每次 [待回复恢复] 之后都跟着 [页面校验] 点击前会话列表已变化?
|
||||
|
||||
定位器 _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()
|
||||
"""为什么每次 [待回复恢复] 之后都跟着 [页面校验] 点击前会话列表已变化?
|
||||
|
||||
定位器 _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()
|
||||
|
||||
Reference in New Issue
Block a user