"""消息通知模块 - 通过爱语飞飞发送通知""" import requests from typing import Optional from applogger import get_logger logger = get_logger(__name__) class IYUUNotifier: """爱语飞飞通知客户端""" def __init__(self, token: str): """ 初始化爱语飞飞通知客户端 Args: token: 爱语飞飞令牌 """ self.token = token self.api_url = f"https://iyuu.cn/{token}.send" def send(self, title: str, content: str) -> bool: """ 发送通知 Args: title: 通知标题 content: 通知内容 Returns: 是否发送成功 """ try: response = requests.get( self.api_url, params={ 'text': title, 'desp': content }, timeout=10 ) response.raise_for_status() result = response.json() if result.get('errcode') == 0: return True else: logger.error(f"发送通知失败: {result.get('errmsg')}") return False except requests.RequestException as e: logger.error(f"发送通知请求失败: {e}") return False except Exception as e: logger.error(f"发送通知异常: {e}") return False class FailureTracker: """失败次数追踪器""" def __init__(self, state_file: str): """ 初始化失败次数追踪器 Args: state_file: 状态文件路径 """ self.state_file = state_file self.state = self._load_state() def _load_state(self) -> dict: """加载状态文件""" import json import os if os.path.exists(self.state_file): try: with open(self.state_file, 'r', encoding='utf-8') as f: return json.load(f) except Exception as e: logger.error(f"加载状态文件失败: {e}") return {} def _save_state(self): """保存状态文件""" import json try: with open(self.state_file, 'w', encoding='utf-8') as f: json.dump(self.state, f, indent=2, ensure_ascii=False) except Exception as e: logger.error(f"保存状态文件失败: {e}") def get_fail_count(self, user_name: str, website_name: str) -> int: """ 获取指定网站的失败次数 Args: user_name: 用户名 website_name: 网站名 Returns: 失败次数 """ key = f"{user_name}_{website_name}" return self.state.get(key, 0) def increment_fail_count(self, user_name: str, website_name: str) -> int: """ 增加失败次数 Args: user_name: 用户名 website_name: 网站名 Returns: 增加后的失败次数 """ key = f"{user_name}_{website_name}" self.state[key] = self.state.get(key, 0) + 1 self._save_state() return self.state[key] def reset_fail_count(self, user_name: str, website_name: str): """ 重置失败次数 Args: user_name: 用户名 website_name: 网站名 """ key = f"{user_name}_{website_name}" self.state[key] = 0 self._save_state() def check_and_notify( self, user_name: str, website_name: str, max_fail_count: int, notifier: Optional[IYUUNotifier], error_msg: str ) -> bool: """ 检查失败次数并在达到阈值时发送通知 Args: user_name: 用户名 website_name: 网站名 max_fail_count: 最大失败次数 notifier: 爱语飞飞通知客户端 error_msg: 错误信息 Returns: 是否应该停止重试 """ fail_count = self.increment_fail_count(user_name, website_name) if fail_count >= max_fail_count: # 发送通知 if notifier: title = f"【Cookie监控】{user_name} - {website_name} 登录失败" content = f"网站: {website_name}\n用户: {user_name}\n连续失败次数: {fail_count}\n错误信息: {error_msg}" if notifier.send(title, content): logger.info(f"已发送失败通知: {user_name} - {website_name}") else: logger.error(f"发送失败通知失败: {user_name} - {website_name}") # 重置失败计数 self.reset_fail_count(user_name, website_name) return True return False if __name__ == "__main__": # 测试代码 tracker = FailureTracker("state.json") # 增加失败次数 count = tracker.increment_fail_count("测试用户", "测试网站") logger.info(f"当前失败次数: {count}") # 检查并发送通知(需要真实的爱语飞飞令牌) # notifier = IYUUNotifier("您的爱语飞飞令牌") # tracker.check_and_notify("测试用户", "测试网站", 3, notifier, "测试错误信息")