Commit Graph
68 Commits
Author SHA1 Message Date
youpaishidifu 59e3657684 加_is_markdown_document过滤: bot回复是md格式(%23标题、[链接](url)、-列表、反引号代码、|表格), 用户聊天框不用md语法, 借此区分bot旧回复vs用户新消息 2026-07-26 19:19:37 +08:00
youpaishidifu 3602ad6ef3 OCR裁剪cap_top 62%->45%放宽避免切消息+PostMessage VK_END兜底滚底(怕keybd_event被TIM忽略) 2026-07-26 19:12:53 +08:00
youpaishidifu 8c71412600 OCR截屏前Ctrl+End滚底+cap_top改为底部38%: 避免历史堆积+bot旧回复混入OCR, 只截最新消息区域 2026-07-26 19:01:24 +08:00
youpaishidifu 4307d5743f TIM裁剪左边界从25%调到42%: 25%截到会话列表的文档预览(混入OCR), 42%从消息面板左边缘开始, 避免文档预览混入, 保留对方消息 2026-07-26 18:54:26 +08:00
youpaishidifu 621d4c45b6 EnumWindows简化: _enum_callback已只加QQ/TIM相关窗口(for+TXGuiFoundation+Chrome+title), for循环直接取第一个可见+尺寸正常的, 不要求标题含QQ/TIM 2026-07-26 18:49:23 +08:00
youpaishidifu efdc8b0a4c QQ NT Electron主窗口标题是群名/昵称而非固定"QQ": Chrome_WidgetWin_1类名+可见+尺寸>200x100即可接受,不要求标题含QQ/TIM 2026-07-26 18:45:05 +08:00
youpaishidifu 3047a3ee82 OCR去重加强: _replied_texts加模糊匹配(0.85阈值)拦截OCR噪声版长回复; 超长文本(>200字符)跳过避免堆积历史冒充新消息触发回环 2026-07-26 18:38:27 +08:00
youpaishidifu ff6b72d5f2 EnumWindows加IsWindowVisible检查+debug log看候选窗口: 之前不可见TXGuiFoundation辅助窗口被缓存, title空top=592874, 真实主窗口一直不被使用 2026-07-26 18:28:11 +08:00
youpaishidifu 8626130f0c Fix QQ_FindWindow误缓存不可见托盘辅助窗口: TXGuiFoundation有不可见托盘辅助窗口(空标题IsWindowVisible=False), FindWindow返回它并缓存→_poll里IsWindowVisible检查静默跳过全轮。加IsWindowVisible检查后才缓存,不可见则fall through到EnumWindows找Chrome_WidgetWin_1可见主窗口 2026-07-26 18:23:57 +08:00
youpaishidifu 7aa3c9398e 修微信[S-A]读到侧栏文件列表而非聊天消息: _read_message_list加位置过滤>窗口45%右半侧才接受; 修QQ NT(Electron)新类名查找失败: EnumWindows加Chrome类名+标题含QQ搜索; config.py默认qq_enabled=True 2026-07-26 18:15:50 +08:00
youpaishidifu 0775ceaea7 QQ托盘隐藏时跳过poll不尝试恢复窗口: 任何ShowWindow(SW_SHOWNORMAL)在隐藏QQ NT窗口上都会触发托盘预览弹窗而非恢复主窗口 2026-07-26 17:57:15 +08:00
youpaishidifu 6bc8885eae 降级_validate_qq_window回c9acd7e版: 不做自动恢复->OCR空读->剪贴板兜底_ensure_foreground负责恢复主窗口 2026-07-26 17:46:55 +08:00
youpaishidifu 86686d0e22 修复Q窗口托盘恢复用SW_SHOWNORMAL替代SW_SHOWNA: SW_SHOWNA触发托盘预览弹窗而非主窗口 2026-07-26 17:38:11 +08:00
youpaishidifu 8f9433983f QQ托盘隐藏时用SW_SHOWNA恢复窗口(不触发托盘弹窗)+poll结束后自动SW_HIDE缩回托盘+验证不通过不再直接报窗口不可用 2026-07-26 17:21:09 +08:00
youpaishidifu e7f3adaa73 QQ窗口定位用Win32 FindWindow/EnumWindows替代UIA枚举,避免root.GetChildren()挂死 2026-07-26 16:59:03 +08:00
youpaishidifu 039b34179a 裁剪左边界退回25%(c9acd7e版),48%只截到自身消息右半边对方消息完全不可见 2026-07-26 16:54:23 +08:00
youpaishidifu 8963a34b6a 修复OCR乱码+KB全文返回: 裁剪48%+&提前清理+全角:转换+纯时间戳过滤+KB回复限200字
1. cap_left 38%→48%(完全避开会话列表~30-55%)
   38%仍捕获到左侧KB预览文字(问题1/2…)混入OCR
   48%只捕获消息面板正文,KB预览不再出现

