2022-08-29 23:12:44 +08:00

136 lines
3.5 KiB
Python

from __future__ import annotations
from typing import Any, Dict, List, Tuple
from httpx import Response, AsyncClient
from .exc import StatusError
from .models import Spot, Tree, MapID, Point, MapInfo, SpotKinds
CLIENT = AsyncClient(
base_url="https://api-static.mihoyo.com/common/blackboard/ys_obc/v1/map"
)
Spots = Dict[int, List[Spot]]
async def _request(endpoint: str) -> Dict[str, Any]:
resp = await CLIENT.get(endpoint)
resp.raise_for_status()
data: dict[str, Any] = resp.json()
if data["retcode"] != 0:
raise StatusError(data["retcode"], data["message"])
return data["data"]
async def get_labels(map_id: MapID) -> List[Tree]:
"""
获取米游社资源列表
参数:
map_id: `MapID`
地图 ID
返回:
`list[Tree]`
"""
data = await _request(f"/label/tree?map_id={map_id}&app_sn=ys_obc")
return [Tree.parse_obj(i) for i in data["tree"]]
async def get_points(map_id: MapID) -> List[Point]:
"""
获取米游社坐标列表
参数:
map_id: `MapID`
地图 ID
返回:
`list[Point]`
"""
data = await _request(f"/point/list?map_id={map_id}&app_sn=ys_obc")
return [Point.parse_obj(i) for i in data["point_list"]]
async def get_maps(map_id: MapID) -> MapInfo:
"""
获取米游社地图
参数:
map_id: `MapID`
地图 ID
返回:
`MapInfo`
"""
data = await _request(f"/info?map_id={map_id}&app_sn=ys_obc&lang=zh-cn")
return MapInfo.parse_obj(data["info"])
async def get_spot_from_game(
map_id: MapID, cookie: str
) -> Tuple[Spots, SpotKinds]:
"""
获取游戏内标点
注意:每十分钟只能获取一次,否则会 -2000 错误
参数:
map_id: `MapID`
地图 ID
cookie: `str`
米游社 Cookie
返回:
`tuple[Spots, SpotKinds]`
"""
def _raise_for_retcode(resp: Response) -> Dict[str, Any]:
resp.raise_for_status()
data: dict[str, Any] = resp.json()
if data["retcode"] != 0:
raise StatusError(data["retcode"], data["message"])
return data["data"]
async with AsyncClient(
base_url="https://api-takumi.mihoyo.com/common/map_user/ys_obc/v1/map",
headers={"Cookie": cookie},
) as client:
# 1. 申请刷新
resp = await client.post(
"/spot_kind/sync_game_spot",
json={
"map_id": str(map_id.value),
"app_sn": "ys_obc",
"lang": "zh-cn",
},
headers={"Cookie": cookie},
)
_raise_for_retcode(resp)
# 2. 获取类别
resp = await client.get(
"/spot_kind/get_spot_kinds?map_id=2&app_sn=ys_obc&lang=zh-cn",
headers={"Cookie": cookie},
)
data = _raise_for_retcode(resp)
spot_kinds_data = SpotKinds.parse_obj(data)
ids = [kind.id for kind in spot_kinds_data.list]
# 3.获取坐标
resp = await client.post(
"/spot/get_map_spots_by_kinds",
json={
"map_id": str(map_id.value),
"app_sn": "ys_obc",
"lang": "zh-cn",
"kind_ids": ids,
},
)
data = _raise_for_retcode(resp)
spots: Spots = {}
for k, v in data["spots"].items():
spots[int(k)] = [Spot.parse_obj(i) for i in v["list"]]
return spots, spot_kinds_data