fix: 修复取消异常被吞、GUI 清理路径与邮箱文案乱码

- wait_for_sso_cookie 不再吞掉 RegistrationCancelled
- GUI 轮次 finally 对齐 CLI 的重启/停止保护
- CPA 本地写入与远程上传互不阻断
- 修复 YYDS/DuckMail 异常与日志中文乱码
This commit is contained in:
Git-creat7
2026-07-11 06:52:37 -05:00
parent 3c5e86c35d
commit 28ee863b84
+47 -29
View File
@@ -332,11 +332,17 @@ def add_sso_to_cpa(raw_token, email="", log_callback=None):
return return
record = _s2cpa.token_to_cpa_record(token, email=email) record = _s2cpa.token_to_cpa_record(token, email=email)
if auth_dir: if auth_dir:
path = _s2cpa.write_cpa_auth(_s2cpa.Path(auth_dir), record) try:
_cpa_log(f"已写入本地 {path}") path = _s2cpa.write_cpa_auth(_s2cpa.Path(auth_dir), record)
_cpa_log(f"已写入本地 {path}")
except Exception as local_exc:
_cpa_log(f"本地写入失败: {local_exc}")
if remote_url: if remote_url:
name = _s2cpa.upload_cpa_auth_remote(remote_url, management_key, record) try:
_cpa_log(f"已上传远程 {remote_url.rstrip('/')}/.../{name}") name = _s2cpa.upload_cpa_auth_remote(remote_url, management_key, record)
_cpa_log(f"已上传远程 {remote_url.rstrip('/')}/.../{name}")
except Exception as remote_exc:
_cpa_log(f"远程上传失败: {remote_exc}")
except Exception as exc: except Exception as exc:
_cpa_log(f"直出失败: {exc}") _cpa_log(f"直出失败: {exc}")
@@ -577,7 +583,7 @@ def yyds_create_account(address=None, domain=None, api_key=None, jwt=None):
data = resp.json() data = resp.json()
if data.get("success"): if data.get("success"):
return data.get("data", {}) return data.get("data", {})
raise Exception(f"YYDS 鍒涘缓閭澶辫触: {data}") raise Exception(f"YYDS 创建邮箱失败: {data}")
def yyds_get_token(address, api_key=None, jwt=None): def yyds_get_token(address, api_key=None, jwt=None):
@@ -595,7 +601,7 @@ def yyds_get_token(address, api_key=None, jwt=None):
data = resp.json() data = resp.json()
if data.get("success"): if data.get("success"):
return data.get("data", {}).get("token") return data.get("data", {}).get("token")
raise Exception(f"YYDS 鑾峰彇token澶辫触: {data}") raise Exception(f"YYDS 获取token失败: {data}")
def yyds_get_messages(address, token=None, api_key=None, jwt=None): def yyds_get_messages(address, token=None, api_key=None, jwt=None):
@@ -631,7 +637,7 @@ def yyds_get_message_detail(message_id, token=None, api_key=None, jwt=None):
data = resp.json() data = resp.json()
if data.get("success"): if data.get("success"):
return data.get("data", {}) return data.get("data", {})
raise Exception(f"YYDS 鑾峰彇閭欢璇︽儏澶辫触: {data}") raise Exception(f"YYDS 获取邮件详情失败: {data}")
def yyds_generate_username(length=10): def yyds_generate_username(length=10):
@@ -642,7 +648,7 @@ def yyds_generate_username(length=10):
def yyds_pick_domain(api_key=None, jwt=None): def yyds_pick_domain(api_key=None, jwt=None):
domains = yyds_get_domains(api_key=api_key, jwt=jwt) domains = yyds_get_domains(api_key=api_key, jwt=jwt)
if not domains: if not domains:
raise Exception("YYDS 娌℃湁杩斿洖浠讳綍鍙敤鍩熷悕") raise Exception("YYDS 没有返回任何可用域名")
private = [d for d in domains if d.get("isVerified") and not d.get("isPublic")] private = [d for d in domains if d.get("isVerified") and not d.get("isPublic")]
if private: if private:
return private[0]["domain"] return private[0]["domain"]
@@ -652,7 +658,7 @@ def yyds_pick_domain(api_key=None, jwt=None):
verified = [d for d in domains if d.get("isVerified")] verified = [d for d in domains if d.get("isVerified")]
if verified: if verified:
return verified[0]["domain"] return verified[0]["domain"]
raise Exception("YYDS 鏃犲凡楠岃瘉鍩熷悕鍙敤") raise Exception("YYDS 无已验证域名可用")
def yyds_get_email_and_token(api_key=None, jwt=None): def yyds_get_email_and_token(api_key=None, jwt=None):
@@ -670,8 +676,8 @@ def yyds_get_email_and_token(api_key=None, jwt=None):
if not temp_token: if not temp_token:
temp_token = yyds_get_token(address, api_key=key, jwt=token) temp_token = yyds_get_token(address, api_key=key, jwt=token)
if not temp_token: if not temp_token:
raise Exception("鑾峰彇 YYDS token 澶辫触") raise Exception("获取 YYDS token 失败")
print(f"[*] 宸插垱寤?YYDS 閭: {address}") print(f"[*] 已创建 YYDS 邮箱: {address}")
return address, temp_token return address, temp_token
@@ -692,7 +698,7 @@ def yyds_get_oai_code(
messages = yyds_get_messages(address, token=token, jwt=jwt) messages = yyds_get_messages(address, token=token, jwt=jwt)
except Exception as exc: except Exception as exc:
if log_callback: if log_callback:
log_callback(f"[Debug] YYDS 鎷夊彇閭欢鍒楄〃澶辫触: {exc}") log_callback(f"[Debug] YYDS 拉取邮件列表失败: {exc}")
sleep_with_cancel(poll_interval, cancel_callback) sleep_with_cancel(poll_interval, cancel_callback)
continue continue
for msg in messages: for msg in messages:
@@ -707,7 +713,7 @@ def yyds_get_oai_code(
detail = yyds_get_message_detail(msg_id, token=token, jwt=jwt) detail = yyds_get_message_detail(msg_id, token=token, jwt=jwt)
except Exception as exc: except Exception as exc:
if log_callback: if log_callback:
log_callback(f"[Debug] YYDS 鑾峰彇閭欢璇︽儏澶辫触: {exc}") log_callback(f"[Debug] YYDS 获取邮件详情失败: {exc}")
continue continue
parts = [] parts = []
text_body = detail.get("text") or "" text_body = detail.get("text") or ""
@@ -719,11 +725,11 @@ def yyds_get_oai_code(
combined = "\n".join(parts) combined = "\n".join(parts)
subject = detail.get("subject", "") subject = detail.get("subject", "")
if log_callback: if log_callback:
log_callback(f"[Debug] YYDS 鏀跺埌閭欢: {subject}") log_callback(f"[Debug] YYDS 收到邮件: {subject}")
code = extract_verification_code(combined, subject) code = extract_verification_code(combined, subject)
if code: if code:
if log_callback: if log_callback:
log_callback(f"[*] YYDS 浠庨偖浠朵腑鎻愬彇鍒伴獙璇佺爜: {code}") log_callback(f"[*] YYDS 从邮件中提取到验证码: {code}")
return code return code
sleep_with_cancel(poll_interval, cancel_callback) sleep_with_cancel(poll_interval, cancel_callback)
raise Exception(f"YYDS 在 {timeout}s 内未收到验证码邮件") raise Exception(f"YYDS 在 {timeout}s 内未收到验证码邮件")
@@ -737,7 +743,7 @@ def generate_username(length=10):
def pick_domain(api_key=None): def pick_domain(api_key=None):
domains = get_domains(api_key=api_key) domains = get_domains(api_key=api_key)
if not domains: if not domains:
raise Exception("DuckMail 娌℃湁杩斿洖浠讳綍鍙敤鍩熷悕") raise Exception("DuckMail 没有返回任何可用域名")
private = [d for d in domains if d.get("ownerId")] private = [d for d in domains if d.get("ownerId")]
verified_private = [d for d in private if d.get("isVerified")] verified_private = [d for d in private if d.get("isVerified")]
if verified_private: if verified_private:
@@ -745,7 +751,7 @@ def pick_domain(api_key=None):
public = [d for d in domains if d.get("isVerified")] public = [d for d in domains if d.get("isVerified")]
if public: if public:
return public[0]["domain"] return public[0]["domain"]
raise Exception("DuckMail 鏃犲凡楠岃瘉鍩熷悕鍙敤") raise Exception("DuckMail 无已验证域名可用")
def get_email_provider(): def get_email_provider():
@@ -792,7 +798,7 @@ def get_email_and_token(api_key=None):
create_account(address, password, api_key=key, expires_in=0) create_account(address, password, api_key=key, expires_in=0)
token = get_token(address, password) token = get_token(address, password)
if not token: if not token:
raise Exception("鑾峰彇 DuckMail token 澶辫触") raise Exception("获取 DuckMail token 失败")
return address, token return address, token
@@ -872,7 +878,7 @@ def duckmail_get_oai_code(
messages = get_messages(dev_token) messages = get_messages(dev_token)
except Exception as exc: except Exception as exc:
if log_callback: if log_callback:
log_callback(f"[Debug] 鎷夊彇閭欢鍒楄〃澶辫触: {exc}") log_callback(f"[Debug] 拉取邮件列表失败: {exc}")
sleep_with_cancel(poll_interval, cancel_callback) sleep_with_cancel(poll_interval, cancel_callback)
continue continue
for msg in messages: for msg in messages:
@@ -887,7 +893,7 @@ def duckmail_get_oai_code(
detail = get_message_detail(dev_token, msg_id) detail = get_message_detail(dev_token, msg_id)
except Exception as exc: except Exception as exc:
if log_callback: if log_callback:
log_callback(f"[Debug] 鑾峰彇閭欢璇︽儏澶辫触: {exc}") log_callback(f"[Debug] 获取邮件详情失败: {exc}")
continue continue
parts = [] parts = []
text_body = detail.get("text") or "" text_body = detail.get("text") or ""
@@ -899,11 +905,11 @@ def duckmail_get_oai_code(
combined = "\n".join(parts) combined = "\n".join(parts)
subject = detail.get("subject", "") subject = detail.get("subject", "")
if log_callback: if log_callback:
log_callback(f"[Debug] 鏀跺埌閭欢: {subject}") log_callback(f"[Debug] 收到邮件: {subject}")
code = extract_verification_code(combined, subject) code = extract_verification_code(combined, subject)
if code: if code:
if log_callback: if log_callback:
log_callback(f"[*] 浠庨偖浠朵腑鎻愬彇鍒伴獙璇佺爜: {code}") log_callback(f"[*] 从邮件中提取到验证码: {code}")
return code return code
sleep_with_cancel(poll_interval, cancel_callback) sleep_with_cancel(poll_interval, cancel_callback)
raise Exception(f"{timeout}s 内未收到验证码邮件") raise Exception(f"{timeout}s 内未收到验证码邮件")
@@ -2505,6 +2511,8 @@ return String(cfInput.value || '').trim().length;
refresh_active_page() refresh_active_page()
except AccountRetryNeeded: except AccountRetryNeeded:
raise raise
except RegistrationCancelled:
raise
except Exception: except Exception:
pass pass
@@ -2910,18 +2918,28 @@ class GrokRegisterGUI:
self.update_stats() self.update_stats()
if self.should_stop(): if self.should_stop():
break break
if browser is None: try:
start_browser(log_callback=self.log) if browser is None:
else: start_browser(log_callback=self.log)
restart_browser(log_callback=self.log) else:
# 停止后不再调用 cancel_callback,避免 finally 里二次抛出 RegistrationCancelled restart_browser(log_callback=self.log)
time.sleep(1) # 停止后不再调用 cancel_callback,避免 finally 里二次抛出 RegistrationCancelled
time.sleep(1)
except RegistrationCancelled:
break
except Exception as restart_exc:
if self.should_stop():
break
self.log(f"[Debug] 轮次清理/重启浏览器失败: {restart_exc}")
except RegistrationCancelled: except RegistrationCancelled:
self.log("[!] 注册被用户停止") self.log("[!] 注册被用户停止")
except Exception as exc: except Exception as exc:
self.log(f"[!] 任务异常: {exc}") self.log(f"[!] 任务异常: {exc}")
finally: finally:
stop_browser() try:
stop_browser()
except BaseException:
pass
self._set_running_ui(False) self._set_running_ui(False)
self.log("[*] 任务结束") self.log("[*] 任务结束")