feat: complete T-105b account login reuse

This commit is contained in:
chengma
2026-07-06 15:01:50 +08:00
parent 7ac0dcd00e
commit 0dad4151ef
12 changed files with 276 additions and 30 deletions
+87 -2
View File
@@ -7,7 +7,7 @@ from datetime import datetime
from typing import Optional
from urllib.parse import urlparse
from . import appconfig, chrome, db, editor
from . import appconfig, cdp, chrome, db, editor
from . import config as account_config
@@ -42,6 +42,12 @@ def _required_text(value, field_name: str) -> str:
return text
def _account_value(account, field, default=None):
if isinstance(account, dict):
return account.get(field, default)
return getattr(account, field, default)
def normalize_region_host(value=None) -> str:
text = _trim(value) or DEFAULT_REGION_HOST
if "://" in text:
@@ -208,9 +214,88 @@ def resolve_account(account_or_alias, path=None, config=None):
return account_or_alias
def _debug_host(account) -> str:
return f"{chrome.CDP_HOST}:{normalize_debug_port(_account_value(account, 'debug_port'))}"
def _seller_portal_url(account) -> str:
return f"https://{normalize_region_host(_account_value(account, 'region_host'))}/portal/"
def _find_login_tab(account, host):
region_host = normalize_region_host(_account_value(account, 'region_host')).lower()
seller_tabs = []
login_tabs = []
for tab in cdp.http_get("/json", host=host):
if tab.get("type") != "page":
continue
url = str(tab.get("url") or "")
lower_url = url.lower()
if region_host in lower_url:
seller_tabs.append(tab)
elif "accounts.shopee." in lower_url and "/seller/login" in lower_url:
login_tabs.append(tab)
return (seller_tabs or login_tabs or [None])[0]
def _open_or_activate_login_tab(account):
host = _debug_host(account)
portal_url = _seller_portal_url(account)
tab = _find_login_tab(account, host)
if tab:
target_id = tab.get("id")
if target_id:
cdp.activate_tab(target_id, host=host)
return {
"target_id": target_id,
"url": tab.get("url") or portal_url,
"created_tab": False,
}
tab = cdp.create_tab_info(portal_url, host=host)
target_id = tab.get("id")
if target_id:
cdp.activate_tab(target_id, host=host)
return {
"target_id": target_id,
"url": tab.get("url") or portal_url,
"created_tab": True,
}
def launch_for_login(account_or_alias, path=None, config=None):
account = resolve_account(account_or_alias, path=path, config=config)
return chrome.launch_chrome(account, config=config)
port = normalize_debug_port(_account_value(account, "debug_port"))
alias = _account_value(account, "alias")
if chrome.is_running(port):
tab = _open_or_activate_login_tab(account)
return {
"ok": True,
"action": "reused",
"reused": True,
"launched": False,
"alias": alias,
"debug_port": port,
"pid": None,
**tab,
}
process = chrome.launch_chrome(account, config=config)
timeout = appconfig.cdp_ready_timeout(config)
if not chrome.wait_debug_ready(port, timeout=timeout):
raise AccountError(f"Chrome 已启动,但 CDP 端口 {port} 未在 {timeout} 秒内就绪")
tab = _open_or_activate_login_tab(account)
return {
"ok": True,
"action": "launched",
"reused": False,
"launched": True,
"alias": alias,
"debug_port": port,
"pid": getattr(process, "pid", None),
**tab,
}
def create_shortcut(account_or_alias, shortcut_path=None, desktop_dir=None, path=None, config=None) -> str:
+14
View File
@@ -43,6 +43,20 @@ def close_tab(target_id, host=None):
return response.ok
def activate_tab(target_id, host=None):
"""Bring an existing Chrome target/page to the foreground."""
if not target_id:
return False
ver = http_get("/json/version", host=host)
b = CDP(ver["webSocketDebuggerUrl"])
try:
b.send("Target.activateTarget", {"targetId": target_id})
finally:
b.close()
return True
class CDP:
"""单个 target 的 CDP 客户端:命令同步、事件回调异步。"""
+23 -5
View File
@@ -312,7 +312,7 @@ class AccountsTab(QWidget):
account=account,
)
try:
process = accounts.launch_for_login(account, config=self.config)
launch_result = accounts.launch_for_login(account, config=self.config)
except Exception as exc:
elapsed_ms = _elapsed_ms(started)
safe_error = diagnostics.redact_log_text(str(exc) or exc.__class__.__name__)
@@ -344,10 +344,17 @@ class AccountsTab(QWidget):
self._show_error(safe_error)
return
elapsed_ms = _elapsed_ms(started)
pid = getattr(process, "pid", None)
action = (launch_result or {}).get("action") or "launched"
pid = (launch_result or {}).get("pid")
target_id = (launch_result or {}).get("target_id") or ""
url = (launch_result or {}).get("url") or ""
event_result = "reused" if action == "reused" else "launched"
_safe_add_run_log_event(
run_id,
f"step=launch_chrome result=success detail=账号 {account.alias} pid={pid or ''} elapsed_ms={elapsed_ms}",
(
f"step=launch_chrome result={event_result} detail=账号 {account.alias} "
f"pid={pid or ''} target_id={target_id} url={url} elapsed_ms={elapsed_ms}"
),
db_path=self.db_path,
account=account,
)
@@ -358,11 +365,22 @@ class AccountsTab(QWidget):
done=1,
success_count=1,
failed_count=0,
summary_json={"ok": True, "alias": account.alias, "debug_port": account.debug_port, "pid": pid},
summary_json={
"ok": True,
"alias": account.alias,
"debug_port": account.debug_port,
"action": action,
"pid": pid,
"target_id": target_id,
"url": url,
},
)
self.login_statuses[account.alias] = "已启动"
self.refresh_accounts()
self._set_status("Chrome 已启动,请人工登录")
if action == "reused":
self._set_status("该账号 Chrome 已打开,已复用现有窗口")
else:
self._set_status("Chrome 已启动,请人工登录")
def check_login(self, checked=False):
account = self._selected_account()