diff --git a/metadata/genshin.py b/metadata/genshin.py index dae67322..53a4e7f2 100644 --- a/metadata/genshin.py +++ b/metadata/genshin.py @@ -2,41 +2,83 @@ from __future__ import annotations +from typing import Generic, Iterator, KeysView, TypeVar + import ujson as json from utils.const import PROJECT_ROOT from utils.log import logger -from utils.typedefs import JSONType, StrOrInt +from utils.typedefs import StrOrInt __all__ = [ 'HONEY_DATA', 'AVATAR_DATA', 'WEAPON_DATA', 'MATERIAL_DATA', 'ARTIFACT_DATA', 'NAMECARD_DATA', - 'honey_id_to_game_id' + 'honey_id_to_game_id', + 'Data' ] +K = TypeVar('K') +V = TypeVar('V') + data_dir = PROJECT_ROOT.joinpath('metadata/data/') data_dir.mkdir(parents=True, exist_ok=True) - -def _get_content(file_name: str) -> JSONType: - path = data_dir.joinpath(file_name).with_suffix('.json') - if not path.exists(): - logger.error( - f"暂未找到名为 \"{file_name}.json\" 的 metadata , 请先使用 [yellow bold]/refresh_metadata[/] 命令下载", - extra={'markup': True} - ) - return {} - with open(path, encoding='utf-8') as file: - return json.load(file) +_cache = {} -HONEY_DATA: dict[str, dict[StrOrInt, list[str | int]]] = _get_content('honey') +class Data(dict, Generic[K, V]): + _dict: dict[K, V] + _file_name: str -AVATAR_DATA: dict[str, dict[str, int | str | list[int]]] = _get_content('avatar') -WEAPON_DATA: dict[str, dict[str, int | str]] = _get_content('weapon') -MATERIAL_DATA: dict[str, dict[str, int | str]] = _get_content('material') -ARTIFACT_DATA: dict[str, dict[str, int | str | list[int] | dict[str, str]]] = _get_content('reliquary') -NAMECARD_DATA: dict[str, dict[str, int | str]] = _get_content('namecard') + @property + def data(self) -> dict[K, V]: + if not (result := _cache.get(self._file_name, None)): + self._dict = result + super(Data, self).__init__(result) + path = data_dir.joinpath(self._file_name).with_suffix('.json') + if not path.exists(): + logger.error( + f"暂未找到名为 \"{self._file_name}.json\" 的 metadata , " + "请先使用 [yellow bold]/refresh_metadata[/] 命令下载", + extra={'markup': True} + ) + self._dict = {} + with open(path, encoding='utf-8') as file: + self._dict = json.load(file) + _cache.update({self._file_name: self._dict}) + return self._dict + + def __init__(self, file_name: str): + self._file_name = file_name + self._dict = {} + super(Data, self).__init__() + + def get(self, key: K) -> V | None: + return self.data.get(key) + + def __getitem__(self, key: K) -> V: + return self.data.__getitem__(key) + + def __setitem__(self, key: K, value: V) -> None: + return self.data.__setitem__(key, value) + + def __delitem__(self, value: V) -> None: + self.data.__delitem__(value) + + def __iter__(self) -> Iterator[K]: + return self.data.__iter__() + + def keys(self) -> KeysView[K, V]: + return self.data.keys() + + +HONEY_DATA: dict[str, dict[StrOrInt, list[str | int]]] = Data('honey') + +AVATAR_DATA: dict[str, dict[str, int | str | list[int]]] = Data('avatar') +WEAPON_DATA: dict[str, dict[str, int | str]] = Data('weapon') +MATERIAL_DATA: dict[str, dict[str, int | str]] = Data('material') +ARTIFACT_DATA: dict[str, dict[str, int | str | list[int] | dict[str, str]]] = Data('reliquary') +NAMECARD_DATA: dict[str, dict[str, int | str]] = Data('namecard') def honey_id_to_game_id(honey_id: str, item_type: str) -> str | None: diff --git a/metadata/scripts/honey.py b/metadata/scripts/honey.py index 9560abad..b6328544 100644 --- a/metadata/scripts/honey.py +++ b/metadata/scripts/honey.py @@ -136,11 +136,11 @@ async def get_namecard_data() -> DATA_TYPE: if not NAMECARD_DATA: # noinspection PyProtectedMember - from metadata.genshin import _get_content + from metadata.genshin import Data from metadata.scripts.metadatas import update_metadata_from_github await update_metadata_from_github() # noinspection PyPep8Naming - NAMECARD_DATA = _get_content('namecard') + NAMECARD_DATA = Data('namecard') url = HONEY_HOST.join("fam_nameplate/?lang=CHS") result = {}