2. &清理移到时间戳分割前+全角:→半角:
   原来&在分割后才清理,"13:5&07"无法被时间戳正则捕获
   分割前清理→"13:5 07"可匹配时间戳→分割出独立段
   全角:统一半角,后续正则只匹配半角

3. 时间戳段用\d{1,2}(允许单数字分钟)
   分割后"07""15"等纯数字段被^[\d:\s]+$过滤
   之前"13:5  07 14:2  15"整段因含空格,^\d{1,2}[::]\d{2}不匹配

4. auto_reply非Q&A文档回复限200字(之前500仍过多)
   子串匹配触发的全文返回只回复前200字符

5. KB行级预览过滤移除(与用户消息混行时误杀)
   段级别^问题\d+过滤器已足够,配合新裁剪基本不会触发
2026-07-26 16:37:41 +08:00
youpaishidifu 0e02a4a44c 修复OCR文字乱码:裁剪38-97%+KB预览过滤+&碎片清理
1. cap_left 25%→38%(避开会话列表KB预览文字)
   25%捕获联系人+会话列表双面板文字,KB预览"问题1:你叫什么名字"
   及小字OCR误读"届亻牛"(插件)→混合乱码
   38%从会话列表偏右开始,主要捕获消息面板大字号正文

2. cap_right 95%→97%(减少右侧时间戳裁剪)
   95%裁到时间戳右边缘→"13:57:07"变"13:5&07"
   97%多给2%宽度,大幅减少&碎片

3. KB预览行直接过滤:^问题\d+[::]
4. 循环中去掉&字符:line.replace('&', '')
2026-07-26 15:52:43 +08:00
youpaishidifu 7bdc7ad637 修复2问题: KB误匹配+返回全文 / Ctrl+C无法停止
1. KB匹配与返回全文
   - _poll中过滤纯时间/日期格式文本(OCR时间戳分割残留)->不入KB搜索
   - knowledge_base.py子串fallback要求query>=4字符,避免"19:15"等短时间戳误匹配
   - auto_reply._get_answer: 非Q&A文档只返回content前500字符,不返回整篇文件
   - 时间戳文本不进入KB + 短query不子串匹配 + 非Q&A截取 = 三层兜底

2. Ctrl+C无法停止
   - ThreadPoolExecutor创建非daemon线程->进程无法退出->必须杀CMD
     改用daemon thread + Event.wait(timeout): daemon线程不阻塞进程退出
   - main.py注册signal.signal(SIGINT) handler: 收到Ctrl+C后stop监控+quit窗口
   - 移除from concurrent.futures导入,替换为import signal
2026-07-26 15:30:55 +08:00
youpaishidifu 6d0974ea8f 修复_ensure_hwnd UIA挂死导致整条while循环卡住\n\n1. _ensure_hwnd 调用包装 ThreadPoolExecutor + 12s 超时\n 防止 QQ TXGuiFoundation 枚举或微信窗口检测无限阻塞\n 超时后日志警告 + 跳过本轮,while 循环继续跑\n\n2. _run_loop 首轮加 '进入 while 循环' 日志\n 快速确认循环启动\n\n3. 新增 concurrent.futures 导入\n\n根因:UIA COM 调用可挂死不返回(如遍历所有顶层窗口时\n某进程无响应),整个 _poll 卡住 → while 循环停转\n→ 无心跳 → 无任何输出 2026-07-26 15:13:09 +08:00
youpaishidifu 5492cdf81b QQ OCR按时间戳分割恢复独立消息
- QQ NT OCR 输出所有可见消息合并为一段无换行文本
- 用re.split捕获组按时间戳(HH:MM或HH:MM:SS)切割
- 每段时间戳之间的文本作为独立消息处理
- 避免"7你好我叫12314:2&15你好我叫12314:42:45SDFI届亻牛有中文吗?"
  整坨变成一条新消息
