update
This commit is contained in:
234
run.py
234
run.py
@@ -364,139 +364,139 @@ def process_accounts(accounts: list, team_name: str, team_index: int = 0,
|
|||||||
if is_team_owner_otp:
|
if is_team_owner_otp:
|
||||||
# 旧格式 Team Owner: 使用 OTP 登录授权
|
# 旧格式 Team Owner: 使用 OTP 登录授权
|
||||||
log.info("Team Owner 账号 (旧格式),使用一次性验证码登录...", icon="auth")
|
log.info("Team Owner 账号 (旧格式),使用一次性验证码登录...", icon="auth")
|
||||||
progress_update(step="OTP Login...")
|
progress_update(step="OTP Login...")
|
||||||
auth_success, codex_data = login_and_authorize_with_otp(email)
|
auth_success, codex_data = login_and_authorize_with_otp(email)
|
||||||
register_success = auth_success
|
|
||||||
elif need_crs_only:
|
|
||||||
# 已授权但未入库: 跳过授权,直接尝试入库
|
|
||||||
log.info(f"已授权账号 (状态: {account_status}),跳过授权,直接入库...", icon="auth")
|
|
||||||
progress_update(step="Adding to CRS...")
|
|
||||||
register_success = True
|
|
||||||
codex_data = None # CPA/S2A 模式不需要 codex_data
|
|
||||||
# CRS 模式下,由于没有 codex_data,无法入库,需要重新授权
|
|
||||||
if AUTH_PROVIDER not in ("cpa", "s2a"):
|
|
||||||
log.warning("CRS 模式下已授权账号缺少 codex_data,需要重新授权")
|
|
||||||
auth_success, codex_data = authorize_only(email, password)
|
|
||||||
register_success = auth_success
|
register_success = auth_success
|
||||||
elif need_auth_only:
|
elif need_crs_only:
|
||||||
# 已注册账号 (包括新格式 Owner): 使用密码登录授权
|
# 已授权但未入库: 跳过授权,直接尝试入库
|
||||||
log.info(f"已注册账号 (状态: {account_status}, 角色: {account_role}),使用密码登录授权...", icon="auth")
|
log.info(f"已授权账号 (状态: {account_status}),跳过授权,直接入库...", icon="auth")
|
||||||
progress_update(step="Authorizing...")
|
progress_update(step="Adding to CRS...")
|
||||||
auth_success, codex_data = authorize_only(email, password)
|
register_success = True
|
||||||
register_success = True
|
codex_data = None # CPA/S2A 模式不需要 codex_data
|
||||||
else:
|
# CRS 模式下,由于没有 codex_data,无法入库,需要重新授权
|
||||||
# 新账号: 注册 + Codex 授权
|
if AUTH_PROVIDER not in ("cpa", "s2a"):
|
||||||
progress_update(step="Registering...")
|
log.warning("CRS 模式下已授权账号缺少 codex_data,需要重新授权")
|
||||||
register_success, codex_data = register_and_authorize(email, password)
|
auth_success, codex_data = authorize_only(email, password)
|
||||||
|
register_success = auth_success
|
||||||
# 检查是否是域名黑名单错误
|
elif need_auth_only:
|
||||||
if register_success == "domain_blacklisted":
|
# 已注册账号 (包括新格式 Owner): 使用密码登录授权
|
||||||
domain = get_domain_from_email(email)
|
log.info(f"已注册账号 (状态: {account_status}, 角色: {account_role}),使用密码登录授权...", icon="auth")
|
||||||
log.error(f"域名 {domain} 不被支持,加入黑名单")
|
progress_update(step="Authorizing...")
|
||||||
add_domain_to_blacklist(domain)
|
auth_success, codex_data = authorize_only(email, password)
|
||||||
|
register_success = True
|
||||||
# 从 tracker 中移除
|
|
||||||
remove_account_from_tracker(_tracker, team_name, email)
|
|
||||||
save_team_tracker(_tracker)
|
|
||||||
|
|
||||||
# 尝试创建新邮箱替代
|
|
||||||
log.info("尝试创建新邮箱替代...")
|
|
||||||
new_email, new_password = unified_create_email()
|
|
||||||
if new_email and not is_email_blacklisted(new_email):
|
|
||||||
# 邀请新邮箱
|
|
||||||
if invite_single_to_team(new_email, _get_team_by_name(team_name)):
|
|
||||||
add_account_with_password(_tracker, team_name, new_email, new_password, "invited")
|
|
||||||
save_team_tracker(_tracker)
|
|
||||||
log.success(f"已创建新邮箱: {new_email},将在下次运行时处理")
|
|
||||||
else:
|
|
||||||
log.error("新邮箱邀请失败")
|
|
||||||
else:
|
|
||||||
log.error("无法创建有效的新邮箱")
|
|
||||||
|
|
||||||
continue # 跳过当前账号,继续下一个
|
|
||||||
|
|
||||||
if register_success and register_success != "domain_blacklisted":
|
|
||||||
update_account_status(_tracker, team_name, email, "registered")
|
|
||||||
save_team_tracker(_tracker)
|
|
||||||
|
|
||||||
# CPA 模式: codex_data 为 None,授权成功后直接标记完成
|
|
||||||
# CRS 模式: 需要 codex_data,手动添加到 CRS
|
|
||||||
if AUTH_PROVIDER == "s2a":
|
|
||||||
# S2A 模式: 授权成功后验证账号是否入库
|
|
||||||
from s2a_service import s2a_verify_account_in_pool
|
|
||||||
|
|
||||||
update_account_status(_tracker, team_name, email, "authorized")
|
|
||||||
save_team_tracker(_tracker)
|
|
||||||
|
|
||||||
# 验证账号是否成功入库
|
|
||||||
log.step("正在验证 S2A 账号入库状态...")
|
|
||||||
progress_update(step="验证入库...")
|
|
||||||
verified, account_data = s2a_verify_account_in_pool(email)
|
|
||||||
|
|
||||||
if verified:
|
|
||||||
account_id = account_data.get("id", "")
|
|
||||||
account_name = account_data.get("name", "")
|
|
||||||
result["status"] = "success"
|
|
||||||
result["crs_id"] = f"S2A-{account_id}"
|
|
||||||
|
|
||||||
update_account_status(_tracker, team_name, email, "completed")
|
|
||||||
save_team_tracker(_tracker)
|
|
||||||
|
|
||||||
log.success(f"✅ S2A 账号入库成功 (ID: {account_id}, 名称: {account_name})")
|
|
||||||
else:
|
|
||||||
log.warning("⚠️ S2A 授权成功但入库验证失败")
|
|
||||||
result["status"] = "partial"
|
|
||||||
update_account_status(_tracker, team_name, email, "partial")
|
|
||||||
save_team_tracker(_tracker)
|
|
||||||
|
|
||||||
elif AUTH_PROVIDER == "cpa":
|
|
||||||
# CPA 模式: 授权成功即完成 (后台自动处理账号)
|
|
||||||
update_account_status(_tracker, team_name, email, "authorized")
|
|
||||||
save_team_tracker(_tracker)
|
|
||||||
|
|
||||||
result["status"] = "success"
|
|
||||||
result["crs_id"] = "CPA-AUTO"
|
|
||||||
|
|
||||||
update_account_status(_tracker, team_name, email, "completed")
|
|
||||||
save_team_tracker(_tracker)
|
|
||||||
|
|
||||||
log.success(f"✅ CPA 账号处理完成: {email}")
|
|
||||||
else:
|
else:
|
||||||
# CRS 模式: 原有逻辑
|
# 新账号: 注册 + Codex 授权
|
||||||
if codex_data:
|
progress_update(step="Registering...")
|
||||||
|
register_success, codex_data = register_and_authorize(email, password)
|
||||||
|
|
||||||
|
# 检查是否是域名黑名单错误
|
||||||
|
if register_success == "domain_blacklisted":
|
||||||
|
domain = get_domain_from_email(email)
|
||||||
|
log.error(f"域名 {domain} 不被支持,加入黑名单")
|
||||||
|
add_domain_to_blacklist(domain)
|
||||||
|
|
||||||
|
# 从 tracker 中移除
|
||||||
|
remove_account_from_tracker(_tracker, team_name, email)
|
||||||
|
save_team_tracker(_tracker)
|
||||||
|
|
||||||
|
# 尝试创建新邮箱替代
|
||||||
|
log.info("尝试创建新邮箱替代...")
|
||||||
|
new_email, new_password = unified_create_email()
|
||||||
|
if new_email and not is_email_blacklisted(new_email):
|
||||||
|
# 邀请新邮箱
|
||||||
|
if invite_single_to_team(new_email, _get_team_by_name(team_name)):
|
||||||
|
add_account_with_password(_tracker, team_name, new_email, new_password, "invited")
|
||||||
|
save_team_tracker(_tracker)
|
||||||
|
log.success(f"已创建新邮箱: {new_email},将在下次运行时处理")
|
||||||
|
else:
|
||||||
|
log.error("新邮箱邀请失败")
|
||||||
|
else:
|
||||||
|
log.error("无法创建有效的新邮箱")
|
||||||
|
|
||||||
|
continue # 跳过当前账号,继续下一个
|
||||||
|
|
||||||
|
if register_success and register_success != "domain_blacklisted":
|
||||||
|
update_account_status(_tracker, team_name, email, "registered")
|
||||||
|
save_team_tracker(_tracker)
|
||||||
|
|
||||||
|
# CPA 模式: codex_data 为 None,授权成功后直接标记完成
|
||||||
|
# CRS 模式: 需要 codex_data,手动添加到 CRS
|
||||||
|
if AUTH_PROVIDER == "s2a":
|
||||||
|
# S2A 模式: 授权成功后验证账号是否入库
|
||||||
|
from s2a_service import s2a_verify_account_in_pool
|
||||||
|
|
||||||
update_account_status(_tracker, team_name, email, "authorized")
|
update_account_status(_tracker, team_name, email, "authorized")
|
||||||
save_team_tracker(_tracker)
|
save_team_tracker(_tracker)
|
||||||
|
|
||||||
# 添加到 CRS
|
# 验证账号是否成功入库
|
||||||
log.step("添加到 CRS...")
|
log.step("正在验证 S2A 账号入库状态...")
|
||||||
crs_result = crs_add_account(email, codex_data)
|
progress_update(step="验证入库...")
|
||||||
|
verified, account_data = s2a_verify_account_in_pool(email)
|
||||||
|
|
||||||
if crs_result:
|
if verified:
|
||||||
crs_id = crs_result.get("id", "")
|
account_id = account_data.get("id", "")
|
||||||
|
account_name = account_data.get("name", "")
|
||||||
result["status"] = "success"
|
result["status"] = "success"
|
||||||
result["crs_id"] = crs_id
|
result["crs_id"] = f"S2A-{account_id}"
|
||||||
|
|
||||||
update_account_status(_tracker, team_name, email, "completed")
|
update_account_status(_tracker, team_name, email, "completed")
|
||||||
save_team_tracker(_tracker)
|
save_team_tracker(_tracker)
|
||||||
|
|
||||||
log.success(f"账号处理完成: {email}")
|
log.success(f"✅ S2A 账号入库成功 (ID: {account_id}, 名称: {account_name})")
|
||||||
else:
|
else:
|
||||||
log.warning("CRS 入库失败,但注册和授权成功")
|
log.warning("⚠️ S2A 授权成功但入库验证失败")
|
||||||
result["status"] = "partial"
|
result["status"] = "partial"
|
||||||
update_account_status(_tracker, team_name, email, "partial")
|
update_account_status(_tracker, team_name, email, "partial")
|
||||||
save_team_tracker(_tracker)
|
save_team_tracker(_tracker)
|
||||||
else:
|
|
||||||
log.warning("Codex 授权失败")
|
elif AUTH_PROVIDER == "cpa":
|
||||||
result["status"] = "auth_failed"
|
# CPA 模式: 授权成功即完成 (后台自动处理账号)
|
||||||
update_account_status(_tracker, team_name, email, "auth_failed")
|
update_account_status(_tracker, team_name, email, "authorized")
|
||||||
save_team_tracker(_tracker)
|
save_team_tracker(_tracker)
|
||||||
elif register_success != "domain_blacklisted":
|
|
||||||
if is_team_owner_otp:
|
result["status"] = "success"
|
||||||
log.error(f"OTP 登录授权失败: {email}")
|
result["crs_id"] = "CPA-AUTO"
|
||||||
else:
|
|
||||||
log.error(f"注册/授权失败: {email}")
|
update_account_status(_tracker, team_name, email, "completed")
|
||||||
update_account_status(_tracker, team_name, email, "register_failed")
|
save_team_tracker(_tracker)
|
||||||
save_team_tracker(_tracker)
|
|
||||||
|
log.success(f"✅ CPA 账号处理完成: {email}")
|
||||||
|
else:
|
||||||
|
# CRS 模式: 原有逻辑
|
||||||
|
if codex_data:
|
||||||
|
update_account_status(_tracker, team_name, email, "authorized")
|
||||||
|
save_team_tracker(_tracker)
|
||||||
|
|
||||||
|
# 添加到 CRS
|
||||||
|
log.step("添加到 CRS...")
|
||||||
|
crs_result = crs_add_account(email, codex_data)
|
||||||
|
|
||||||
|
if crs_result:
|
||||||
|
crs_id = crs_result.get("id", "")
|
||||||
|
result["status"] = "success"
|
||||||
|
result["crs_id"] = crs_id
|
||||||
|
|
||||||
|
update_account_status(_tracker, team_name, email, "completed")
|
||||||
|
save_team_tracker(_tracker)
|
||||||
|
|
||||||
|
log.success(f"账号处理完成: {email}")
|
||||||
|
else:
|
||||||
|
log.warning("CRS 入库失败,但注册和授权成功")
|
||||||
|
result["status"] = "partial"
|
||||||
|
update_account_status(_tracker, team_name, email, "partial")
|
||||||
|
save_team_tracker(_tracker)
|
||||||
|
else:
|
||||||
|
log.warning("Codex 授权失败")
|
||||||
|
result["status"] = "auth_failed"
|
||||||
|
update_account_status(_tracker, team_name, email, "auth_failed")
|
||||||
|
save_team_tracker(_tracker)
|
||||||
|
elif register_success != "domain_blacklisted":
|
||||||
|
if is_team_owner_otp:
|
||||||
|
log.error(f"OTP 登录授权失败: {email}")
|
||||||
|
else:
|
||||||
|
log.error(f"注册/授权失败: {email}")
|
||||||
|
update_account_status(_tracker, team_name, email, "register_failed")
|
||||||
|
save_team_tracker(_tracker)
|
||||||
|
|
||||||
except ShutdownRequested:
|
except ShutdownRequested:
|
||||||
# 用户请求停止,保存当前状态并退出
|
# 用户请求停止,保存当前状态并退出
|
||||||
|
|||||||
42
uv.lock
generated
42
uv.lock
generated
@@ -15,6 +15,18 @@ wheels = [
|
|||||||
{ url = "https://files.pythonhosted.org/packages/38/0e/27be9fdef66e72d64c0cdc3cc2823101b80585f8119b5c112c2e8f5f7dab/anyio-4.12.1-py3-none-any.whl", hash = "sha256:d405828884fc140aa80a3c667b8beed277f1dfedec42ba031bd6ac3db606ab6c", size = 113592, upload-time = "2026-01-06T11:45:19.497Z" },
|
{ url = "https://files.pythonhosted.org/packages/38/0e/27be9fdef66e72d64c0cdc3cc2823101b80585f8119b5c112c2e8f5f7dab/anyio-4.12.1-py3-none-any.whl", hash = "sha256:d405828884fc140aa80a3c667b8beed277f1dfedec42ba031bd6ac3db606ab6c", size = 113592, upload-time = "2026-01-06T11:45:19.497Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "apscheduler"
|
||||||
|
version = "3.11.2"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
dependencies = [
|
||||||
|
{ name = "tzlocal" },
|
||||||
|
]
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/07/12/3e4389e5920b4c1763390c6d371162f3784f86f85cd6d6c1bfe68eef14e2/apscheduler-3.11.2.tar.gz", hash = "sha256:2a9966b052ec805f020c8c4c3ae6e6a06e24b1bf19f2e11d91d8cca0473eef41", size = 108683, upload-time = "2025-12-22T00:39:34.884Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/9f/64/2e54428beba8d9992aa478bb8f6de9e4ecaa5f8f513bcfd567ed7fb0262d/apscheduler-3.11.2-py3-none-any.whl", hash = "sha256:ce005177f741409db4e4dd40a7431b76feb856b9dd69d57e0da49d6715bfd26d", size = 64439, upload-time = "2025-12-22T00:39:33.303Z" },
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "certifi"
|
name = "certifi"
|
||||||
version = "2025.11.12"
|
version = "2025.11.12"
|
||||||
@@ -326,7 +338,7 @@ version = "0.1.0"
|
|||||||
source = { virtual = "." }
|
source = { virtual = "." }
|
||||||
dependencies = [
|
dependencies = [
|
||||||
{ name = "drissionpage" },
|
{ name = "drissionpage" },
|
||||||
{ name = "python-telegram-bot" },
|
{ name = "python-telegram-bot", extra = ["job-queue"] },
|
||||||
{ name = "requests" },
|
{ name = "requests" },
|
||||||
{ name = "rich" },
|
{ name = "rich" },
|
||||||
{ name = "setuptools" },
|
{ name = "setuptools" },
|
||||||
@@ -337,7 +349,7 @@ dependencies = [
|
|||||||
[package.metadata]
|
[package.metadata]
|
||||||
requires-dist = [
|
requires-dist = [
|
||||||
{ name = "drissionpage", specifier = ">=4.1.1.2" },
|
{ name = "drissionpage", specifier = ">=4.1.1.2" },
|
||||||
{ name = "python-telegram-bot", specifier = ">=22.5" },
|
{ name = "python-telegram-bot", extras = ["job-queue"], specifier = ">=22.5" },
|
||||||
{ name = "requests", specifier = ">=2.32.5" },
|
{ name = "requests", specifier = ">=2.32.5" },
|
||||||
{ name = "rich", specifier = ">=14.2.0" },
|
{ name = "rich", specifier = ">=14.2.0" },
|
||||||
{ name = "setuptools", specifier = ">=80.9.0" },
|
{ name = "setuptools", specifier = ">=80.9.0" },
|
||||||
@@ -404,6 +416,11 @@ wheels = [
|
|||||||
{ url = "https://files.pythonhosted.org/packages/bc/c3/340c7520095a8c79455fcf699cbb207225e5b36490d2b9ee557c16a7b21b/python_telegram_bot-22.5-py3-none-any.whl", hash = "sha256:4b7cd365344a7dce54312cc4520d7fa898b44d1a0e5f8c74b5bd9b540d035d16", size = 730976, upload-time = "2025-09-27T13:50:25.93Z" },
|
{ url = "https://files.pythonhosted.org/packages/bc/c3/340c7520095a8c79455fcf699cbb207225e5b36490d2b9ee557c16a7b21b/python_telegram_bot-22.5-py3-none-any.whl", hash = "sha256:4b7cd365344a7dce54312cc4520d7fa898b44d1a0e5f8c74b5bd9b540d035d16", size = 730976, upload-time = "2025-09-27T13:50:25.93Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[package.optional-dependencies]
|
||||||
|
job-queue = [
|
||||||
|
{ name = "apscheduler" },
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "requests"
|
name = "requests"
|
||||||
version = "2.32.5"
|
version = "2.32.5"
|
||||||
@@ -527,6 +544,27 @@ wheels = [
|
|||||||
{ url = "https://files.pythonhosted.org/packages/18/67/36e9267722cc04a6b9f15c7f3441c2363321a3ea07da7ae0c0707beb2a9c/typing_extensions-4.15.0-py3-none-any.whl", hash = "sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548", size = 44614, upload-time = "2025-08-25T13:49:24.86Z" },
|
{ url = "https://files.pythonhosted.org/packages/18/67/36e9267722cc04a6b9f15c7f3441c2363321a3ea07da7ae0c0707beb2a9c/typing_extensions-4.15.0-py3-none-any.whl", hash = "sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548", size = 44614, upload-time = "2025-08-25T13:49:24.86Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tzdata"
|
||||||
|
version = "2025.3"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/5e/a7/c202b344c5ca7daf398f3b8a477eeb205cf3b6f32e7ec3a6bac0629ca975/tzdata-2025.3.tar.gz", hash = "sha256:de39c2ca5dc7b0344f2eba86f49d614019d29f060fc4ebc8a417896a620b56a7", size = 196772, upload-time = "2025-12-13T17:45:35.667Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/c7/b0/003792df09decd6849a5e39c28b513c06e84436a54440380862b5aeff25d/tzdata-2025.3-py2.py3-none-any.whl", hash = "sha256:06a47e5700f3081aab02b2e513160914ff0694bce9947d6b76ebd6bf57cfc5d1", size = 348521, upload-time = "2025-12-13T17:45:33.889Z" },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tzlocal"
|
||||||
|
version = "5.3.1"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
dependencies = [
|
||||||
|
{ name = "tzdata", marker = "sys_platform == 'win32'" },
|
||||||
|
]
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/8b/2e/c14812d3d4d9cd1773c6be938f89e5735a1f11a9f184ac3639b93cef35d5/tzlocal-5.3.1.tar.gz", hash = "sha256:cceffc7edecefea1f595541dbd6e990cb1ea3d19bf01b2809f362a03dd7921fd", size = 30761, upload-time = "2025-03-05T21:17:41.549Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/c2/14/e2a54fabd4f08cd7af1c07030603c3356b74da07f7cc056e600436edfa17/tzlocal-5.3.1-py3-none-any.whl", hash = "sha256:eb1a66c3ef5847adf7a834f1be0800581b683b5608e74f86ecbcef8ab91bb85d", size = 18026, upload-time = "2025-03-05T21:17:39.857Z" },
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "urllib3"
|
name = "urllib3"
|
||||||
version = "2.6.2"
|
version = "2.6.2"
|
||||||
|
|||||||
Reference in New Issue
Block a user