"""Cookie 监控主程序""" import time from datetime import datetime from urllib.parse import urlparse from cookie_cloud import CookieCloud from notification import create_notification_manager from config_manager import ConfigManager, CookieDataManager from browser_manager import BrowserManager from logger import get_logger logger = get_logger(__name__) NOTIFY_TIMES = [6, 22] STATE_FILE = "notify_state.json" def load_notify_state() -> dict: """加载通知状态""" import json import os if os.path.exists(STATE_FILE): try: with open(STATE_FILE, 'r', encoding='utf-8') as f: return json.load(f) except: pass return {} def save_notify_state(state: dict): """保存通知状态""" import json try: with open(STATE_FILE, 'w', encoding='utf-8') as f: json.dump(state, f, indent=2, ensure_ascii=False) except Exception as e: logger.error(f"保存通知状态失败: {e}") def should_send_notification(user_name: str) -> bool: """判断是否应该发送通知""" return False def mark_notification_sent(user_name: str): """标记通知已发送""" now = datetime.now() state = load_notify_state() if user_name not in state: state[user_name] = {} state[user_name]['date'] = now.strftime('%Y-%m-%d') state[user_name]['hour'] = now.hour save_notify_state(state) class CookieMonitor: """Cookie 监控器""" def __init__(self, config_file: str = "config.json"): """ 初始化监控器 Args: config_file: 配置文件路径 """ self.config_manager = ConfigManager(config_file) self.cookie_data_manager = CookieDataManager() self.all_results = [] def process_user(self, user_config: dict): """ 处理单个用户:依次验证各网站登录状态 Args: user_config: 用户配置字典 """ user_name = user_config.get('name', '未知用户') logger.info(f"{'='*20} 开始处理用户: {user_name} {'='*20}") websites = user_config.get('websites', []) if not websites: logger.info(f"用户 {user_name} 没有配置网站,跳过") return browser_config = user_config.get('browser', {}) browser = BrowserManager( browser_type=browser_config.get('type', 'edge'), headless=browser_config.get('headless', False) ) user_results = { 'user_name': user_name, 'notification_config': user_config.get('notification', {}), 'websites': [], 'success_count': 0, 'fail_count': 0 } try: logger.info(f"步骤1: 从本地 cookie_data.json 读取用户 cookies") local_cookies = self.cookie_data_manager.get_user_cookies(user_name) logger.info(f"步骤1.5: 从 Cookie Cloud 获取所有 cookies") cookie_cloud_config = user_config.get('cookie_cloud', {}) cookie_cloud = CookieCloud( api_url=cookie_cloud_config.get('api_url', ''), uuid=cookie_cloud_config.get('uuid', ''), password=cookie_cloud_config.get('password', '') ) all_cookies = cookie_cloud.get_cookies() total_domains = len(all_cookies) total_cookies = sum(len(c) for c in all_cookies.values()) logger.info(f"获取到 {total_domains} 个域名,共 {total_cookies} 个 cookie") logger.info(f"步骤2: 初始化浏览器") browser.init_browser() logger.info(f"步骤3: 依次验证各网站登录状态") for website in websites: result = self.process_website( user_name=user_name, website_config=website, browser=browser, all_cookies=all_cookies, local_cookies=local_cookies ) user_results['websites'].append(result) if result['success']: user_results['success_count'] += 1 else: user_results['fail_count'] += 1 self.all_results.append(user_results) self._print_summary(user_name, user_results['websites']) logger.info(f"\n检查用户 {user_name} 是否需要发送通知") if should_send_notification(user_name): self._send_user_notification(user_results) finally: browser.close() def process_website( self, user_name: str, website_config: dict, browser: BrowserManager, all_cookies: dict, local_cookies: dict ) -> dict: """ 验证网站登录状态 Args: user_name: 用户名 website_config: 网站配置 browser: 浏览器管理器 all_cookies: 所有cookies local_cookies: 本地cookies Returns: 验证结果字典 """ website_name = website_config.get('name', '未知网站') url = website_config.get('url', '') check_selector = website_config.get('login_check_selector', '') success_text = website_config.get('success_text', '') logger.info(f"\n验证网站: {website_name}") logger.info(f" URL: {url}") result = { 'name': website_name, 'url': url, 'success': False, 'error': '' } if not url: result['error'] = 'URL 未配置' logger.error(f" 失败: {result['error']}") return result try: parsed = urlparse(url) domain = parsed.netloc domain_cookies = [] for cookie_domain, cookie_data in local_cookies.items(): clean_domain = cookie_domain.lstrip('.') if domain in clean_domain or clean_domain in domain: if isinstance(cookie_data, dict): cookies = cookie_data.get('cookies', []) elif isinstance(cookie_data, list): cookies = cookie_data else: cookies = [] domain_cookies.extend(cookies) if domain_cookies: logger.info(f" 找到 {len(domain_cookies)} 个本地 cookie") success_count = browser.import_cookies(domain_cookies, domain) logger.info(f" 成功导入 {success_count} 个 cookie") else: logger.warning(f" 未找到本地 cookie") login_success = browser.verify_login( url=url, check_selector=check_selector, success_text=success_text ) if login_success: result['success'] = True logger.info(f" ✓ 使用本地 cookie 登录验证成功") if domain_cookies: logger.info(f" 保存 {len(domain_cookies)} 个 cookie 到本地文件") self.cookie_data_manager.save_user_cookies( user_name=user_name, cookies=domain_cookies, url=url, website_name=website_name ) else: logger.warning(f" 登录验证成功但 cookies 为空,跳过保存") else: logger.warning(f" ✗ 本地 cookie 登录失败,尝试使用服务器 cookie") domain_cookies = [] for cookie_domain, cookie_data in all_cookies.items(): clean_domain = cookie_domain.lstrip('.') if domain in clean_domain or clean_domain in domain: if isinstance(cookie_data, dict): cookies = cookie_data.get('cookies', []) elif isinstance(cookie_data, list): cookies = cookie_data else: cookies = [] domain_cookies.extend(cookies) if domain_cookies: logger.info(f" 找到 {len(domain_cookies)} 个服务器 cookie") success_count = browser.import_cookies(domain_cookies, domain) logger.info(f" 成功导入 {success_count} 个 cookie") else: logger.warning(f" 未找到服务器 cookie") login_success = browser.verify_login( url=url, check_selector=check_selector, success_text=success_text ) if login_success: result['success'] = True logger.info(f" ✓ 使用服务器 cookie 登录验证成功") if domain_cookies: logger.info(f" 保存 {len(domain_cookies)} 个 cookie 到本地文件") self.cookie_data_manager.save_user_cookies( user_name=user_name, cookies=domain_cookies, url=url, website_name=website_name ) else: logger.warning(f" 登录验证成功但 cookies 为空,跳过保存") else: result['error'] = '登录状态验证失败(本地和服务器 cookie 都无效)' logger.warning(f" ✗ {result['error']}") except Exception as e: result['error'] = f'处理异常: {str(e)}' logger.error(f" 异常: {e}") return result def _print_summary(self, user_name: str, results: list): """打印处理结果汇总""" success_count = sum(1 for r in results if r['success']) fail_count = len(results) - success_count logger.info(f"\n{'='*20} 用户 {user_name} 处理结果汇总 {'='*20}") logger.info(f"总网站数: {len(results)}") logger.info(f"成功: {success_count}, 失败: {fail_count}") if fail_count > 0: logger.info("\n失败详情:") for r in results: if not r['success']: logger.info(f" - {r['name']}: {r['error']}") def _send_user_notification(self, user_result: dict): """发送单个用户的通知""" user_name = user_result['user_name'] notification_config = user_result.get('notification_config', {}) notifier = create_notification_manager(notification_config) if not notifier: logger.warning(f"用户 {user_name} 未配置通知") return success_count = user_result['success_count'] fail_count = user_result['fail_count'] title = f"【Cookie监控】{user_name} - 成功{success_count} 失败{fail_count}" content_lines = [ f"**{user_name} Cookie监控报告**", f"", f"监控时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}", f"成功: {success_count} 个网站", f"失败: {fail_count} 个网站", f"", ] for website in user_result['websites']: status = "✓ 成功" if website['success'] else f"✗ 失败: {website['error']}" content_lines.append(f" {website['name']}: {status}") content = "\n".join(content_lines) logger.info(f"\n发送用户通知: {user_name}") logger.info(f"Title: {title}") if notifier.send(title, content): logger.info(f"✓ 用户 {user_name} 通知发送成功") mark_notification_sent(user_name) else: logger.error(f"✗ 用户 {user_name} 通知发送失败") def run(self): """运行监控""" logger.info("="*50) logger.info("Cookie 监控开始") logger.info(f"时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}") logger.info("="*50) users = self.config_manager.get_users() if not users: logger.error("未找到用户配置") return for user_config in users: try: self.process_user(user_config) except Exception as e: logger.error(f"处理用户失败: {e}") logger.info("\n" + "="*50) logger.info("Cookie 监控结束") logger.info("="*50) def main(): """主函数""" from logger import setup_logging setup_logging() monitor = CookieMonitor() monitor.run() if __name__ == "__main__": main()