2026-07-26 14:54:21 +08:00
youpaishidifu 62f6277cf3 修复 stale UnboundLocalError:初始化stal变量在不同路径
- stale 变量仅在 signature-early-return 分支定义
- 正常路径(新消息处理)用到 stale 时报 UnboundLocalError
- 修复:在 signature 检查前初始化 stale=0,两个路径都能访问
2026-07-26 14:46:39 +08:00
youpaishidifu f4c6243944 修复重复处理+新消息不处理:全签名跳过+_seen_messages上限+模糊阈值0.80
1. 全文本签名提前跳过(关键)
   OCR输出与上轮完全一样→立即return,不跑去重循环
   99%场景OCR内容不变,之前却每次都跑模糊匹配→噪声导致漏网

2. _seen_messages上限500条,超了裁到300
   无限增长→新消息模糊匹配时被历史噪声误杀("新消息没处理")
   上限后新消息只和最近300条比,大幅降低误杀率

3. 模糊匹配阈值0.72→0.80
   短文本0.72太松,"你好"vs"你好啊"75%相似就被当成重复
   0.80要求80%重复才跳过,放行真新消息
2026-07-26 14:11:37 +08:00
youpaishidifu e9d9551e3d 修复2个问题:退回裁剪+知识库只回复匹配句\n\n1. 裁剪退回c9acd7e版(cap_left=0.25)\n 0.35只截到时间戳,用户消息被切;0.25覆盖消息文字区域\n\n2. 知识库返回全文→只返回匹配问答段\n 原问题:名字.txt含2个Q&A,TF-IDF整文件匹配后返回全文\n 该方案:knowledge_base._parse_qa_segments解析文件为独立问答段\n 每段作为独立doc,auto_reply._get_answer优先返回doc.answer\n 用户问一句话,只回复对应答句,不塞全部内容 2026-07-26 13:38:04 +08:00
youpaishidifu af3b730106 修复过滤过宽+裁剪范围
1. _is_system_message 中系统模式匹配从 in 改为 startswith
   否则 OCR 捕获的多行合一文本只要包含答:就被整行丢弃
   用户消息你叫啥名字啊?混在文本里一起被杀
2. cap_left 从 25% → 35%
   25% 覆盖到联系人列表,OCR 读出多面板混合文本
   35% 从会话列表偏右到消息面板,减少噪声
3. 保留上轮加的前台切换和 debug 日志
2026-07-26 13:25:21 +08:00
youpaishidifu c9acd7e039 加OCR原始行日志定位过滤空白原因
- filter前用logger.info输出ocr_lines原始内容
- 配合ocr_debug_*.png截图对比,立即知道OCR读到了什么但被哪个filter吃掉
2026-07-26 12:58:29 +08:00
youpaishidifu 6c22b0de5d 修复OCR两个过宽过滤导致真消息被丢弃
1. 纯中文1-15字符正则(第637行)→ 改为仅过滤单字符
   原正则让"你好""你是谁"等真消息全被跳过
2. _is_system_message中"问题"和"回答"子串匹配
   用户说"我有一个问题"也会误杀,删掉,"答:"已够用
2026-07-26 12:37:21 +08:00
youpaishidifu 5de25211a1 OCR左边界30%→25%加大跨度 2026-07-26 12:29:51 +08:00
youpaishidifu 3f14573758 OCR左边界33%→30%继续左移微调 2026-07-26 12:24:42 +08:00
youpaishidifu 3f76bcb7e1 OCR左边界40%→33%继续左移避开自身消息\n\n- cap_left 从 0.40 降到 0.33,幅度更大\n- 目标:只捕获左侧他人消息区域 2026-07-26 12:05:33 +08:00
youpaishidifu ac833664ab OCR截屏前切QQ前台+左边界调到40%
- 截屏前调用 _ensure_foreground 确保 QQ 在最前,避免 CMD 窗口遮挡截入 OCR
- cap_left 从 45% → 40%,进一步左移捕获消息正文
2026-07-26 11:58:49 +08:00
youpaishidifu d07cb59cff OCR裁剪左边界从55%调到45%捕获消息正文而非时间戳
- cap_left 从 55% → 45%,消息文字在消息面板左侧
- 右边界保持 95%,裁剪宽度从 40% 增至 50%
- 注释更新说明
2026-07-26 11:31:29 +08:00
youpaishidifu f0b221f570 OCR截屏保存到根目录用于调试排错
- OCR截取后立即保存图片到程序根目录 (ocr_debug_时间戳.png)
- 自动清理旧文件,仅保留最近20张
- 防止截错区域无法肉眼核实
2026-07-26 11:21:20 +08:00
youpaishidifu acbadb95a7 修复重复处理:加模糊匹配去重兜底
OCR输出每次微小差异(勖彐碎片/行首数字/尾部截断)导致精确去重永远命中不了。
新增 _fuzzy_duplicate 用 difflib.SequenceMatcher.quick_ratio 做相似度去重(阈值0.72),
长度差距>40%直接跳过(quick_ratio上界<阈值)。精确匹配+模糊匹配双重兜底。
2026-07-26 00:45:15 +08:00
youpaishidifu 3da156b916 修复: 删除已移除方法 _read_via_clipboard 的残留调用 2026-07-26 00:25:56 +08:00
youpaishidifu bb85dbdfb1 修复重复处理:OCR去噪 + 剪贴板/读取前台唤醒增强
1. OCR去噪:去掉行首未读红点数字(0)和行尾删除按钮误识别(勖彐),
   同一消息OCR输出稳定,精确去重得以命中,不再重复触发回复
