fix: Sub2ApiWebsiteClient.list_accounts 支持分页拉取,避免只拿到默认第一页 20 条导致误建重复账号
This commit is contained in:
@@ -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。"""
|
||||
|
||||
Reference in New Issue
Block a user