# -*- coding: utf-8 -*- """ 微信自动发送祝福语脚本 功能: 1. 从API获取已选联系人的搜索姓名和祝福语 2. 自动搜索联系人、发送祝福语 3. 发送完成后更新前端状态 4. 按 F9 停止运行 """ import os import sys import time import json import threading import requests import pyautogui import pyperclip from ctypes import windll, c_long # 坐标配置 SEARCH_BOX_X, SEARCH_BOX_Y = 1933, 39 SEARCH_RESULT_X, SEARCH_RESULT_Y = 2009, 100 CHAT_INPUT_X, CHAT_INPUT_Y = 2160, 1173 # API配置 API_BASE = 'http://localhost:5000/api' # 全局停止标志 stop_flag = False stop_lock = threading.Lock() def get_selected_contacts(): """获取已选择的联系人""" try: response = requests.get(f'{API_BASE}/contacts?page=1&page_size=1000', timeout=10) data = response.json() selected = [c for c in data.get('contacts', []) if c.get('selected')] return selected except Exception as e: print(f"获取联系人失败: {e}") return [] def update_contact_sent(contact_id): """更新联系人发送状态""" try: requests.put( f'{API_BASE}/contacts/{contact_id}', json={'selected': False}, timeout=10 ) return True except Exception as e: print(f"更新状态失败: {e}") return False def check_stop(): """检查是否需要停止""" with stop_lock: return stop_flag def set_stop(): """设置停止标志""" with stop_lock: global stop_flag stop_flag = True print("\n收到停止信号,正在停止...") def get_current_key(): """获取当前按下的键""" try: # 使用windll获取按键状态 # F9 = 0x78 (120) if windll.user32.GetAsyncKeyState(0x78) & 0x8000: return 'F9' except: pass return None def wait_for_key_press(): """监听F9按键""" global stop_flag import keyboard try: keyboard.add_hotkey('F9', set_stop) print("提示: 按 F9 可随时停止运行") except ImportError: print("警告: keyboard库未安装,无法使用F9停止功能") print("请运行: pip install keyboard") def send_blessing_to_contact(search_name, blessing): """发送祝福语给单个联系人""" if check_stop(): return False, "已停止" try: # 1. 点击搜索框 print(f" → 点击搜索框 ({SEARCH_BOX_X}, {SEARCH_BOX_Y})") pyautogui.moveTo(SEARCH_BOX_X, SEARCH_BOX_Y, duration=0.3) pyautogui.click() time.sleep(0.5) if check_stop(): return False, "已停止" # 2. 清空搜索框并输入名字 print(f" → 输入名字: {search_name}") pyautogui.hotkey('ctrl', 'a') time.sleep(0.2) pyperclip.copy(search_name) pyautogui.hotkey('ctrl', 'v') time.sleep(1) if check_stop(): return False, "已停止" # 3. 点击搜索结果 print(f" → 点击搜索结果 ({SEARCH_RESULT_X}, {SEARCH_RESULT_Y})") pyautogui.moveTo(SEARCH_RESULT_X, SEARCH_RESULT_Y, duration=0.3) pyautogui.click() time.sleep(1) if check_stop(): return False, "已停止" # 4. 点击聊天输入框 print(f" → 点击聊天输入框 ({CHAT_INPUT_X}, {CHAT_INPUT_Y})") pyautogui.moveTo(CHAT_INPUT_X, CHAT_INPUT_Y, duration=0.3) pyautogui.click() time.sleep(0.5) if check_stop(): return False, "已停止" # 5. 输入祝福语 print(f" → 输入祝福语...") pyperclip.copy(blessing) pyautogui.hotkey('ctrl', 'v') time.sleep(0.5) if check_stop(): return False, "已停止" # 6. 发送 print(f" → 发送消息") pyautogui.press('enter') time.sleep(0.5) return True, "发送成功" except Exception as e: return False, f"发送失败: {str(e)}" def main(): global stop_flag print("=" * 60) print("微信自动发送祝福语脚本") print("=" * 60) print() print("配置信息:") print(f" 搜索框坐标: ({SEARCH_BOX_X}, {SEARCH_BOX_Y})") print(f" 搜索结果坐标: ({SEARCH_RESULT_X}, {SEARCH_RESULT_Y})") print(f" 聊天输入框坐标: ({CHAT_INPUT_X}, {CHAT_INPUT_Y})") print() # 尝试导入keyboard库用于F9停止 try: import keyboard keyboard.add_hotkey('F9', set_stop) print("✓ F9 停止功能已启用") except ImportError: print("✗ keyboard库未安装,F9停止功能不可用") print(" 请运行: pip install keyboard") except Exception as e: print(f"✗ keyboard库加载失败: {e}") print() # 获取已选联系人 print("正在获取已选联系人...") contacts = get_selected_contacts() if not contacts: print("没有找到已选择的联系人!") print("请在前端页面勾选要发送的联系人,然后重试。") return print(f"找到 {len(contacts)} 个已选联系人:") print("-" * 60) for i, c in enumerate(contacts, 1): print(f" {i}. {c.get('name', '未知')} (搜索名: {c.get('search_name', '')})") print("-" * 60) print() # 确认开始 print("准备开始发送祝福语...") print("请在 5 秒内切换到微信窗口!") print() # 等待用户准备 for i in range(5, 0, -1): if check_stop(): print("已取消运行") return print(f" {i}...") time.sleep(1) print() print("开始发送祝福语...") print("=" * 60) success_count = 0 fail_count = 0 skip_count = 0 for i, contact in enumerate(contacts, 1): if check_stop(): print("\n用户停止运行") break name = contact.get('name', '未知') search_name = contact.get('search_name') or contact.get('name', '') blessing = contact.get('blessing', '') contact_id = contact.get('id') print(f"\n[{i}/{len(contacts)}] 发送给: {name}") print(f" 搜索名: {search_name}") if len(blessing) > 50: print(f" 祝福语: {blessing[:50]}...") else: print(f" 祝福语: {blessing}") # 检查祝福语是否为空 if not blessing: print(f" ⚠ 跳过: 祝福语为空") skip_count += 1 continue # 发送祝福语 success, message = send_blessing_to_contact(search_name, blessing) if success: print(f" ✓ 发送成功") success_count += 1 # 更新前端状态 if update_contact_sent(contact_id): print(f" ✓ 已更新前端状态") else: print(f" ✗ 更新前端状态失败") # 发送间隔 time.sleep(1) else: print(f" ✗ {message}") fail_count += 1 if not check_stop(): time.sleep(2) print() print("=" * 60) print("发送完成!") print("=" * 60) print(f" 成功: {success_count}") print(f" 失败: {fail_count}") print(f" 跳过: {skip_count}") print() if __name__ == '__main__': main()