Files
auto_cursor/main.py

317 lines
13 KiB
Python
Raw Normal View History

2025-03-27 10:20:06 +08:00
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
2025-04-07 13:14:29 +08:00
from register.host_register_worker import HostRegisterWorker
2025-03-27 10:20:06 +08:00
from services.email_manager import EmailManager
from services.fetch_manager import FetchManager
from services.proxy_pool import ProxyPool
from services.token_pool import TokenPool
2025-04-07 13:14:29 +08:00
from services.self_hosted_email import SelfHostedEmail
from upload_account import AccountUploader
from auto_cursor_service import AutoCursorService
2025-03-27 10:20:06 +08:00
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)
2025-04-07 13:14:29 +08:00
# 初始化常规邮箱服务
2025-03-27 10:20:06 +08:00
self.email_manager = EmailManager(self.config, self.db_manager)
self.register_worker = RegisterWorker(
self.config,
self.fetch_manager,
self.email_manager
)
2025-04-07 13:14:29 +08:00
# 初始化自建邮箱服务(如果配置了)
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("自建邮箱注册工作器已初始化")
2025-03-27 10:20:06 +08:00
async def initialize(self):
"""初始化数据库"""
await self.db_manager.initialize()
2025-04-02 09:28:25 +08:00
# 确保EmailManager完成初始化
await self.email_manager.initialize()
2025-03-27 10:20:06 +08:00
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
2025-04-07 13:14:29 +08:00
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)
2025-04-07 13:14:29 +08:00
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
2025-04-07 13:14:29 +08:00
for i, result in enumerate(results):
if isinstance(result, Exception):
self.logger.error(f"注册任务 {i+1} 失败: {str(result)}")
2025-04-07 13:14:29 +08:00
failed.append(str(result))
elif result is None:
skipped += 1
2025-04-07 13:14:29 +08:00
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)
2025-04-07 13:14:29 +08:00
# 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}")
2025-04-07 13:14:29 +08:00
return successful
except Exception as e:
self.logger.error(f"批量注册失败: {str(e)}")
2025-04-07 13:14:29 +08:00
return []
2025-03-27 10:20:06 +08:00
async def main():
register = CursorRegister()
await register.initialize()
try:
batch_size = register.config.register_config.batch_size
total_registered = 0
2025-04-07 13:14:29 +08:00
# 直接使用自建邮箱模式,不再检查配置
register.logger.info("使用自建邮箱模式")
# 确保已初始化自建邮箱服务
if not register.host_register_worker:
register.logger.error("自建邮箱注册工作器未初始化,请检查配置")
return
2025-03-27 10:20:06 +08:00
2025-04-07 13:14:29 +08:00
# 自建邮箱模式,直接执行自建邮箱批量注册
while True:
register.logger.info(f"开始新一轮自建邮箱批量注册,批次大小: {batch_size}")
results = await register.batch_register_with_host(batch_size)
2025-03-27 10:20:06 +08:00
# 统计结果
successful = len(results)
total_registered += successful
register.logger.info(f"当前总进度: 已注册 {total_registered} 个账号")
2025-04-07 13:14:29 +08:00
# 批次之间的间隔
await asyncio.sleep(5)
2025-04-02 09:28:25 +08:00
2025-03-27 10:20:06 +08:00
# 如果本批次注册失败率过高,暂停一段时间
2025-04-01 17:58:08 +08:00
if successful < batch_size * 0.5 and successful > 0: # 成功率低于50%但不为零
2025-03-27 10:20:06 +08:00
register.logger.warning("本批次成功率过低暂停60秒后继续")
await asyncio.sleep(60)
2025-04-01 17:58:08 +08:00
elif successful == 0 and batch_size > 0: # 完全失败
register.logger.error("本批次完全失败可能存在系统问题暂停120秒后继续")
await asyncio.sleep(120)
2025-04-07 13:14:29 +08:00
# 让用户决定是否继续
try:
answer = input("是否继续下一批注册? (y/n): ").strip().lower()
if answer != 'y':
register.logger.info("用户选择停止注册")
break
except Exception:
# 如果在非交互环境中运行,默认继续
pass
2025-03-27 10:20:06 +08:00
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())