2. 剪贴板垃圾过滤:复用_is_ocr_console_garbage丢弃终端/Python内容,
   解决剪贴板误读控制台输出当消息的问题
3. _ensure_foreground新增AllowSetForegroundWindow(-1),
   读取路径前台唤醒与发送路径一致,减少误复制
2026-07-26 00:12:25 +08:00
youpaishidifu f90e3fbaaf OCR 终极防御:进程验证+最小化检测+垃圾内容过滤
QQ 被杀/最小化后 OCR 截到终端窗口导致死循环回复。
三重防御:
1. _validate_qq_window() — IsWindowVisible+IsIconic+进程名(QT/TIM.exe)验证
2. _is_ocr_console_garbage() — 内容级检测:Python模块名/脚本路径/日志关键词/无中文长文本
3. 连续3次无效自动清缓存清PID防死循环
新增 _cached_pid 字典,与 _cached_hwnd 同步生命周期
2026-07-25 23:30:37 +08:00
youpaishidifu 85b790cb81 修QQ:raw_lines作用域bug+UIA优先生成窗口+剪贴板行数检测 2026-07-25 21:39:23 +08:00
youpaishidifu 3da88da267 补完QQ实时消息:修force_scroll_bottom传参+前台retries=5+UIA兜底前刷新 2026-07-25 20:09:24 +08:00
youpaishidifu 0a8c861603 修TIM剪贴板死循环:_replied_texts永久集+UIA优先+剪贴板行预过滤 2026-07-25 18:19:16 +08:00
youpaishidifu a4b6f05a80 修QQ只读历史消息:剪贴板优先+安全键盘导航Enter+Ctrl+End+前景守卫 2026-07-25 17:38:28 +08:00
youpaishidifu 9cd1e607aa 修TIM全局keybd_event误杀:删Esc键盘导航+PostMessage替代+恢复UIA多层读取 2026-07-25 17:21:16 +08:00
youpaishidifu 7529825357 修QQ读不到消息:恢复键盘导航Esc→Esc→Enter不切会话 2026-07-25 17:09:19 +08:00
youpaishidifu 0927603fc3 修死循环:全局去重+取消QQ键盘导航切会话+过滤系统消息 2026-07-25 16:58:09 +08:00
youpaishidifu 6a96111db6 修复QQ读不到消息+微信前台判定失败(窗口在前台仍报错)\n\n问题1: QQ(TIM)读不到消息\n 根因: _focus_message_area在窗口未前置前SendKeys({Esc})发给错误窗口\n 然后_read_via_clipboard_once只用{Esc}未能聚焦消息显示区\n TIM中{Esc}只退出搜索到会话列表,非消息区域\n 修复: 删_focus_message_area(整个方法窗口未前置时无意义)\n _read_via_clipboard_once中TIM路径改为:\n {Esc}{Esc}退出搜索→{Down}选中对话→{Enter}打开(加载消息区)\n 此时Ctrl+A选中消息内容而非会话列表\n\n问题2: 微信已前置仍报目标窗口不在前台\n 根因: _cached_hwnd存储UIA NativeWindowHandle(可能是子窗口句柄)\n 而GetForegroundWindow()返回顶层窗口句柄→hwnd不匹配\n 修复: _ensure_hwnd存储时加GetAncestor(hwnd,GA_ROOT)确保存顶层句柄\n _ensure_foreground改用root_hwnd判断\n 加SwitchToThisWindow fallback(权限要求比SetForegroundWindow低)\n \n其他: .gitignore加tim_dump.txt 2026-07-25 15:02:26 +08:00
youpaishidifu 0322e2af64 修复QQ抓联系人列表+微信自动回复错发给QQ+重复处理\n\n问题1: QQ/TIM抓会话列表而非消息\n 根因: _click_message_area单次点击(width*0.88)落在联系人/群列表\n 而非消息显示区,导致Ctrl+A复制联系人名而非消息内容\n 修复: _focus_message_area两次SendMessage点击\n 先点会话列表(左15%)选对话→再点消息区(中右60%)聚焦消息\n + Esc前导键退出搜索模式\n\n问题2: 微信自动回复发给QQ\n 根因: _attach_set_foreground静默失败不返回结果\n SendKeys输入到当前前台窗口(QQ)\n 修复: _ensure_foreground使用GetForegroundWindow验证\n 确认目标窗口真正在前台,失败则return False放弃发送\n + 处理托盘/最小化窗口(ShowWindow SW_SHOWNORMAL)\n\n问题3: 重复处理同1条消息\n 根因: QQ每次读到不同联系人名=不同新消息=反复触发\n 修复: ①聚焦消息区后读到稳定消息内容 ②_sending_event锁\n 自动回复发送期间阻止监控轮询,避免焦点被抢\n\n其他: _ensure_hwnd检测QQ NT vs TIM变体\n 用于选择UIA优先或剪贴板优先策略 2026-07-25 14:37:54 +08:00
youpaishidifu cb170d1160 修复知识库短查询不匹配+QQ消息抓不到
问题1: 你叫啥名字→分词["你","叫","啥","名字"]
  → len(t)>=2过滤只剩["名字"]→len(tokens)<=1直接返回空
  修复: 放宽过滤 len(tokens)<=1→len(tokens)==0且len>=2
  添加子串匹配回退: TF-IDF无结果时检查查询是否包含在文档中

