fix: Sub2ApiWebsiteClient.list_accounts 支持分页拉取,避免只拿到默认第一页 20 条导致误建重复账号

This commit is contained in:
SmartUp Developer
2026-07-02 11:04:46 +08:00
parent fe3f9f4a4c
commit 00af34c487
2 changed files with 131 additions and 11 deletions
+77 -11
View File
@@ -334,17 +334,83 @@ class Sub2ApiWebsiteClient:
return None
def list_accounts(self, endpoint: str = "/accounts") -> list[dict[str, Any]] | None:
"""拉取远端账号列表。成功返回账号 dict 列表,失败返回 None。"""
try:
resp = self._request("GET", endpoint)
except Exception:
logger.warning("account list fetch failed for %s", endpoint, exc_info=True)
return None
items = self._unwrap_list(resp)
if items is None:
logger.warning("account list unexpected format for %s", endpoint)
return None
return [item for item in items if isinstance(item, dict)]
"""拉取远端账号列表。支持分页拉取,成功返回账号 dict 列表,失败返回 None。"""
base_path = endpoint
query_params = {}
if "?" in endpoint:
base_path, query_str = endpoint.split("?", 1)
for part in query_str.split("&"):
if "=" in part:
k, v = part.split("=", 1)
query_params[k] = v
page_size = 100
if "page_size" in query_params:
try:
page_size = int(query_params["page_size"])
except ValueError:
pass
page = 1
all_items = []
while True:
params = dict(query_params)
params["page"] = str(page)
params["page_size"] = str(page_size)
qp_str = "&".join(f"{k}={v}" for k, v in params.items())
current_path = f"{base_path}?{qp_str}"
try:
resp = self._request("GET", current_path)
except Exception:
logger.warning("account list fetch failed for %s", current_path, exc_info=True)
return None
items = self._unwrap_list(resp)
if items is None:
logger.warning("account list unexpected format for %s", current_path)
return None
all_items.extend([item for item in items if isinstance(item, dict)])
if isinstance(resp, dict):
# 尝试从顶层或嵌套的 data 字典中提取分页字段
meta = resp
data_val = resp.get("data")
if isinstance(data_val, dict) and any(k in data_val for k in ("pages", "total", "page_size")):
meta = data_val
pages = meta.get("pages")
if pages is not None:
try:
pages_val = int(pages)
if page >= pages_val:
break
page += 1
continue
except (ValueError, TypeError):
pass
total = meta.get("total")
current_page_size = meta.get("page_size")
if total is not None and current_page_size is not None:
try:
total_val = int(total)
page_size_val = int(current_page_size)
import math
calculated_pages = math.ceil(total_val / page_size_val)
if page >= calculated_pages:
break
page += 1
continue
except (ValueError, TypeError):
pass
break
return all_items
def _get_account_ids(self, endpoint: str = "/accounts") -> set[str] | None:
"""拉取远端账号列表。成功返回 ID 集合(可能为空),解析失败返回 None。"""