EnkaNetwork.py/enkanetwork/client.py

242 lines
7.3 KiB
Python
Raw Normal View History

from __future__ import annotations
import os
import json
import logging
from .http import HTTPClient
from .model.base import (
EnkaNetworkResponse,
EnkaNetworkProfileResponse
)
from .model.hoyos import PlayerHoyos
from .model.build import Builds
2022-07-16 19:35:08 +00:00
from .assets import Assets
2022-07-18 08:54:24 +00:00
from .enum import Language
2022-08-02 17:37:24 +00:00
from .cache import Cache
from .config import Config
2022-07-12 19:55:54 +00:00
from typing import Union, Optional, Type, TYPE_CHECKING, List, Any
if TYPE_CHECKING:
from typing_extensions import Self
from types import TracebackType
__all__ = ("EnkaNetworkAPI",)
2022-07-29 04:31:21 +00:00
class EnkaNetworkAPI:
2022-07-05 08:46:47 +00:00
LOGGER = logging.getLogger(__name__)
def __init__(self, lang: str = "en", *, debug: bool = False, key: str = "", cache: bool = True, user_agent: str = "", timeout: int = 10) -> None: # noqa: E501
2022-07-05 08:46:47 +00:00
# Logging
logging.basicConfig()
2022-07-29 04:31:21 +00:00
logging.getLogger("enkanetwork").setLevel(logging.DEBUG if debug else logging.ERROR) # noqa: E501
2022-06-22 06:14:31 +00:00
# Set language and load config
2022-07-16 19:35:08 +00:00
self.assets = Assets(lang)
2022-07-12 19:55:54 +00:00
2022-08-02 17:37:24 +00:00
# Cache
self._enable_cache = cache
if self._enable_cache:
Config.init_cache(Cache(1024, 60 * 3))
2022-08-02 17:37:24 +00:00
# http client
self.__http = HTTPClient(key=key, agent=user_agent, timeout=timeout)
self._closed = False
2022-08-03 07:50:43 +00:00
async def __aenter__(self) -> Self:
return self
async def __aexit__(
self,
exc_type: Optional[Type[BaseException]],
exc_value: Optional[BaseException],
traceback: Optional[TracebackType],
) -> None:
self._close = True
if self._close:
await self.__http.close()
def is_closed(self) -> bool:
return self._closed
2022-06-22 06:14:31 +00:00
2022-08-22 09:39:55 +00:00
@property
def http(self) -> HTTPClient:
return self.__http
@http.setter
def http(self, http: HTTPClient) -> None:
self.__http = http
2022-07-18 08:54:24 +00:00
@property
def lang(self) -> Language:
return self.assets.LANGS
@lang.setter
def lang(self, lang: Language) -> None:
self.assets._set_language(lang)
2022-08-02 17:37:24 +00:00
def set_cache(self, cache: Cache) -> None:
Config.init_cache(cache)
2022-08-02 17:37:24 +00:00
2022-07-18 08:54:24 +00:00
async def set_language(self, lang: Language) -> None:
self.lang = lang
async def fetch_user_by_uid(
self,
uid: Union[str, int],
*,
info: bool = False
) -> EnkaNetworkResponse:
2022-08-02 17:37:24 +00:00
if self._enable_cache:
self.LOGGER.warning("Getting data from cache...")
data = await Config.CACHE.get(uid)
2022-08-02 17:37:24 +00:00
if data is not None:
# Return data
self.LOGGER.debug("Parsing data...")
return EnkaNetworkResponse.parse_obj(data)
2022-08-02 17:40:30 +00:00
self.LOGGER.debug(f"Fetching user with UID {uid}...")
user = await self.__http.fetch_user_by_uid(uid, info=info)
2022-08-05 01:41:21 +00:00
data = user["content"]
2022-08-15 20:17:34 +00:00
data = json.loads(data)
2022-08-05 01:41:21 +00:00
if self._enable_cache:
self.LOGGER.debug("Caching data...")
await Config.CACHE.set(uid, data)
2022-08-05 01:41:21 +00:00
2022-07-12 19:55:54 +00:00
# Return data
self.LOGGER.debug("Parsing data...")
if "owner" in data:
data["owner"] = {
**data["owner"],
"builds": await self.fetch_builds(
profile_id=data["owner"]["username"],
metaname=data["owner"]["hash"]
)
}
2022-07-12 19:55:54 +00:00
return EnkaNetworkResponse.parse_obj(data)
2022-06-22 06:14:31 +00:00
async def fetch_user_by_username(
self,
profile_id: Union[str, int]
) -> EnkaNetworkProfileResponse:
if self._enable_cache:
self.LOGGER.warning("Getting data from cache...")
data = await Config.CACHE.get(profile_id)
if data is not None:
# Return data
self.LOGGER.debug("Parsing data...")
return EnkaNetworkProfileResponse.parse_obj(data)
self.LOGGER.debug(f"Fetching user with profile {profile_id}...")
user = await self.__http.fetch_user_by_username(profile_id)
data = user["content"]
data = json.loads(data)
if self._enable_cache:
self.LOGGER.debug("Caching data...")
await Config.CACHE.set(profile_id, data)
# Return data
self.LOGGER.debug("Parsing data...")
return EnkaNetworkProfileResponse.parse_obj({
**data,
"hoyos": await self.fetch_hoyos_by_username(profile_id)
})
async def fetch_hoyos_by_username(
self,
profile_id: Union[str, int]
) -> List[PlayerHoyos]:
key = profile_id + ":hoyos"
# Check config
if Config.CACHE_ENABLED:
self.LOGGER.warning("Getting data from cache...")
data = await Config.CACHE.get(key)
if data is not None:
self.LOGGER.debug("Parsing data...")
return await self.__format_hoyos(profile_id, data)
self.LOGGER.debug(f"Fetching user hoyos with profile {profile_id}...")
user = await self.__http.fetch_hoyos_by_username(profile_id)
data = user["content"]
data = json.loads(data)
if Config.CACHE_ENABLED:
self.LOGGER.debug("Caching data...")
await Config.CACHE.set(key, data)
self.LOGGER.debug("Parsing data...")
return await self.__format_hoyos(profile_id, data)
async def fetch_builds(
self,
*,
profile_id: Union[str, int],
metaname: Union[str, int]
) -> PlayerHoyos:
key = profile_id + ":hoyos:" + metaname + ":builds"
# Check config
if Config.CACHE_ENABLED:
self.LOGGER.warning("Getting data from cache...")
data = await Config.CACHE.get(key)
if data is not None:
self.LOGGER.debug("Parsing data...")
return await self.__format_hoyos(profile_id, data)
# Request data first
user = await self.__http.fetch_hoyos_by_username(profile_id,metaname,True)
data = user["content"]
data = json.loads(data)
if Config.CACHE_ENABLED:
self.LOGGER.debug("Caching data...")
await Config.CACHE.set(key, data)
self.LOGGER.debug("Parsing data...")
return Builds.parse_obj(data)
async def request_enka():
pass
async def update_assets(self) -> None:
print("Updating assets...")
2022-07-12 19:55:54 +00:00
self.LOGGER.debug("Downloading new content...")
path = Assets._get_path_assets()
for folder in path:
for filename in os.listdir(path[folder]):
self.LOGGER.debug(f"Downloading {folder} file {filename}...")
2022-08-05 02:21:21 +00:00
data = await self.__http.fetch_asset(folder, filename)
self.LOGGER.debug(f"Writing {folder} file {filename}...")
# dumps to json file
with open(os.path.join(path[folder], filename), "w", encoding="utf-8") as f:
json.dump(json.loads(data["content"]),
f, ensure_ascii=False, indent=4)
2022-06-22 06:14:31 +00:00
# Reload config
2022-07-29 04:31:21 +00:00
self.assets.reload_assets()
async def __format_hoyos(self, username: str, data: List[Any]) -> List[PlayerHoyos]:
return [PlayerHoyos.parse_obj({
"builds": await self.fetch_builds(profile_id=username, metaname=data[key]["hash"]),
**data[key]
}) for key in data]
# Concept by genshin.py python library
fetch_user = fetch_user_by_uid
fetch_profile = fetch_user_by_username