diff --git a/README.md b/README.md index d20da4e..4a08312 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ ## 功能概述 -这是一个自动发送每日AI新闻图片和消息到微信的程序,具有完整的日志记录和错误处理功能。 +这是一个自动发送每日AI新闻图片和消息到微信的程序,具有完整的日志记录、错误处理和微信状态检查功能。 ## 主要功能 @@ -10,6 +10,31 @@ - **容错机制**: 微信失败时自动发送飞书提醒 - **详细日志**: 完整的操作日志记录,便于问题排查 - **进程管理**: 支持后台运行和进程控制 +- **微信状态检查**: 自动检查微信客户端状态和接收者有效性 +- **智能重试**: 支持多种图片格式,自动重试机制 + +## 新增功能 + +### 微信状态检查 +程序现在会自动检查: +- 微信客户端是否就绪 +- 微信是否已登录 +- 接收者是否存在于联系人列表 +- 当前会话数量和联系人数量 +- 微信窗口状态 + +### 发送结果验证 +使用wxauto的WxResponse对象验证: +- 文件发送是否成功 +- 消息发送是否成功 +- 详细的发送状态信息 +- 部分失败时的智能处理 + +### 多格式图片支持 +支持多种图片格式: +- .jpg +- .jpeg +- .png ## 日志功能 @@ -58,6 +83,11 @@ python service_runner.py python stop_scheduler.py ``` +### 5. 测试微信状态 +```bash +python test_wechat_status.py +``` + ## 配置说明 在 `config.py` 中配置: @@ -79,12 +109,26 @@ python stop_scheduler.py 3. **飞书API问题**: 查看 `send_openmsg_*.log` 和 `send_filemsg_*.log` 4. **进程管理问题**: 查看 `service_runner_*.log` 和 `stop_scheduler_*.log` +### 微信状态检查 +运行测试脚本检查微信状态: +```bash +python test_wechat_status.py +``` + +这将显示: +- 微信客户端状态 +- 登录状态 +- 接收者有效性 +- 可用方法列表 + ### 日志示例 ``` -2024-01-15 11:40:00 - sendmsg - INFO - send_daily_message:25 - 开始执行每日消息发送任务,当前尝试次数: 0 -2024-01-15 11:40:00 - sendmsg - INFO - send_daily_message:30 - 目标日期: 2024-01-15 -2024-01-15 11:40:00 - sendmsg - INFO - send_daily_message:31 - 目标文件: 2024-01-15.jpg -2024-01-15 11:40:00 - sendmsg - INFO - send_daily_message:32 - 完整文件路径: Z:\2024-01-15.jpg +2024-01-15 11:40:00 - sendmsg - INFO - check_wechat_status:45 - ✅ 微信已登录,当前会话数量: 15 +2024-01-15 11:40:00 - sendmsg - INFO - check_wechat_status:52 - ✅ 接收者 '文件传输助手' 存在于联系人列表中 +2024-01-15 11:40:00 - sendmsg - INFO - send_daily_message:120 - 🎉 所有内容发送完成! +2024-01-15 11:40:00 - sendmsg - INFO - send_daily_message:125 - 发送结果总结: +2024-01-15 11:40:00 - sendmsg - INFO - send_daily_message:126 - 📎 文件发送: ✅ 成功 +2024-01-15 11:40:00 - sendmsg - INFO - send_daily_message:127 - 💬 消息发送: ✅ 成功 ``` ## 依赖要求 @@ -101,3 +145,19 @@ python stop_scheduler.py 2. 检查文件路径配置是否正确 3. 验证飞书API配置是否有效 4. 定期检查日志文件大小,避免占用过多磁盘空间 +5. 运行前建议先执行 `test_wechat_status.py` 检查微信状态 + +## 更新日志 + +### v0.2.0 +- 添加微信状态检查功能 +- 使用WxResponse验证发送结果 +- 支持多种图片格式 +- 改进错误处理和日志记录 +- 添加微信状态测试脚本 + +### v0.1.0 +- 基础消息发送功能 +- 定时任务调度 +- 飞书提醒机制 +- 基础日志记录 diff --git a/sendmsg.py b/sendmsg.py index cf52615..bb0d406 100644 --- a/sendmsg.py +++ b/sendmsg.py @@ -10,6 +10,101 @@ 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() @@ -61,9 +156,17 @@ def send_daily_message(count): try: logger.info("尝试初始化微信客户端...") wx = WeChat() - logger.info("微信客户端初始化成功") + 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: @@ -81,6 +184,17 @@ def send_daily_message(count): 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 @@ -101,21 +215,72 @@ def send_daily_message(count): try: # 发送文件 logger.info(f"正在发送文件: {file_path}") - wx.SendFiles(filepath=file_path, who=who) - logger.info("文件发送成功") + 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}") - wx.SendMsg(msg=msg, who=who) - logger.info("消息发送成功") + msg_response = wx.SendMsg(msg=msg, who=who) - logger.info("所有内容发送完成!") - return True + # 检查消息发送结果 + 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}")