PaiGram/modules/apihelper/client/components/map.py
2023-02-19 18:12:47 +08:00

112 lines
4.0 KiB
Python

import json
from pathlib import Path
from typing import Dict, Union
from httpx import AsyncClient, HTTPError
from modules.apihelper.models.genshin.map import LabelTree, ListData
from utils.const import PROJECT_ROOT
MAP_PATH = PROJECT_ROOT.joinpath("data", "apihelper", "map")
MAP_PATH.mkdir(parents=True, exist_ok=True)
class MapException(Exception):
"""提瓦特地图异常"""
def __init__(self, message: str):
self.message = message
class MapHelper:
"""提瓦特大地图"""
MAP_API_URL = "https://map.minigg.cn/map/get_map"
LABEL_URL = "https://api-static.mihoyo.com/common/blackboard/ys_obc/v1/map/label/tree?app_sn=ys_obc"
COUNT_URL = "https://api-static.mihoyo.com/common/blackboard/ys_obc/v1/map/point/list"
COUNT_PARAMS = {"app_sn": "ys_obc", "map_id": "2"}
MAP_ID_LIST = [
"2",
"7",
"9",
]
MAP_NAME_LIST = [
"提瓦特大陆",
"渊下宫",
"层岩巨渊·地下矿区",
]
def __init__(self):
self.client = AsyncClient()
self.query_map_path = MAP_PATH / "query_map.json"
self.label_count_path = MAP_PATH / "label_count.json"
self.query_map: Dict[str, str] = {}
self.label_count: Dict[str, Dict[str, int]] = {}
self.load(self.query_map, self.query_map_path)
self.load(self.label_count, self.label_count_path)
@staticmethod
def load(data: Dict, path: Path) -> None:
"""加载文件"""
if not path.exists():
return
data.clear()
with open(path, "r", encoding="utf-8") as f:
data.update(json.load(f))
def save(self, data: Dict, path: Path) -> None:
"""保存查询映射"""
if path not in [self.query_map_path, self.label_count_path]:
return
with open(path, "w", encoding="utf-8") as f:
json.dump(data, f, ensure_ascii=False, indent=4)
async def refresh_query_map(self) -> None:
"""刷新查询映射"""
data = {}
label_data = await self.client.get(self.LABEL_URL)
for label_tree_source in label_data.json().get("data", {}).get("tree", []):
label_tree = LabelTree(**label_tree_source)
for child in label_tree.children:
data[child.name] = str(child.id)
self.query_map = data
self.save(data, self.query_map_path)
async def refresh_label_count(self) -> None:
"""刷新标签数量"""
data = self.label_count
for map_id in self.MAP_ID_LIST:
data[map_id] = {}
params = self.COUNT_PARAMS.copy()
params["map_id"] = map_id
count_data = await self.client.get(self.COUNT_URL, params=params)
list_data = ListData(**count_data.json().get("data", {}))
for label in list_data.label_list:
if label.depth == 2:
data[map_id][label.name] = len([i for i in list_data.point_list if i.label_id == label.id])
self.save(data, self.label_count_path)
def get_label_count(self, map_id: Union[str, int], label_name: str) -> int:
"""获取标签数量"""
return self.label_count.get(str(map_id), {}).get(label_name, 0)
async def get_map(self, map_id: Union[str, int], name: str) -> bytes:
"""获取资源图片"""
try:
req = await self.client.get(
self.MAP_API_URL,
params={
"resource_name": name,
"map_id": str(map_id),
"is_cluster": False,
},
timeout=60,
)
except HTTPError as e:
raise MapException("请求超时,请稍后再试") from e
if req.headers.get("content-type") == "image/jpeg":
return req.content
if req.headers.get("content-type") == "application/json":
raise MapException(req.json().get("message", "遇到未知错误,请稍后再试"))
raise MapException("遇到未知错误,请稍后再试")