添加自动发送祝福语功能和坐标配置

This commit is contained in:
2026-03-03 11:05:33 +08:00
parent 415ec18182
commit 024950e9fb
10 changed files with 514 additions and 25 deletions

270
auto_send_blessing.py Normal file
View File

@@ -0,0 +1,270 @@
# -*- 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()