Files
cookie/notifier.py
2026-03-02 17:02:09 +08:00

189 lines
5.3 KiB
Python

"""消息通知模块 - 通过爱语飞飞发送通知"""
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, "测试错误信息")