import asyncio import sys # Windows平台特殊处理,强制使用SelectorEventLoop if sys.platform.startswith('win'): asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy()) from typing import Dict, List from core.config import Config from core.database import DatabaseManager from core.logger import setup_logger from register.register_worker import RegisterWorker from register.host_register_worker import HostRegisterWorker from services.email_manager import EmailManager from services.fetch_manager import FetchManager from services.proxy_pool import ProxyPool from services.token_pool import TokenPool from services.self_hosted_email import SelfHostedEmail from upload_account import AccountUploader from auto_cursor_service import AutoCursorService class CursorRegister: def __init__(self): self.config = Config.from_yaml() self.logger = setup_logger(self.config) self.db_manager = DatabaseManager(self.config) self.fetch_manager = FetchManager(self.config) self.proxy_pool = ProxyPool(self.config, self.fetch_manager) self.token_pool = TokenPool(self.config) # 初始化常规邮箱服务 self.email_manager = EmailManager(self.config, self.db_manager) self.register_worker = RegisterWorker( self.config, self.fetch_manager, self.email_manager ) # 初始化自建邮箱服务(如果配置了) self.self_hosted_email = None self.host_register_worker = None if hasattr(self.config, 'self_hosted_email_config') and self.config.self_hosted_email_config: self.self_hosted_email = SelfHostedEmail( self.fetch_manager, self.config.self_hosted_email_config.api_base_url, self.config.self_hosted_email_config.api_key ) self.logger.info("自建邮箱服务已初始化") # 初始化自建邮箱注册工作器 self.host_register_worker = HostRegisterWorker( self.config, self.fetch_manager, self.self_hosted_email ) self.logger.info("自建邮箱注册工作器已初始化") async def initialize(self): """初始化数据库""" await self.db_manager.initialize() # 确保EmailManager完成初始化 await self.email_manager.initialize() async def cleanup(self): """清理资源""" await self.db_manager.cleanup() async def batch_register(self, num: int): """批量注册""" try: self.logger.info(f"开始批量注册 {num} 个账号") # 1. 先获取token对 token_pairs = await self.token_pool.batch_generate(num) if not token_pairs: self.logger.error("获取token失败,终止注册") return [] actual_num = len(token_pairs) # 根据实际获取到的token对数量调整注册数量 if actual_num < num: self.logger.warning(f"只获取到 {actual_num} 对token,将减少注册数量") num = actual_num # 2. 获取邮箱账号 email_accounts = await self.email_manager.batch_get_accounts(num) if len(email_accounts) < num: self.logger.warning(f"可用邮箱账号不足,仅获取到 {len(email_accounts)} 个") num = len(email_accounts) # 3. 获取代理 proxies = await self.proxy_pool.batch_get(num) # 在关键位置添加详细日志 self.logger.debug(f"代理列表: {proxies}") self.logger.debug(f"邮箱账号: {[a.email for a in email_accounts]}") self.logger.debug(f"尝试使用的token对数量: {len(token_pairs)}") # 4. 创建注册任务 tasks = [] for account, proxy, token_pair in zip(email_accounts, proxies, token_pairs): task = self.register_worker.register(proxy, token_pair, account) tasks.append(task) # 5. 并发执行 results = await asyncio.gather(*tasks, return_exceptions=True) # 6. 处理结果 successful = [] failed = [] skipped = 0 for i, result in enumerate(results): if isinstance(result, Exception): self.logger.error(f"注册任务 {i+1} 失败: {str(result)}") failed.append(str(result)) elif result is None: # 跳过的账号 skipped += 1 else: try: # 更新数据库 await self.email_manager.update_account( result['account_id'], result['cursor_password'], result['cursor_cookie'], result['cursor_jwt'] ) self.logger.debug(f"更新数据库成功 - 账号ID: {result['account_id']}") successful.append(result) except Exception as e: self.logger.error(f"更新数据库失败 - 账号ID: {result['account_id']}, 错误: {str(e)}") failed.append(str(e)) self.logger.info(f"注册完成: 成功 {len(successful)}, 失败 {len(failed)}, 跳过 {skipped}") return successful except Exception as e: self.logger.error(f"批量注册失败: {str(e)}") return [] async def _process_results(self, results: List[Dict]): """处理注册结果""" successful = [] failed = [] for result in results: if isinstance(result, Exception): failed.append(str(result)) else: # 更新数据库 await self.email_manager.update_account( result['account_id'], result['cursor_password'], result['cursor_cookie'] ) successful.append(result) print(f"Successfully registered: {len(successful)}") print(f"Failed registrations: {len(failed)}") return successful async def batch_register_with_host(self, num: int): """使用自建邮箱批量注册""" if not self.host_register_worker: self.logger.error("未配置自建邮箱注册工作器,无法继续") return [] try: self.logger.info(f"开始使用自建邮箱批量注册 {num} 个账号") # 1. 获取token对 token_pairs = await self.token_pool.batch_generate(num) if not token_pairs: self.logger.error("获取token失败,终止注册") return [] actual_num = len(token_pairs) if actual_num < num: self.logger.warning(f"只获取到 {actual_num} 对token,将减少注册数量") num = actual_num # 2. 获取代理 proxies = await self.proxy_pool.batch_get(num) self.logger.debug(f"代理列表: {proxies}") self.logger.debug(f"尝试使用的token对数量: {len(token_pairs)}") # 3. 创建注册任务 tasks = [] for proxy, token_pair in zip(proxies, token_pairs): task = self.host_register_worker.register(proxy, token_pair) tasks.append(task) # 4. 并发执行 results = await asyncio.gather(*tasks, return_exceptions=True) # 5. 处理结果 successful = [] failed = [] skipped = 0 for i, result in enumerate(results): if isinstance(result, Exception): self.logger.error(f"注册任务 {i+1} 失败: {str(result)}") failed.append(str(result)) elif result is None: skipped += 1 else: successful.append(result) # 添加详细的账号信息日志 self.logger.info("=" * 50) self.logger.info(f"账号 {i+1} 注册成功:") self.logger.info(f"邮箱: {result['email']}") if 'email_password' in result and result['email_password']: self.logger.info(f"邮箱密码: {result['email_password']}") else: self.logger.info("邮箱密码: (无)") self.logger.info(f"Cursor密码: {result['cursor_password']}") # 只显示token的前30个字符,避免日志过长 token = result.get('cursor_jwt', '') if token: self.logger.info(f"Token: {token[:30]}...") self.logger.info("=" * 50) # 6. 直接上传成功注册的账号 if successful: try: service = AutoCursorService() await service.initialize() # 准备上传数据 upload_data = [] for account in successful: upload_item = { "email": account["email"], "password": account.get("email_password", ""), # 使用get并提供默认值 "cursor_password": account["cursor_password"], "cursor_cookie": account["cursor_cookie"], "cursor_jwt": account.get("cursor_jwt", "") } upload_data.append(upload_item) # 上传账号 await service.upload_accounts(upload_data) await service.cleanup() self.logger.info(f"成功上传 {len(upload_data)} 个账号到服务器") except Exception as e: self.logger.error(f"上传账号时发生错误: {str(e)}") self.logger.info(f"注册完成: 成功 {len(successful)}, 失败 {len(failed)}, 跳过 {skipped}") return successful except Exception as e: self.logger.error(f"批量注册失败: {str(e)}") return [] async def main(): register = CursorRegister() await register.initialize() try: batch_size = register.config.register_config.batch_size total_registered = 0 # 直接使用自建邮箱模式,不再检查配置 register.logger.info("使用自建邮箱模式") # 确保已初始化自建邮箱服务 if not register.host_register_worker: register.logger.error("自建邮箱注册工作器未初始化,请检查配置") return # 自建邮箱模式,直接执行自建邮箱批量注册 while True: register.logger.info(f"开始新一轮自建邮箱批量注册,批次大小: {batch_size}") results = await register.batch_register_with_host(batch_size) # 统计结果 successful = len(results) total_registered += successful register.logger.info(f"当前总进度: 已注册 {total_registered} 个账号") # 批次之间的间隔 await asyncio.sleep(5) # 如果本批次注册失败率过高,暂停一段时间 if successful < batch_size * 0.5 and successful > 0: # 成功率低于50%但不为零 register.logger.warning("本批次成功率过低,暂停60秒后继续") await asyncio.sleep(60) elif successful == 0 and batch_size > 0: # 完全失败 register.logger.error("本批次完全失败,可能存在系统问题,暂停120秒后继续") await asyncio.sleep(120) # 让用户决定是否继续 try: answer = input("是否继续下一批注册? (y/n): ").strip().lower() if answer != 'y': register.logger.info("用户选择停止注册") break except Exception: # 如果在非交互环境中运行,默认继续 pass except Exception as e: register.logger.error(f"程序执行出错: {str(e)}") finally: register.logger.info(f"程序结束,总共成功注册 {total_registered} 个账号") await register.cleanup() if __name__ == "__main__": asyncio.run(main())