teddy 6acdaea9f8 feat(sendmsg, README): 添加微信状态检查和发送结果验证功能
- 在sendmsg.py中实现微信状态检查,确保客户端就绪、已登录及接收者有效性。
- 增强消息和文件发送逻辑,添加发送结果验证,记录详细的发送状态信息。
- 更新README.md,详细描述新增功能和使用方法,包括微信状态检查和多格式图片支持。
2025-08-22 18:02:11 +08:00

324 lines
13 KiB
Python
Raw 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.

from wxauto import WeChat
from datetime import date, datetime, time as dt_time
import sys
import os
import subprocess
from config import CONFIG
import time
from logger_config import setup_logger
# 设置日志记录器
logger = setup_logger('sendmsg')
def check_wechat_status(wx, who):
"""检查微信客户端状态"""
logger.info("=" * 30)
logger.info("微信状态检查开始")
logger.info("=" * 30)
status_info = {
'client_ready': False,
'logged_in': False,
'receiver_exists': False,
'sessions_count': 0,
'contacts_count': 0
}
try:
# 检查微信客户端是否就绪
if wx:
status_info['client_ready'] = True
logger.info("✅ 微信客户端对象创建成功")
else:
logger.error("❌ 微信客户端对象创建失败")
return status_info
# 检查微信是否已登录
try:
if hasattr(wx, 'GetSessionList'):
sessions = wx.GetSessionList()
if sessions:
status_info['logged_in'] = True
status_info['sessions_count'] = len(sessions)
logger.info(f"✅ 微信已登录,当前会话数量: {len(sessions)}")
logger.info(f"📱 会话列表: {sessions[:5]}...") # 只显示前5个
else:
logger.warning("⚠️ 微信已登录但会话列表为空")
else:
logger.warning("⚠️ 无法获取会话列表方法")
except Exception as session_e:
logger.warning(f"⚠️ 无法获取会话列表: {str(session_e)}")
# 检查接收者是否存在
try:
if hasattr(wx, 'GetAllContacts'):
contacts = wx.GetAllContacts()
if contacts:
status_info['contacts_count'] = len(contacts)
logger.info(f"📋 联系人总数: {len(contacts)}")
if who in contacts:
status_info['receiver_exists'] = True
logger.info(f"✅ 接收者 '{who}' 存在于联系人列表中")
else:
logger.warning(f"❌ 接收者 '{who}' 不在联系人列表中")
logger.info(f"📝 可用的联系人: {contacts[:10]}...") # 显示前10个
# 尝试模糊匹配
similar_contacts = [c for c in contacts if who.lower() in c.lower()]
if similar_contacts:
logger.info(f"🔍 找到相似的联系人: {similar_contacts}")
else:
logger.warning("⚠️ 联系人列表为空")
else:
logger.warning("⚠️ 无法获取联系人列表方法")
except Exception as contact_e:
logger.warning(f"⚠️ 无法获取联系人列表: {str(contact_e)}")
# 检查微信窗口状态
try:
if hasattr(wx, 'GetWeChatWindow'):
window = wx.GetWeChatWindow()
if window:
logger.info("✅ 微信窗口已找到")
else:
logger.warning("⚠️ 微信窗口未找到")
else:
logger.warning("⚠️ 无法获取微信窗口方法")
except Exception as window_e:
logger.warning(f"⚠️ 无法获取微信窗口: {str(window_e)}")
# 状态总结
logger.info("=" * 30)
logger.info("微信状态检查总结:")
logger.info(f" 🖥️ 客户端就绪: {'' if status_info['client_ready'] else ''}")
logger.info(f" 🔐 登录状态: {'' if status_info['logged_in'] else ''}")
logger.info(f" 👤 接收者存在: {'' if status_info['receiver_exists'] else ''}")
logger.info(f" 📱 会话数量: {status_info['sessions_count']}")
logger.info(f" 📋 联系人数量: {status_info['contacts_count']}")
logger.info("=" * 30)
return status_info
except Exception as e:
logger.error(f"微信状态检查过程中出现错误: {str(e)}")
logger.error(f"错误类型: {type(e).__name__}")
return status_info
def wait_until_time():
"""等待到配置的发送时间"""
now = datetime.now()
# 从配置文件中读取发送时间
send_time_str = CONFIG['sending_time'] # "17:10"
hour, minute = map(int, send_time_str.split(':'))
target_time = now.replace(hour=hour, minute=minute, second=0, microsecond=0)
# 如果当前时间已经过了今天的发送时间,则设置为明天的发送时间
if now >= target_time:
target_time = target_time.replace(day=target_time.day + 1)
wait_seconds = (target_time - now).total_seconds()
logger.info(f"当前时间: {now.strftime('%Y-%m-%d %H:%M:%S')}")
logger.info(f"目标发送时间: {target_time.strftime('%Y-%m-%d %H:%M:%S')}")
logger.info(f"等待时间: {wait_seconds/3600:.2f} 小时 ({wait_seconds:.0f} 秒)")
time.sleep(wait_seconds)
logger.info("等待完成,开始执行发送操作")
def send_daily_message(count):
"""发送每日消息的主函数"""
logger.info(f"开始执行每日消息发送任务,当前尝试次数: {count}")
today = date.today()
formatted_date = today.strftime('%Y-%m-%d')
# 支持多种图片格式jpg, jpeg, png
file_formats = [".jpg", ".jpeg", ".png"]
# 初始化文件路径变量
file_path = None
file_name = formatted_date + ".jpg"
file_path = CONFIG['file_path'] + file_name
logger.info(f"目标日期: {formatted_date}")
logger.info(f"目标文件: {file_name}")
logger.info(f"完整文件路径: {file_path}")
num = count
if num >= 4:
logger.error("已尝试4次程序将退出")
sys.exit(0) # 直接终止程序
try:
logger.info("尝试初始化微信客户端...")
wx = WeChat()
logger.info("微信客户端初始化完成")
except Exception as e:
logger.error(f"微信客户端初始化失败: {str(e)}")
logger.error(f"错误类型: {type(e).__name__}")
logger.error("可能的原因:")
logger.error(" 1. 微信客户端未启动")
logger.error(" 2. 微信客户端未登录")
logger.error(" 3. wxauto库版本不兼容")
logger.error(" 4. 系统权限不足")
logger.info("尝试发送飞书提醒消息...")
subprocess.run([sys.executable, 'send_openmsg.py'])
if num<4:
logger.info(f"等待60秒后重试当前尝试次数: {num+1}")
time.sleep(60)
num += 1
send_daily_message(num)
else:
logger.error("已尝试4次程序将退出")
sys.exit(0) # 直接终止程序
msg = CONFIG['message']
who = CONFIG['messages_reciever']
logger.info(f"消息内容: {msg}")
logger.info(f"接收者: {who}")
# 使用专门的函数检查微信状态
wechat_status = check_wechat_status(wx, who)
# 如果接收者不存在,给出警告但继续执行
if not wechat_status['receiver_exists']:
logger.warning("⚠️ 接收者不在联系人列表中,但将继续尝试发送")
logger.warning("这可能是因为:")
logger.warning(" 1. 接收者是群聊名称")
logger.warning(" 2. 接收者是特殊联系人(如文件传输助手)")
logger.warning(" 3. 联系人列表获取不完整")
# 依次检查各种格式的文件是否存在
for format in file_formats:
temp_file_name = formatted_date + format
temp_file_path = CONFIG['file_path'] + temp_file_name
if os.path.isfile(temp_file_path):
file_path = temp_file_path
print(f"找到了{format}格式的图片文件!")
break
if file_path and os.path.isfile(file_path):
logger.info("找到了指定文件!")
logger.info(f"文件大小: {os.path.getsize(file_path)} 字节")
# 等待到配置的时间再执行发送操作
wait_until_time()
logger.info("开始发送文件和消息...")
try:
# 发送文件
logger.info(f"正在发送文件: {file_path}")
file_response = wx.SendFiles(filepath=file_path, who=who)
# 检查文件发送结果
if hasattr(file_response, 'success') and file_response.success():
logger.info("文件发送成功")
logger.info(f"文件发送响应: {file_response}")
else:
logger.warning("文件发送可能失败")
logger.warning(f"文件发送响应: {file_response}")
if hasattr(file_response, 'message'):
logger.warning(f"文件发送消息: {file_response.message}")
# 发送消息
logger.info(f"正在发送消息: {msg}")
msg_response = wx.SendMsg(msg=msg, who=who)
# 检查消息发送结果
if hasattr(msg_response, 'success') and msg_response.success():
logger.info("消息发送成功")
logger.info(f"消息发送响应: {msg_response}")
else:
logger.warning("消息发送可能失败")
logger.warning(f"消息发送响应: {msg_response}")
if hasattr(msg_response, 'message'):
logger.warning(f"消息发送消息: {msg_response.message}")
# 综合判断发送结果
file_success = hasattr(file_response, 'success') and file_response.success()
msg_success = hasattr(msg_response, 'success') and msg_response.success()
if file_success and msg_success:
logger.info("🎉 所有内容发送完成!")
logger.info("=" * 50)
logger.info("发送结果总结:")
logger.info(f" 📎 文件发送: {'✅ 成功' if file_success else '❌ 失败'}")
logger.info(f" 💬 消息发送: {'✅ 成功' if msg_success else '❌ 失败'}")
logger.info("=" * 50)
return True
else:
logger.warning("⚠️ 部分内容发送失败")
logger.warning("=" * 50)
logger.warning("发送结果总结:")
logger.warning(f" 📎 文件发送: {'✅ 成功' if file_success else '❌ 失败'}")
logger.warning(f" 💬 消息发送: {'✅ 成功' if msg_success else '❌ 失败'}")
logger.warning("=" * 50)
# 即使部分失败,也记录为成功(因为至少发送了部分内容)
if file_success or msg_success:
logger.info("由于部分内容发送成功,记录为成功")
return True
else:
logger.error("所有内容发送失败,需要重试")
raise Exception("文件发送和消息发送都失败了")
except Exception as e:
logger.error(f"发送过程中出现错误: {str(e)}")
logger.error(f"错误类型: {type(e).__name__}")
# 记录详细的错误信息
if 'file_response' in locals():
logger.error(f"文件发送响应详情: {file_response}")
if 'msg_response' in locals():
logger.error(f"消息发送响应详情: {msg_response}")
# 发送失败时也尝试发送飞书提醒
logger.info("尝试发送飞书提醒消息...")
subprocess.run([sys.executable, 'send_filemsg.py'])
if num<4:
logger.info(f"等待60秒后重试当前尝试次数: {num+1}")
time.sleep(60)
num += 1
send_daily_message(num)
else:
logger.error("已尝试4次程序将退出")
sys.exit(0)
else:
print("没找到任何支持格式的图片文件(.jpg, .jpeg, .png)")
logger.warning(f"没找到指定文件: {file_path}")
logger.info("尝试发送飞书提醒消息...")
subprocess.run([sys.executable, 'send_filemsg.py'])
if num<4:
time.sleep(1800)
logger.info(f"等待60秒后重试当前尝试次数: {num+1}")
time.sleep(60)
num += 1
send_daily_message(num)
else:
logger.error("已尝试4次程序将退出")
sys.exit(0) # 直接终止程序
# 如果直接运行此脚本,执行发送消息功能
if __name__ == "__main__":
logger.info("=" * 50)
logger.info("开始执行微信消息发送程序")
logger.info("=" * 50)
count = 0
try:
send_daily_message(count)
logger.info("程序执行完成")
except Exception as e:
logger.error(f"程序执行过程中出现未捕获的异常: {str(e)}")
logger.error(f"异常类型: {type(e).__name__}")
import traceback
logger.error(f"异常堆栈: {traceback.format_exc()}")
sys.exit(1)