Files
astrbot_plugin_jx3/core/adapters/jx3box.py
T
2026-07-26 17:57:44 +08:00

93 lines
3.1 KiB
Python

import hashlib
import json
from collections.abc import Mapping
from typing import Any
from astrbot.api import logger
from ..request import APIResponseFormatError
from .base import EndpointAdapter
class JX3BoxAdapter(EndpointAdapter):
"""适配 JX3BOX 响应结构,并集中实现其分页规则。"""
def extract_payload(self, payload: Any, out_key: str | None) -> Any:
if out_key in (None, ""):
return payload
if not isinstance(payload, Mapping):
raise APIResponseFormatError(
f"JX3BOX 响应不是对象,无法提取字段: {out_key}"
)
if out_key not in payload:
raise APIResponseFormatError(f"JX3BOX 响应缺少字段: {out_key}")
return payload[out_key]
async def request_all_pages(
self,
endpoint_name: str,
*,
params: Mapping[str, Any] | None = None,
out_key: str | None = None,
path_params: Mapping[str, Any] | None = None,
page_key: str = "page",
list_key: str = "list",
max_pages: int = 10,
) -> list[Any]:
if max_pages < 1:
raise ValueError("max_pages 必须大于等于 1")
all_items: list[Any] = []
request_params = dict(params or {})
previous_page_hash: str | None = None
for current_page in range(1, max_pages + 1):
request_params[page_key] = str(current_page)
data = await self.request(
endpoint_name,
params=request_params,
out_key=out_key,
path_params=path_params,
)
page_items = self._extract_page_items(data, list_key)
if not page_items:
break
page_hash = hashlib.sha256(
json.dumps(
page_items,
ensure_ascii=False,
sort_keys=True,
default=str,
).encode("utf-8")
).hexdigest()
if page_hash == previous_page_hash:
logger.warning(
"JX3BOX 分页接口连续返回重复页面,已停止: "
f"key={endpoint_name}, page={current_page}"
)
break
all_items.extend(page_items)
previous_page_hash = page_hash
return all_items
@staticmethod
def _extract_page_items(data: Any, list_key: str) -> list[Any]:
if data is None:
return []
if isinstance(data, bytes):
raise APIResponseFormatError("JX3BOX 分页接口返回了二进制内容")
if isinstance(data, list):
return data
if not isinstance(data, Mapping):
raise APIResponseFormatError("JX3BOX 分页响应必须是列表或对象")
if list_key not in data:
raise APIResponseFormatError(f"JX3BOX 分页响应缺少字段: {list_key}")
items = data[list_key]
if not isinstance(items, list):
raise APIResponseFormatError(f"JX3BOX 分页字段 {list_key} 不是列表")
return items