update
This commit is contained in:
136
run.py
136
run.py
@@ -26,7 +26,7 @@ from team_service import batch_invite_to_team, print_team_summary, check_availab
|
||||
from crs_service import crs_add_account, crs_sync_team_owners, crs_verify_token
|
||||
from cpa_service import cpa_verify_connection
|
||||
from s2a_service import s2a_verify_connection
|
||||
from browser_automation import register_and_authorize, login_and_authorize_with_otp, authorize_only, login_and_authorize_team_owner
|
||||
from browser_automation import register_and_authorize, login_and_authorize_with_otp, authorize_only, login_and_authorize_team_owner, ShutdownRequested
|
||||
from utils import (
|
||||
save_to_csv,
|
||||
load_team_tracker,
|
||||
@@ -44,13 +44,14 @@ from logger import log
|
||||
|
||||
# 进度更新 (Telegram Bot 使用,导入失败时忽略)
|
||||
try:
|
||||
from bot_notifier import progress_start, progress_update, progress_account_done, progress_finish
|
||||
from bot_notifier import progress_start, progress_update, progress_account_done, progress_finish, notify_team_completed_sync
|
||||
except ImportError:
|
||||
# 如果没有 bot_notifier,使用空函数
|
||||
def progress_start(team_name, total): pass
|
||||
def progress_update(account=None, step=None): pass
|
||||
def progress_account_done(email, success): pass
|
||||
def progress_finish(): pass
|
||||
def notify_team_completed_sync(team_name, results): pass
|
||||
|
||||
|
||||
# ==================== 全局状态 ====================
|
||||
@@ -96,10 +97,13 @@ if threading.current_thread() is threading.main_thread():
|
||||
|
||||
|
||||
def process_single_team(team: dict) -> tuple[list, list]:
|
||||
def process_single_team(team: dict, team_index: int = 0, teams_total: int = 0) -> tuple[list, list]:
|
||||
"""处理单个 Team 的完整流程
|
||||
|
||||
Args:
|
||||
team: Team 配置
|
||||
team_index: 当前 Team 序号 (从 1 开始)
|
||||
teams_total: Team 总数
|
||||
|
||||
Returns:
|
||||
tuple: (处理结果列表, 待处理的 Owner 列表)
|
||||
@@ -202,21 +206,42 @@ def process_single_team(team: dict) -> tuple[list, list]:
|
||||
else:
|
||||
log.warning(f"Team {team_name} 没有可用席位,无法邀请新成员")
|
||||
|
||||
# ========== 阶段 3: 处理普通成员 (注册 + Codex 授权 + CRS) ==========
|
||||
if invited_accounts:
|
||||
log.section(f"阶段 3: 逐个注册 OpenAI + Codex 授权 + CRS 入库")
|
||||
member_results = process_accounts(invited_accounts, team_name)
|
||||
results.extend(member_results)
|
||||
# ========== 合并成员和 Owner 一起处理 ==========
|
||||
all_to_process = invited_accounts.copy()
|
||||
|
||||
# 添加未完成的 Owner 到处理列表
|
||||
from config import INCLUDE_TEAM_OWNERS
|
||||
include_owner = INCLUDE_TEAM_OWNERS and len(owner_accounts) > 0
|
||||
|
||||
if include_owner:
|
||||
for owner in owner_accounts:
|
||||
all_to_process.append({
|
||||
"email": owner["email"],
|
||||
"password": owner.get("password", DEFAULT_PASSWORD),
|
||||
"status": owner.get("status", ""),
|
||||
"role": "owner"
|
||||
})
|
||||
log.info(f"包含 {len(owner_accounts)} 个 Owner 账号一起处理")
|
||||
|
||||
# Owner 不在这里处理,统一放到所有 Team 处理完后
|
||||
# ========== 阶段 3: 处理所有账号 (注册 + Codex 授权 + 入库) ==========
|
||||
if all_to_process:
|
||||
log.section(f"阶段 3: 逐个注册 OpenAI + Codex 授权 + 入库")
|
||||
all_results = process_accounts(
|
||||
all_to_process, team_name,
|
||||
team_index=team_index, teams_total=teams_total,
|
||||
include_owner=include_owner
|
||||
)
|
||||
results.extend(all_results)
|
||||
|
||||
# ========== Team 处理完成 ==========
|
||||
success_count = sum(1 for r in results if r["status"] == "success")
|
||||
if results:
|
||||
log.success(f"{team_name} 成员处理完成: {success_count}/{len(results)} 成功")
|
||||
log.success(f"{team_name} 处理完成: {success_count}/{len(results)} 成功")
|
||||
# 发送 Team 完成报告到 Telegram
|
||||
notify_team_completed_sync(team_name, results)
|
||||
|
||||
# 返回未完成的 Owner 列表供后续统一处理
|
||||
return results, owner_accounts
|
||||
# 返回空列表,因为 Owner 已经在这里处理了
|
||||
return results, []
|
||||
|
||||
|
||||
def _get_team_by_name(team_name: str) -> dict:
|
||||
@@ -227,12 +252,16 @@ def _get_team_by_name(team_name: str) -> dict:
|
||||
return {}
|
||||
|
||||
|
||||
def process_accounts(accounts: list, team_name: str) -> list:
|
||||
def process_accounts(accounts: list, team_name: str, team_index: int = 0,
|
||||
teams_total: int = 0, include_owner: bool = False) -> list:
|
||||
"""处理账号列表 (注册/授权/CRS)
|
||||
|
||||
Args:
|
||||
accounts: 账号列表 [{"email", "password", "status", "role"}]
|
||||
team_name: Team 名称
|
||||
team_index: 当前 Team 序号 (从 1 开始)
|
||||
teams_total: Team 总数
|
||||
include_owner: 是否包含 Owner
|
||||
|
||||
Returns:
|
||||
list: 处理结果
|
||||
@@ -242,7 +271,7 @@ def process_accounts(accounts: list, team_name: str) -> list:
|
||||
results = []
|
||||
|
||||
# 启动进度跟踪 (Telegram Bot)
|
||||
progress_start(team_name, len(accounts))
|
||||
progress_start(team_name, len(accounts), team_index, teams_total, include_owner)
|
||||
|
||||
for i, account in enumerate(accounts):
|
||||
if _shutdown_requested:
|
||||
@@ -291,7 +320,7 @@ def process_accounts(accounts: list, team_name: str) -> list:
|
||||
log.separator("#", 50)
|
||||
|
||||
# 更新进度: 当前账号
|
||||
progress_update(account=email, step="Starting...")
|
||||
progress_update(account=email, step="Starting...", role=role)
|
||||
|
||||
result = {
|
||||
"team": team_name,
|
||||
@@ -331,10 +360,11 @@ def process_accounts(accounts: list, team_name: str) -> list:
|
||||
update_account_status(_tracker, team_name, email, "processing")
|
||||
save_team_tracker(_tracker)
|
||||
|
||||
with Timer(f"账号 {email}"):
|
||||
if is_team_owner_otp:
|
||||
# 旧格式 Team Owner: 使用 OTP 登录授权
|
||||
log.info("Team Owner 账号 (旧格式),使用一次性验证码登录...", icon="auth")
|
||||
try:
|
||||
with Timer(f"账号 {email}"):
|
||||
if is_team_owner_otp:
|
||||
# 旧格式 Team Owner: 使用 OTP 登录授权
|
||||
log.info("Team Owner 账号 (旧格式),使用一次性验证码登录...", icon="auth")
|
||||
progress_update(step="OTP Login...")
|
||||
auth_success, codex_data = login_and_authorize_with_otp(email)
|
||||
register_success = auth_success
|
||||
@@ -469,6 +499,13 @@ def process_accounts(accounts: list, team_name: str) -> list:
|
||||
update_account_status(_tracker, team_name, email, "register_failed")
|
||||
save_team_tracker(_tracker)
|
||||
|
||||
except ShutdownRequested:
|
||||
# 用户请求停止,保存当前状态并退出
|
||||
log.warning(f"用户请求停止,当前账号: {email}")
|
||||
# 不改变账号状态,保持中断前的状态,下次继续处理
|
||||
save_team_tracker(_tracker)
|
||||
break
|
||||
|
||||
# 保存到 CSV
|
||||
save_to_csv(
|
||||
email=email,
|
||||
@@ -514,10 +551,10 @@ def run_all_teams():
|
||||
log.warning(f"发现 {total_incomplete} 个未完成账号,将优先处理")
|
||||
|
||||
_current_results = []
|
||||
all_pending_owners = [] # 收集所有待处理的 Owner
|
||||
teams_total = len(TEAMS)
|
||||
|
||||
with Timer("全部流程"):
|
||||
# ========== 第一阶段: 处理所有 Team 的普通成员 ==========
|
||||
# ========== 处理所有 Team (成员 + Owner 一起) ==========
|
||||
for i, team in enumerate(TEAMS):
|
||||
if _shutdown_requested:
|
||||
log.warning("检测到中断请求,停止处理...")
|
||||
@@ -525,51 +562,18 @@ def run_all_teams():
|
||||
|
||||
log.separator("★", 60)
|
||||
team_email = team.get('account') or team.get('owner_email', '')
|
||||
log.highlight(f"Team {i + 1}/{len(TEAMS)}: {team['name']} ({team_email})", icon="team")
|
||||
log.highlight(f"Team {i + 1}/{teams_total}: {team['name']} ({team_email})", icon="team")
|
||||
log.separator("★", 60)
|
||||
|
||||
results, pending_owners = process_single_team(team)
|
||||
|
||||
# 收集待处理的 Owner
|
||||
if pending_owners:
|
||||
for owner in pending_owners:
|
||||
all_pending_owners.append({
|
||||
"team_name": team["name"],
|
||||
"email": owner["email"],
|
||||
"password": owner.get("password", DEFAULT_PASSWORD),
|
||||
"status": owner.get("status", "team_owner"),
|
||||
"role": "owner"
|
||||
})
|
||||
# 传递 Team 序号信息
|
||||
results, _ = process_single_team(team, team_index=i + 1, teams_total=teams_total)
|
||||
_current_results.extend(results)
|
||||
|
||||
# Team 之间的间隔
|
||||
if i < len(TEAMS) - 1 and not _shutdown_requested:
|
||||
if i < teams_total - 1 and not _shutdown_requested:
|
||||
wait_time = 3
|
||||
log.countdown(wait_time, "下一个 Team")
|
||||
|
||||
# ========== 第二阶段: 统一处理所有 Team Owner 的 CRS 授权 ==========
|
||||
if all_pending_owners and not _shutdown_requested:
|
||||
log.separator("★", 60)
|
||||
log.header(f"统一处理 Team Owner CRS 授权 ({len(all_pending_owners)} 个)")
|
||||
log.separator("★", 60)
|
||||
|
||||
for i, owner in enumerate(all_pending_owners):
|
||||
if _shutdown_requested:
|
||||
log.warning("检测到中断请求,停止处理...")
|
||||
break
|
||||
|
||||
log.separator("#", 50)
|
||||
log.info(f"Owner {i + 1}/{len(all_pending_owners)}: {owner['email']} ({owner['team_name']})", icon="account")
|
||||
log.separator("#", 50)
|
||||
|
||||
owner_results = process_accounts([owner], owner["team_name"])
|
||||
_current_results.extend(owner_results)
|
||||
|
||||
# Owner 之间的间隔
|
||||
if i < len(all_pending_owners) - 1 and not _shutdown_requested:
|
||||
wait_time = random.randint(5, 15)
|
||||
log.info(f"等待 {wait_time}s 后处理下一个 Owner...", icon="wait")
|
||||
time.sleep(wait_time)
|
||||
|
||||
# 打印总结
|
||||
print_summary(_current_results)
|
||||
|
||||
@@ -592,22 +596,10 @@ def run_single_team(team_index: int = 0):
|
||||
log.info(f"单 Team 模式: {team['name']}", icon="start")
|
||||
|
||||
_current_results = []
|
||||
results, pending_owners = process_single_team(team)
|
||||
# 单 Team 模式:序号为 1/1
|
||||
results, _ = process_single_team(team, team_index=1, teams_total=1)
|
||||
_current_results.extend(results)
|
||||
|
||||
# 单 Team 模式下也处理 Owner
|
||||
if pending_owners:
|
||||
log.section(f"处理 Team Owner ({len(pending_owners)} 个)")
|
||||
for owner in pending_owners:
|
||||
owner_data = {
|
||||
"email": owner["email"],
|
||||
"password": owner.get("password", DEFAULT_PASSWORD),
|
||||
"status": owner.get("status", "team_owner"),
|
||||
"role": "owner"
|
||||
}
|
||||
owner_results = process_accounts([owner_data], team["name"])
|
||||
_current_results.extend(owner_results)
|
||||
|
||||
print_summary(_current_results)
|
||||
|
||||
return _current_results
|
||||
|
||||
Reference in New Issue
Block a user