问题2: QQ消息抓不到
  _read_via_clipboard 加重试机制(首次空自动重试1次)
  _read_win32_texts 降低文本长度过滤 4→2 字
  QQ路径加 _click_message_area 确保焦点在消息区
2026-07-25 13:56:09 +08:00
youpaishidifu 95b4c8a136 修复PeekMessage找不到+线程未启动就join导致程序崩溃\n\n问题1: ctypes.windll.user32.PeekMessage 在64位Windows上\n 函数名为PeekMessageW(A/W后缀必须带),PeekMessage找不到\n 且消息队列应在daemon线程(调用SetForegroundWindow的线程)创建\n 而非主线程. 移到_run_loop内+改PeekMessageW\n\n问题2: start()在PeekMessage崩溃,self._thread未.start()\n stop()调join()→RuntimeError: cannot join thread before started\n 窗口无法关闭,必须Ctrl+C强杀\n 修复: stop()加is_alive()判断再join 2026-07-25 13:21:23 +08:00
youpaishidifu a0e54805fd 修复QQ读不出/读旧数据/auto-reply错发平台
问题1: QQ读不出消息 — daemon线程SetForegroundWindow频繁失败
   -> _run_loop添加PeekMessage创建Windows消息队列
   -> _attach_set_foreground内部异常全部捕获,不抛给调用者

问题2: QQ读旧剪贴板数据 — PostMessage键盘 Electron不响应
   -> 移除前台跳过检查(降频已足够,20s一次不频繁)
   -> _click_message_area PostMessage->SendMessage(Electron响应同步消息)
   -> 移除_force_scroll_bottom(PostMessage对Electron无效)

问题3: WeChat消息错发给QQ — auto-reply daemon线程SetForegroundWindow失败
   -> auto_reply.on_kb_match不再直接调用_paste_and_send
   -> 改为get_reply_data返回{platform,answer,sender}给主线程
   -> gui.py添加_reply_queue + _flush_reply_queue(主线程after轮询)
   -> _execute_reply在主线程执行_search_contact和_paste_and_send
      (SetForegroundWindow从主线程调用永远可靠)
2026-07-25 13:06:36 +08:00
youpaishidifu 336347d577 修复QQ抢窗口(aacc)+自动回复错发平台
- 删除 _read_via_clipboard_quiet: PostMessage WM_KEYDOWN+ord('A')/'C'
  Electron不识别组合键,输入字面a/c. 废弃该方法
- QQ路径改用 _read_via_clipboard(SetForegroundWindow+SendKeys)
  SendKeys 用 keybd_event,正确模拟 Ctrl+A/C
- 加前台判定: QQ在前台时跳过读取,不抢用户焦点
- _attach_set_foreground 新方法: AttachThreadInput+SetForegroundWindow
  确保 daemon 线程(自动回复)也能正确激活目标窗口
- _search_contact / _paste_and_send / _read_via_clipboard
  全部改用 _attach_set_foreground,修复自动回复错发窗口
2026-07-25 12:31:43 +08:00