This commit is contained in:
2026-01-27 10:08:10 +08:00
parent 06eaff03b9
commit ad10d1f2b7
2 changed files with 96 additions and 83 deletions

View File

@@ -2121,6 +2121,15 @@ def register_and_authorize(email: str, password: str, use_api_register: bool = T
- CRS 模式: codex_data 包含 tokens - CRS 模式: codex_data 包含 tokens
- CPA/S2A 模式: codex_data 为 None (后台自动处理) - CPA/S2A 模式: codex_data 为 None (后台自动处理)
""" """
# 获取授权回调锁 (CPA/S2A 模式需要串行授权)
auth_lock = None
if AUTH_PROVIDER in ("cpa", "s2a"):
try:
import run
auth_lock = run._auth_callback_lock
except (ImportError, AttributeError):
pass
with browser_context_with_retry(max_browser_retries=2) as ctx: with browser_context_with_retry(max_browser_retries=2) as ctx:
for attempt in ctx.attempts(): for attempt in ctx.attempts():
try: try:
@@ -2144,6 +2153,14 @@ def register_and_authorize(email: str, password: str, use_api_register: bool = T
# 短暂等待确保注册完成 # 短暂等待确保注册完成
time.sleep(0.5) time.sleep(0.5)
# ========== 授权流程 - CPA/S2A 需要串行执行 (避免回调端口冲突) ==========
# 在调用授权函数之前获取锁,确保浏览器不会在等待锁时空闲断开
if auth_lock:
log.step("等待授权回调锁...")
auth_lock.acquire()
log.step("获取授权回调锁,开始授权...")
try:
# 根据配置选择授权方式 # 根据配置选择授权方式
if AUTH_PROVIDER == "cpa": if AUTH_PROVIDER == "cpa":
# CPA 模式: 授权成功即完成,后台自动处理账号 # CPA 模式: 授权成功即完成,后台自动处理账号
@@ -2157,6 +2174,10 @@ def register_and_authorize(email: str, password: str, use_api_register: bool = T
# CRS 模式: 需要 codex_data # CRS 模式: 需要 codex_data
codex_data = perform_codex_authorization(ctx.page, email, password) codex_data = perform_codex_authorization(ctx.page, email, password)
return True, codex_data return True, codex_data
finally:
if auth_lock:
log.step("释放授权回调锁")
auth_lock.release()
except Exception as e: except Exception as e:
ctx.handle_error(e) ctx.handle_error(e)
@@ -2178,8 +2199,24 @@ def authorize_only(email: str, password: str) -> tuple[bool, dict]:
- CRS 模式: codex_data 包含 tokens - CRS 模式: codex_data 包含 tokens
- CPA/S2A 模式: codex_data 为 None (后台自动处理) - CPA/S2A 模式: codex_data 为 None (后台自动处理)
""" """
# 获取授权回调锁 (CPA/S2A 模式需要串行授权)
auth_lock = None
if AUTH_PROVIDER in ("cpa", "s2a"):
try:
import run
auth_lock = run._auth_callback_lock
except (ImportError, AttributeError):
pass
with browser_context_with_retry(max_browser_retries=2) as ctx: with browser_context_with_retry(max_browser_retries=2) as ctx:
for attempt in ctx.attempts(): for attempt in ctx.attempts():
try:
# ========== 授权流程 - CPA/S2A 需要串行执行 (避免回调端口冲突) ==========
if auth_lock:
log.step("等待授权回调锁...")
auth_lock.acquire()
log.step("获取授权回调锁,开始授权...")
try: try:
# 根据配置选择授权方式 # 根据配置选择授权方式
if AUTH_PROVIDER == "cpa": if AUTH_PROVIDER == "cpa":
@@ -2214,6 +2251,10 @@ def authorize_only(email: str, password: str) -> tuple[bool, dict]:
log.warning("授权失败,准备重试...") log.warning("授权失败,准备重试...")
continue continue
return False, None return False, None
finally:
if auth_lock:
log.step("释放授权回调锁")
auth_lock.release()
except Exception as e: except Exception as e:
ctx.handle_error(e) ctx.handle_error(e)
@@ -2243,17 +2284,8 @@ def perform_cpa_authorization(page, email: str, password: str) -> bool:
""" """
log.info(f"开始 CPA 授权: {email}", icon="code") log.info(f"开始 CPA 授权: {email}", icon="code")
# ========== 授权流程 - 需要串行执行 (避免回调端口冲突) ========== # 注意: 授权回调锁已在上层函数 (register_and_authorize/authorize_only) 中获取
try: # 这里不再重复获取锁
import run
auth_lock = run._auth_callback_lock
except (ImportError, AttributeError):
auth_lock = None
if auth_lock:
log.step("等待授权锁...")
auth_lock.acquire()
log.step("获取授权锁,开始授权流程...")
try: try:
# 生成授权 URL # 生成授权 URL
@@ -2397,14 +2429,9 @@ def perform_cpa_authorization(page, email: str, password: str) -> bool:
log.error("CPA 授权状态检查失败") log.error("CPA 授权状态检查失败")
return False return False
finally: except Exception as e:
# 确保释放锁 log.error(f"CPA 授权异常: {e}")
if auth_lock: return False
try:
auth_lock.release()
log.step("释放授权回调锁")
except RuntimeError:
pass # 锁可能已经被释放
def perform_cpa_authorization_with_otp(page, email: str) -> bool: def perform_cpa_authorization_with_otp(page, email: str) -> bool:
@@ -2654,17 +2681,8 @@ def perform_s2a_authorization(page, email: str, password: str) -> bool:
log.info(f"开始 S2A 授权: {email}", icon="code") log.info(f"开始 S2A 授权: {email}", icon="code")
progress_update(phase="授权", step="开始 S2A 授权...") progress_update(phase="授权", step="开始 S2A 授权...")
# ========== 授权流程 - 需要串行执行 (避免回调端口冲突) ========== # 注意: 授权回调锁已在上层函数 (register_and_authorize/authorize_only) 中获取
try: # 这里不再重复获取锁
import run
auth_lock = run._auth_callback_lock
except (ImportError, AttributeError):
auth_lock = None
if auth_lock:
log.step("等待授权锁...")
auth_lock.acquire()
log.step("获取授权锁,开始授权流程...")
try: try:
# 生成授权 URL # 生成授权 URL
@@ -2864,14 +2882,9 @@ def perform_s2a_authorization(page, email: str, password: str) -> bool:
log.error("S2A 账号入库失败") log.error("S2A 账号入库失败")
return False return False
finally: except Exception as e:
# 确保释放锁 log.error(f"S2A 授权异常: {e}")
if auth_lock: return False
try:
auth_lock.release()
log.step("释放授权回调锁")
except RuntimeError:
pass # 锁可能已经被释放
# ==================== 格式3专用: 登录获取 Session ==================== # ==================== 格式3专用: 登录获取 Session ====================

2
run.py
View File

@@ -775,7 +775,7 @@ def process_accounts_concurrent(
if max_workers is None: if max_workers is None:
max_workers = CONCURRENT_WORKERS max_workers = CONCURRENT_WORKERS
stagger_delay = 2.0 # 线程错开启动间隔 (秒) stagger_delay = 4.0 # 线程错开启动间隔 (秒)
# 过滤已完成的账号 # 过滤已完成的账号
pending_accounts = [acc for acc in accounts if acc.get("status") != "completed"] pending_accounts = [acc for acc in accounts if acc.get("status") != "completed"]