Files
kefu/wechat_rpa/tmp/probe_surface_drift.py
2026-07-31 11:48:16 +08:00

135 lines
5.0 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""查明粘贴草稿后 _chat_surface_signature() 的哪个分量发生了变化。
会临时往输入框粘贴一段文字,测完立即 Ctrl+A + Backspace 清除,并还原剪贴板。
绝不按 Enter,不会发出任何消息。
"""
import os
import sys
import time
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
import numpy as np
import pyautogui
import pyperclip
from PIL import Image
import wechat_bot as bot_module
_HERE = os.path.dirname(os.path.abspath(__file__))
_PROBE_DRAFT = "诊断用草稿请忽略"
def measure(bot):
"""分别返回聊天区布局指纹、选中行预览指纹和整体指纹。"""
full = bot._capture_full_window()
list_x1 = max(0, int(bot._list_x))
list_y1 = max(0, int(bot._list_y))
list_x2 = min(full.shape[1], list_x1 + int(bot._list_w))
list_y2 = min(full.shape[0], list_y1 + int(bot._list_h))
chat_x1 = max(0, int(bot._chat_rel_x))
chat_y1 = max(0, int(bot._chat_rel_y))
chat_x2 = min(full.shape[1], chat_x1 + int(bot._chat_rel_w))
chat_y2 = min(full.shape[0], chat_y1 + int(bot._chat_rel_h))
session_list = full[list_y1:list_y2, list_x1:list_x2]
chat = full[chat_y1:chat_y2, chat_x1:chat_x2]
selected_y = bot.detect_selected_row(session_list)
activity = (
bot._session_row_activity_signature(session_list, selected_y)
if selected_y >= 0
else b""
)
return {
"chat_layout": bot._chat_layout_signature(chat).hex(),
"selected_y": selected_y,
"row_preview": activity.hex(),
"overall": bot._chat_surface_signature().hex(),
"chat_box": (chat_x1, chat_y1, chat_x2, chat_y2),
"session_list": session_list,
"chat": chat,
}
def main():
bot = bot_module.WeChatBot()
bot.safe_window_mode = True
bot.auto_activate_window = True
if not bot.connect(activate=False, wait_if_missing=False):
print("[-] 未挂载到企业微信窗口")
return
if not bot._ensure_visible():
print("[-] 企业微信未能切到前台")
return
bot._refresh_message_geometry(bot._capture_full_window())
print(f"聊天区裁剪框(窗口内): x {bot._chat_rel_x}~{bot._chat_rel_x + bot._chat_rel_w}"
f" y {bot._chat_rel_y}~{bot._chat_rel_y + bot._chat_rel_h}")
print(f"_composer_rel_top : {bot._composer_rel_top}")
before = measure(bot)
print("\n[粘贴草稿前]")
print(f" 聊天区布局 : {before['chat_layout']}")
print(f" 选中行 y : {before['selected_y']}")
print(f" 会话行预览 : {before['row_preview']}")
print(f" 整体指纹 : {before['overall']}")
old_clipboard = ""
try:
old_clipboard = pyperclip.paste()
except Exception:
pass
try:
pyperclip.copy(_PROBE_DRAFT)
pyautogui.click(bot.input_x, bot.input_y)
time.sleep(0.2)
pyautogui.hotkey("ctrl", "v")
time.sleep(0.6)
after = measure(bot)
print("\n[粘贴草稿后]")
print(f" 聊天区布局 : {after['chat_layout']}"
f" {'← 变化' if after['chat_layout'] != before['chat_layout'] else '(未变)'}")
print(f" 选中行 y : {after['selected_y']}")
print(f" 会话行预览 : {after['row_preview']}"
f" {'← 变化' if after['row_preview'] != before['row_preview'] else '(未变)'}")
print(f" 整体指纹 : {after['overall']}"
f" {'← 变化' if after['overall'] != before['overall'] else '(未变)'}")
print(f" _composer_rel_top 重算: "
f"{bot_module.infer_composer_top(bot._capture_full_window(), int(bot._list_x + bot._list_w), bot.scale)}")
Image.fromarray(before["chat"][:, :, :3][:, :, ::-1]).save(
os.path.join(_HERE, "surface_chat_before.png")
)
Image.fromarray(after["chat"][:, :, :3][:, :, ::-1]).save(
os.path.join(_HERE, "surface_chat_after.png")
)
Image.fromarray(after["session_list"][:, :, :3][:, :, ::-1]).save(
os.path.join(_HERE, "surface_list_after.png")
)
diff = np.abs(
before["chat"][:, :, :3].astype(np.int16)
- after["chat"][:, :, :3].astype(np.int16)
).max(axis=2)
rows = np.flatnonzero((diff > 12).any(axis=1))
if rows.size:
print(f" 聊天区裁剪内实际变化的行(裁剪内坐标): {rows.min()} ~ {rows.max()}"
f" (裁剪高度 {diff.shape[0]}")
else:
print(" 聊天区裁剪内像素没有任何变化")
print(" 已保存 tmp/surface_chat_before.png / surface_chat_after.png / surface_list_after.png")
finally:
pyautogui.hotkey("ctrl", "a")
pyautogui.press("backspace")
time.sleep(0.2)
try:
pyperclip.copy(old_clipboard)
except Exception:
pass
print("\n[清理] 已清除诊断草稿并还原剪贴板。")
if __name__ == "__main__":
main()