Fix pattern code. (Flake8)

This commit is contained in:
M-307 2022-07-29 11:31:21 +07:00
parent e352031691
commit bb78e8aa7c
13 changed files with 192 additions and 160 deletions

View File

@ -1,8 +1,8 @@
from .client import * from .client import * # noqa: F403
from .exception import * from .exception import * # noqa: F403
from .model import * from .model import * # noqa: F403
from .utils import * from .utils import * # noqa: F403
from .info import * from .info import * # noqa: F403
__VERSION__ = VERSION __VERSION__ = VERSION # noqa: F405
__AUTHOR__ = AUTHOR __AUTHOR__ = AUTHOR # noqa: F405

View File

@ -13,14 +13,10 @@ PATH = os.path.dirname(os.path.abspath(__file__))
LOGGER = logging.getLogger(__name__) LOGGER = logging.getLogger(__name__)
class Assets: class Assets:
# Characters & Skills
DATA: Dict[str, dict] = {} DATA: Dict[str, dict] = {}
# Hash Map
HASH_MAP: Dict[str, dict] = {} HASH_MAP: Dict[str, dict] = {}
# Language
LANGS: Language = Language.EN LANGS: Language = Language.EN
def __init__(self, lang: Language = Language.EN) -> None: def __init__(self, lang: Language = Language.EN) -> None:
@ -49,7 +45,7 @@ class Assets:
}) })
@classmethod @classmethod
def constellations(cls, id: int) -> Union[assets.CharacterConstellationsAsset, None]: def constellations(cls, id: int) -> Union[assets.CharacterConstellationsAsset, None]: # noqa: E501
LOGGER.debug(f"Getting character constellations assets with id: {id}") LOGGER.debug(f"Getting character constellations assets with id: {id}")
data = cls.DATA["constellations"].get(str(id)) data = cls.DATA["constellations"].get(str(id))
if not data: if not data:
@ -94,14 +90,14 @@ class Assets:
@classmethod @classmethod
def get_hash_map(cls, hash_id: str) -> Union[str, None]: def get_hash_map(cls, hash_id: str) -> Union[str, None]:
LOGGER.debug(f"Getting nameTextMapHash {hash_id} with language: {cls.LANGS}") LOGGER.debug(f"Getting nameTextMapHash {hash_id} with language: {cls.LANGS}") # noqa: E501
for key in cls.HASH_MAP: for key in cls.HASH_MAP:
if str(hash_id) in cls.HASH_MAP[key]: if str(hash_id) in cls.HASH_MAP[key]:
val = cls.HASH_MAP[key][str(hash_id)][cls.LANGS] val = cls.HASH_MAP[key][str(hash_id)][cls.LANGS]
LOGGER.debug(f"Got nameTextMapHash {hash_id} with language: {key} (Value '{val}')") LOGGER.debug(f"Got nameTextMapHash {hash_id} with language: {key} (Value '{val}')") # noqa: E501
return val return val
LOGGER.error(f"nameTextMapHash {hash_id} not found with language: {cls.LANGS}") LOGGER.error(f"nameTextMapHash {hash_id} not found with language: {cls.LANGS}") # noqa: E501
return return
@classmethod @classmethod
@ -117,7 +113,7 @@ class Assets:
return assets.CharacterIconAsset( return assets.CharacterIconAsset(
icon=create_ui_path(path.replace("_Side", "")), icon=create_ui_path(path.replace("_Side", "")),
side=create_ui_path(path), side=create_ui_path(path),
banner=create_ui_path(path.replace("AvatarIcon_Side", "Gacha_AvatarImg")) banner=create_ui_path(path.replace("AvatarIcon_Side", "Gacha_AvatarImg")) # noqa: E501
) )
@staticmethod @staticmethod
@ -128,7 +124,7 @@ class Assets:
def _set_language(cls, lang: Language) -> None: def _set_language(cls, lang: Language) -> None:
# Check language # Check language
if not lang.split("-")[0].lower() in list(Language): if not lang.split("-")[0].lower() in list(Language):
raise ValueError("Language not supported. Please check your language.") raise ValueError("Language not supported. Please check your language.") # noqa: E501
LOGGER.debug(f"Set language to {lang}.") LOGGER.debug(f"Set language to {lang}.")
cls.LANGS = lang.upper() cls.LANGS = lang.upper()
@ -146,7 +142,7 @@ class Assets:
FILE_LANG = os.listdir(_PATH) FILE_LANG = os.listdir(_PATH)
for FILENAME in FILE_LANG: for FILENAME in FILE_LANG:
LOGGER.debug(f"Loading language file {FILENAME}...") LOGGER.debug(f"Loading language file {FILENAME}...")
cls.HASH_MAP[FILENAME.split(".")[0]] = json.load(cls.__load(os.path.join(_PATH, FILENAME))) cls.HASH_MAP[FILENAME.split(".")[0]] = json.load(cls.__load(os.path.join(_PATH, FILENAME))) # noqa: E501
@classmethod @classmethod
def __load_assets_data(cls) -> None: def __load_assets_data(cls) -> None:
@ -154,7 +150,7 @@ class Assets:
FILE_DATA = os.listdir(_PATH) FILE_DATA = os.listdir(_PATH)
for FILENAME in FILE_DATA: for FILENAME in FILE_DATA:
LOGGER.debug(f"Loading data file {FILENAME}...") LOGGER.debug(f"Loading data file {FILENAME}...")
cls.DATA[FILENAME.split(".")[0]] = json.load(cls.__load(os.path.join(_PATH, FILENAME))) cls.DATA[FILENAME.split(".")[0]] = json.load(cls.__load(os.path.join(_PATH, FILENAME))) # noqa: E501
def __load(path: str) -> TextIOWrapper: def __load(path: str) -> TextIOWrapper:
return open(path, "r", encoding="utf-8") return open(path, "r", encoding="utf-8")

View File

@ -10,16 +10,15 @@ from .assets import Assets
from .utils import create_path, validate_uid, request from .utils import create_path, validate_uid, request
from .enum import Language from .enum import Language
class EnkaNetworkAPI: class EnkaNetworkAPI:
LOGGER = logging.getLogger(__name__) LOGGER = logging.getLogger(__name__)
RAWDATA = "https://raw.githubusercontent.com/mrwan200/enkanetwork.py-data/{PATH}" # noqa: E501
# JSON Data & Language def __init__(self, lang: str = "en", debug: bool = False, key: str = "") -> None: # noqa: E501
RAWDATA = "https://raw.githubusercontent.com/mrwan200/enkanetwork.py-data/{PATH}"
def __init__(self, lang: str = "en", debug: bool = False, key: str = "") -> None:
# Logging # Logging
logging.basicConfig() logging.basicConfig()
logging.getLogger("enkanetwork").setLevel(logging.DEBUG if debug else logging.ERROR) logging.getLogger("enkanetwork").setLevel(logging.DEBUG if debug else logging.ERROR) # noqa: E501
# Set language and load config # Set language and load config
self.assets = Assets(lang) self.assets = Assets(lang)
@ -41,11 +40,11 @@ class EnkaNetworkAPI:
async def fetch_user(self, uid: Union[str, int]) -> EnkaNetworkResponse: async def fetch_user(self, uid: Union[str, int]) -> EnkaNetworkResponse:
self.LOGGER.debug(f"Validating with UID {uid}...") self.LOGGER.debug(f"Validating with UID {uid}...")
if not validate_uid(str(uid)): if not validate_uid(str(uid)):
raise VaildateUIDError("Validate UID failed. Please check your UID.") raise VaildateUIDError("Validate UID failed. Please check your UID.") # noqa: E501
self.LOGGER.debug(f"Fetching user with UID {uid}...") self.LOGGER.debug(f"Fetching user with UID {uid}...")
resp = await request(url=create_path(f"u/{uid}/__data.json" + ("?key={key}" if self.__key else ""))) resp = await request(url=create_path(f"u/{uid}/__data.json" + ("?key={key}" if self.__key else ""))) # noqa: E501
# Check if status code is not 200 (Ex. 500) # Check if status code is not 200 (Ex. 500)
if resp["status"] != 200: if resp["status"] != 200:
@ -71,12 +70,12 @@ class EnkaNetworkAPI:
for filename in os.listdir(_PATH[folder]): for filename in os.listdir(_PATH[folder]):
self.LOGGER.debug(f"Downloading {folder} file {filename}...") self.LOGGER.debug(f"Downloading {folder} file {filename}...")
_json = await request( _json = await request(
url=self.RAWDATA.format(PATH=f"master/exports/{folder}/{filename}") url=self.RAWDATA.format(PATH=f"master/exports/{folder}/{filename}") # noqa: E501
) )
self.LOGGER.debug(f"Writing {folder} file {filename}...") self.LOGGER.debug(f"Writing {folder} file {filename}...")
with open(os.path.join(_PATH[folder], filename), "w", encoding="utf-8") as f: with open(os.path.join(_PATH[folder], filename), "w", encoding="utf-8") as f: # noqa: E501
json.dump(_json["content"], f, ensure_ascii=False, indent=4) json.dump(_json["content"], f, ensure_ascii=False, indent=4) # noqa: E501
# Reload config # Reload config
self.assets.reload_assets() self.assets.reload_assets()

View File

@ -1,5 +1,6 @@
from enum import Enum from enum import Enum
class Language(str, Enum): class Language(str, Enum):
EN = "en" EN = "en"
RU = "ru" RU = "ru"
@ -22,15 +23,18 @@ class Language(str, Enum):
CHT = "cht" CHT = "cht"
CHS = "chs" CHS = "chs"
class EquipmentsType(int, Enum): class EquipmentsType(int, Enum):
UNKNOWN = -1 UNKNOWN = -1
ARTIFACT = 0 ARTIFACT = 0
WEAPON = 1 WEAPON = 1
class DigitType(int, Enum): class DigitType(int, Enum):
NUMBER = 0 NUMBER = 0
PERCENT = 1 PERCENT = 1
class ElementType(str, Enum): class ElementType(str, Enum):
Unknown = "Unknown" Unknown = "Unknown"
Cryo = "Ice" Cryo = "Ice"
@ -40,6 +44,7 @@ class ElementType(str, Enum):
Geo = "Rock" Geo = "Rock"
Electro = "Electric" Electro = "Electric"
class EquipType(str, Enum): class EquipType(str, Enum):
Unknown = "UNKNOWN" Unknown = "UNKNOWN"
Flower = "EQUIP_BRACER" Flower = "EQUIP_BRACER"

View File

@ -1,5 +1,6 @@
class VaildateUIDError(Exception): class VaildateUIDError(Exception):
pass pass
class UIDNotFounded(Exception): class UIDNotFounded(Exception):
pass pass

View File

@ -4,6 +4,7 @@ from typing import List
from .players import PlayerInfo from .players import PlayerInfo
from .character import CharacterInfo from .character import CharacterInfo
class EnkaNetworkResponse(BaseModel): class EnkaNetworkResponse(BaseModel):
player: PlayerInfo = Field(None, alias="playerInfo") player: PlayerInfo = Field(None, alias="playerInfo")
characters: List[CharacterInfo] = Field(None, alias="avatarInfoList") characters: List[CharacterInfo] = Field(None, alias="avatarInfoList")

View File

@ -3,6 +3,7 @@ from typing import List, Any
from ..enum import ElementType from ..enum import ElementType
class NamecardAsset(BaseModel): class NamecardAsset(BaseModel):
id: int = 0 id: int = 0
hash_id: str = Field("", alias="nameTextMapHash") hash_id: str = Field("", alias="nameTextMapHash")
@ -10,25 +11,24 @@ class NamecardAsset(BaseModel):
banner: str = "" banner: str = ""
navbar: str = "" navbar: str = ""
class CharacterIconAsset(BaseModel): class CharacterIconAsset(BaseModel):
icon: str = "" icon: str = ""
side: str = "" side: str = ""
banner: str = "" banner: str = ""
class CharacterSkillAsset(BaseModel): class CharacterSkillAsset(BaseModel):
id: int = 0 id: int = 0
hash_id: str = Field("", alias="nameTextMapHash") hash_id: str = Field("", alias="nameTextMapHash")
icon: str = Field(None, alias="skillIcon") icon: str = Field(None, alias="skillIcon")
class CharacterConstellationsAsset(BaseModel): class CharacterConstellationsAsset(BaseModel):
id: int = 0 id: int = 0
hash_id: str = Field("", alias="nameTextMapHash") hash_id: str = Field("", alias="nameTextMapHash")
icon: str = Field(None, alias="icon") icon: str = Field(None, alias="icon")
class CharacterSkillAsset(BaseModel):
id: int = 0
hash_id: str = Field("", alias="nameTextMapHash")
icon: str = Field(None, alias="skillIcon")
class CharacterAsset(BaseModel): class CharacterAsset(BaseModel):
id: int = 0 id: int = 0
@ -44,4 +44,4 @@ class CharacterAsset(BaseModel):
def __init__(__pydantic_self__, **data: Any) -> None: def __init__(__pydantic_self__, **data: Any) -> None:
super().__init__(**data) super().__init__(**data)
__pydantic_self__.element = ElementType(data["costElemType"]) if data["costElemType"] != "" else ElementType.Unknown.name __pydantic_self__.element = ElementType(data["costElemType"]) if data["costElemType"] != "" else ElementType.Unknown.name # noqa: E501

View File

@ -13,18 +13,21 @@ from ..enum import ElementType
LOGGER = logging.getLogger(__name__) LOGGER = logging.getLogger(__name__)
class CharacterSkill(BaseModel): class CharacterSkill(BaseModel):
id: int = 0 id: int = 0
name: str = "" name: str = ""
icon: str = "" icon: str = ""
level: int = 0 level: int = 0
class CharacterConstellations(BaseModel): class CharacterConstellations(BaseModel):
id: int = 0 id: int = 0
name: str = "" name: str = ""
icon: str = "" icon: str = ""
unlocked: bool = False # If character has this constellation. unlocked: bool = False # If character has this constellation.
class CharacterInfo(BaseModel): class CharacterInfo(BaseModel):
""" """
API Response data API Response data
@ -61,18 +64,23 @@ class CharacterInfo(BaseModel):
__pydantic_self__.friendship_level = data["fetterInfo"]["expLevel"] __pydantic_self__.friendship_level = data["fetterInfo"]["expLevel"]
# Get prop map # Get prop map
__pydantic_self__.xp = int(data["propMap"]["1001"]["ival"]) if "1001" in data["propMap"] else 0 __pydantic_self__.xp = int(
__pydantic_self__.ascension = int(data["propMap"]["1002"]["ival"]) if "1002" in data["propMap"] else 0 data["propMap"]["1001"]["ival"]) if "1001" in data["propMap"] else 0 # noqa: E501
__pydantic_self__.level = int(data["propMap"]["4001"]["ival"]) if "4001" in data["propMap"] else 0 __pydantic_self__.ascension = int(
data["propMap"]["1002"]["ival"]) if "1002" in data["propMap"] else 0 # noqa: E501
__pydantic_self__.level = int(
data["propMap"]["4001"]["ival"]) if "4001" in data["propMap"] else 0 # noqa: E501
# Constellation unlocked count # Constellation unlocked count
__pydantic_self__.constellations_unlocked = len(data["talentIdList"]) if "talentIdList" in data else 0 __pydantic_self__.constellations_unlocked = len(
data["talentIdList"]) if "talentIdList" in data else 0
# Get max character level # Get max character level
__pydantic_self__.max_level = (__pydantic_self__.ascension * 10) + (10 if __pydantic_self__.ascension > 0 else 0) + 20 __pydantic_self__.max_level = (
__pydantic_self__.ascension * 10) + (10 if __pydantic_self__.ascension > 0 else 0) + 20 # noqa: E501
# Get character # Get character
LOGGER.debug(f"=== Character Data ===") LOGGER.debug("=== Character Data ===")
character = Assets.character(str(data["avatarId"])) character = Assets.character(str(data["avatarId"]))
# Check if character is founded # Check if character is founded
@ -86,7 +94,7 @@ class CharacterInfo(BaseModel):
__pydantic_self__.element = ElementType(character.element).name __pydantic_self__.element = ElementType(character.element).name
# Load constellation # Load constellation
LOGGER.debug(f"=== Constellation ===") LOGGER.debug("=== Constellation ===")
for constellation in character.constellations: for constellation in character.constellations:
_constellation = Assets.constellations(constellation) _constellation = Assets.constellations(constellation)
if not _constellation: if not _constellation:
@ -102,11 +110,12 @@ class CharacterInfo(BaseModel):
id=int(constellation), id=int(constellation),
name=_name, name=_name,
icon=_constellation.icon, icon=_constellation.icon,
unlocked=int(constellation) in data["talentIdList"] if "talentIdList" in data else False unlocked=int(
constellation) in data["talentIdList"] if "talentIdList" in data else False # noqa: E501
)) ))
# Load skills # Load skills
LOGGER.debug(f"=== Skills ===") LOGGER.debug("=== Skills ===")
for skill in character.skills: for skill in character.skills:
_skill = Assets.skills(skill) _skill = Assets.skills(skill)
@ -126,7 +135,7 @@ class CharacterInfo(BaseModel):
level=data["skillLevelMap"].get(str(skill), 0) level=data["skillLevelMap"].get(str(skill), 0)
)) ))
LOGGER.debug(f"=== Character Name ===") LOGGER.debug("=== Character Name ===")
_name = Assets.get_hash_map(str(character.hash_id)) _name = Assets.get_hash_map(str(character.hash_id))
if _name is None: if _name is None:

View File

@ -9,6 +9,7 @@ from ..utils import create_ui_path
LOGGER = logging.getLogger(__name__) LOGGER = logging.getLogger(__name__)
class EquipmentsStats(BaseModel): class EquipmentsStats(BaseModel):
prop_id: str = "" prop_id: str = ""
type: DigitType = DigitType.NUMBER type: DigitType = DigitType.NUMBER
@ -23,7 +24,7 @@ class EquipmentsStats(BaseModel):
__pydantic_self__.value = data["statValue"] __pydantic_self__.value = data["statValue"]
LOGGER.debug(f"=== Fight prop ===") LOGGER.debug("=== Fight prop ===")
if "mainPropId" in data: if "mainPropId" in data:
__pydantic_self__.prop_id = str(data["mainPropId"]) __pydantic_self__.prop_id = str(data["mainPropId"])
@ -37,6 +38,7 @@ class EquipmentsStats(BaseModel):
__pydantic_self__.name = fight_prop __pydantic_self__.name = fight_prop
class EquipmentsDetail(BaseModel): class EquipmentsDetail(BaseModel):
""" """
Custom data Custom data
@ -53,33 +55,37 @@ class EquipmentsDetail(BaseModel):
super().__init__(**data) super().__init__(**data)
if data["itemType"] == "ITEM_RELIQUARY": # AKA. Artifact if data["itemType"] == "ITEM_RELIQUARY": # AKA. Artifact
LOGGER.debug(f"=== Artifact ===") LOGGER.debug("=== Artifact ===")
__pydantic_self__.icon = Assets.create_icon_path(data["icon"]) __pydantic_self__.icon = Assets.create_icon_path(data["icon"])
__pydantic_self__.artifact_type = EquipType(data["equipType"]).name __pydantic_self__.artifact_type = EquipType(data["equipType"]).name
# Sub Stats # Sub Stats
for stats in data["reliquarySubstats"]: for stats in data["reliquarySubstats"]:
__pydantic_self__.substats.append(EquipmentsStats.parse_obj(stats)) __pydantic_self__.substats.append(
EquipmentsStats.parse_obj(stats))
if data["itemType"] == "ITEM_WEAPON": # AKA. Weapon if data["itemType"] == "ITEM_WEAPON": # AKA. Weapon
LOGGER.debug(f"=== Weapon ===") LOGGER.debug("=== Weapon ===")
__pydantic_self__.icon = create_ui_path(data["icon"]) __pydantic_self__.icon = create_ui_path(data["icon"])
# Main and Sub Stats # Main and Sub Stats
__pydantic_self__.mainstats = EquipmentsStats.parse_obj(data["weaponStats"][0]) __pydantic_self__.mainstats = EquipmentsStats.parse_obj(
data["weaponStats"][0])
for stats in data["weaponStats"][1:]: for stats in data["weaponStats"][1:]:
__pydantic_self__.substats.append(EquipmentsStats.parse_obj(stats)) __pydantic_self__.substats.append(
EquipmentsStats.parse_obj(stats))
_name = Assets.get_hash_map(str(data["nameTextMapHash"])) _name = Assets.get_hash_map(str(data["nameTextMapHash"]))
if "setNameTextMapHash" in data: if "setNameTextMapHash" in data:
_artifact_name_set = Assets.get_hash_map(str(data["setNameTextMapHash"])) _artifact_name_set = Assets.get_hash_map(
str(data["setNameTextMapHash"]))
__pydantic_self__.artifact_name_set = _artifact_name_set or "" __pydantic_self__.artifact_name_set = _artifact_name_set or ""
__pydantic_self__.name = _name if not _name is None else "" __pydantic_self__.name = _name if _name is not None else ""
class Config: class Config:
use_enum_values = True use_enum_values = True
class Equipments(BaseModel): class Equipments(BaseModel):
""" """
API Response data API Response data
@ -91,7 +97,8 @@ class Equipments(BaseModel):
Custom data Custom data
""" """
level: int = 0 # Get form key "reliquary" and "weapon" level: int = 0 # Get form key "reliquary" and "weapon"
type: EquipmentsType = EquipmentsType.UNKNOWN # Type of equipments (Ex. Artifact, Weapon) # Type of equipments (Ex. Artifact, Weapon)
type: EquipmentsType = EquipmentsType.UNKNOWN
refinement: int = 0 # Refinement of equipments (Weapon only) refinement: int = 0 # Refinement of equipments (Weapon only)
ascension: int = 0 # Ascension (Weapon only) ascension: int = 0 # Ascension (Weapon only)
@ -109,6 +116,7 @@ class Equipments(BaseModel):
__pydantic_self__.type = EquipmentsType.WEAPON __pydantic_self__.type = EquipmentsType.WEAPON
__pydantic_self__.level = data["weapon"]["level"] __pydantic_self__.level = data["weapon"]["level"]
if "affixMap" in data["weapon"]: if "affixMap" in data["weapon"]:
__pydantic_self__.refinement = data["weapon"]["affixMap"][list(data["weapon"]["affixMap"].keys())[0]] + 1 __pydantic_self__.refinement = data["weapon"]["affixMap"][list(
data["weapon"]["affixMap"].keys())[0]] + 1
if "promoteLevel" in data["weapon"]: if "promoteLevel" in data["weapon"]:
__pydantic_self__.ascension = data["weapon"]["promoteLevel"] __pydantic_self__.ascension = data["weapon"]["promoteLevel"]

View File

@ -4,9 +4,10 @@ from pydantic import BaseModel, Field
from typing import List, Any from typing import List, Any
from ..assets import Assets from ..assets import Assets
from ..utils import create_ui_path
LOGGER = logging.getLogger(__name__) LOGGER = logging.getLogger(__name__)
class ProfilePicture(BaseModel): class ProfilePicture(BaseModel):
""" """
API Response data API Response data
@ -22,7 +23,7 @@ class ProfilePicture(BaseModel):
super().__init__(**data) super().__init__(**data)
# Get character # Get character
LOGGER.debug(f"=== Avatar ===") LOGGER.debug("=== Avatar ===")
icon = Assets.character_icon(str(data["avatarId"])) icon = Assets.character_icon(str(data["avatarId"]))
if not icon: if not icon:
@ -30,6 +31,7 @@ class ProfilePicture(BaseModel):
__pydantic_self__.url = icon.icon __pydantic_self__.url = icon.icon
class showAvatar(BaseModel): class showAvatar(BaseModel):
""" """
API Response data API Response data
@ -47,7 +49,7 @@ class showAvatar(BaseModel):
super().__init__(**data) super().__init__(**data)
# Get character # Get character
LOGGER.debug(f"=== Character preview ===") LOGGER.debug("=== Character preview ===")
character_preview = Assets.character(str(data["avatarId"])) character_preview = Assets.character(str(data["avatarId"]))
if not character_preview: if not character_preview:
@ -75,7 +77,7 @@ class Namecard(BaseModel):
super().__init__(**data) super().__init__(**data)
if __pydantic_self__.id > 0: if __pydantic_self__.id > 0:
LOGGER.debug(f"=== Namecard ===") LOGGER.debug("=== Namecard ===")
# Get name card # Get name card
namecard = Assets.namecards(str(__pydantic_self__.id)) namecard = Assets.namecards(str(__pydantic_self__.id))
@ -92,6 +94,7 @@ class Namecard(BaseModel):
__pydantic_self__.name = _name __pydantic_self__.name = _name
class PlayerInfo(BaseModel): class PlayerInfo(BaseModel):
""" """
API Response data API Response data
@ -104,7 +107,8 @@ class PlayerInfo(BaseModel):
world_level: int = Field(1, alias="worldLevel") world_level: int = Field(1, alias="worldLevel")
icon: ProfilePicture = Field(None, alias="profilePicture") icon: ProfilePicture = Field(None, alias="profilePicture")
# Avatars # Avatars
characters_preview: List[showAvatar] = Field([], alias="showAvatarInfoList") characters_preview: List[showAvatar] = Field(
[], alias="showAvatarInfoList")
# Abyss floor # Abyss floor
abyss_floor: int = Field(0, alias="towerFloorIndex") abyss_floor: int = Field(0, alias="towerFloorIndex")
abyss_room: int = Field(0, alias="towerLevelIndex") abyss_room: int = Field(0, alias="towerLevelIndex")
@ -119,4 +123,5 @@ class PlayerInfo(BaseModel):
super().__init__(**data) super().__init__(**data)
__pydantic_self__.namecard = Namecard(id=data["nameCardId"]) __pydantic_self__.namecard = Namecard(id=data["nameCardId"])
__pydantic_self__.namecards = [Namecard(id=namecard) for namecard in (data["showNameCardIdList"])] if "showNameCardIdList" in data else [] __pydantic_self__.namecards = [Namecard(id=namecard) for namecard in (
data["showNameCardIdList"])] if "showNameCardIdList" in data else [] # noqa: E501

View File

@ -4,6 +4,7 @@ from pydantic import BaseModel
from typing import Any from typing import Any
class Stats(BaseModel): class Stats(BaseModel):
id: int = 0 id: int = 0
value: float = 0 value: float = 0
@ -11,6 +12,7 @@ class Stats(BaseModel):
def to_rounded(self) -> float: def to_rounded(self) -> float:
return math.ceil(self.value) return math.ceil(self.value)
class StatsPercentage(BaseModel): class StatsPercentage(BaseModel):
id: int = 0 id: int = 0
value: float = 0.0 value: float = 0.0
@ -21,6 +23,7 @@ class StatsPercentage(BaseModel):
def to_percentage_symbol(self) -> str: def to_percentage_symbol(self) -> str:
return f"{self.to_percentage()}%" return f"{self.to_percentage()}%"
class CharacterStats(BaseModel): class CharacterStats(BaseModel):
BASE_HP: Stats = Stats(id=1, value=0) BASE_HP: Stats = Stats(id=1, value=0)
FIGHT_PROP_HP: Stats = Stats(id=2, value=0) FIGHT_PROP_HP: Stats = Stats(id=2, value=0)
@ -30,7 +33,7 @@ class CharacterStats(BaseModel):
FIGHT_PROP_ATTACK_PERCENT: StatsPercentage = StatsPercentage(id=6, value=0) FIGHT_PROP_ATTACK_PERCENT: StatsPercentage = StatsPercentage(id=6, value=0)
FIGHT_PROP_BASE_DEFENSE: Stats = Stats(id=7, value=0) FIGHT_PROP_BASE_DEFENSE: Stats = Stats(id=7, value=0)
FIGHT_PROP_DEFENSE: Stats = Stats(id=8, value=0) FIGHT_PROP_DEFENSE: Stats = Stats(id=8, value=0)
FIGHT_PROP_DEFENSE_PERCENT: StatsPercentage = StatsPercentage(id=9, value=0) FIGHT_PROP_DEFENSE_PERCENT: StatsPercentage = StatsPercentage(id=9, value=0) # noqa: E501
FIGHT_PROP_BASE_SPEED: Stats = Stats(id=10, value=0) FIGHT_PROP_BASE_SPEED: Stats = Stats(id=10, value=0)
FIGHT_PROP_SPEED_PERCENT: StatsPercentage = StatsPercentage(id=11, value=0) FIGHT_PROP_SPEED_PERCENT: StatsPercentage = StatsPercentage(id=11, value=0)
FIGHT_PROP_HP_MP_PERCENT: StatsPercentage = StatsPercentage(id=12, value=0) FIGHT_PROP_HP_MP_PERCENT: StatsPercentage = StatsPercentage(id=12, value=0)
@ -38,28 +41,28 @@ class CharacterStats(BaseModel):
FIGHT_PROP_CRITICAL: StatsPercentage = StatsPercentage(id=20, value=0) FIGHT_PROP_CRITICAL: StatsPercentage = StatsPercentage(id=20, value=0)
FIGHT_PROP_ANTI_CRITICAL: StatsPercentage = StatsPercentage(id=21, value=0) FIGHT_PROP_ANTI_CRITICAL: StatsPercentage = StatsPercentage(id=21, value=0)
FIGHT_PROP_CRITICAL_HURT: StatsPercentage = StatsPercentage(id=22, value=0) FIGHT_PROP_CRITICAL_HURT: StatsPercentage = StatsPercentage(id=22, value=0)
FIGHT_PROP_CHARGE_EFFICIENCY: StatsPercentage = StatsPercentage(id=23, value=0) FIGHT_PROP_CHARGE_EFFICIENCY: StatsPercentage = StatsPercentage(id=23, value=0) # noqa: E501
FIGHT_PROP_ADD_HURT: StatsPercentage = StatsPercentage(id=24, value=0) FIGHT_PROP_ADD_HURT: StatsPercentage = StatsPercentage(id=24, value=0)
FIGHT_PROP_SUB_HURT: StatsPercentage = StatsPercentage(id=25, value=0) FIGHT_PROP_SUB_HURT: StatsPercentage = StatsPercentage(id=25, value=0)
FIGHT_PROP_HEAL_ADD: StatsPercentage = StatsPercentage(id=26, value=0) FIGHT_PROP_HEAL_ADD: StatsPercentage = StatsPercentage(id=26, value=0)
FIGHT_PROP_HEALED_ADD: StatsPercentage = StatsPercentage(id=27, value=0) FIGHT_PROP_HEALED_ADD: StatsPercentage = StatsPercentage(id=27, value=0)
FIGHT_PROP_ELEMENT_MASTERY: Stats = Stats(id=28, value=0) FIGHT_PROP_ELEMENT_MASTERY: Stats = Stats(id=28, value=0)
FIGHT_PROP_PHYSICAL_SUB_HURT: StatsPercentage = StatsPercentage(id=29, value=0) FIGHT_PROP_PHYSICAL_SUB_HURT: StatsPercentage = StatsPercentage(id=29, value=0) # noqa: E501
FIGHT_PROP_PHYSICAL_ADD_HURT: StatsPercentage = StatsPercentage(id=30, value=0) FIGHT_PROP_PHYSICAL_ADD_HURT: StatsPercentage = StatsPercentage(id=30, value=0) # noqa: E501
FIGHT_PROP_DEFENCE_IGNORE_RATIO: Stats = Stats(id=31, value=0) FIGHT_PROP_DEFENCE_IGNORE_RATIO: Stats = Stats(id=31, value=0)
FIGHT_PROP_DEFENCE_IGNORE_DELTA: Stats = Stats(id=32, value=0) FIGHT_PROP_DEFENCE_IGNORE_DELTA: Stats = Stats(id=32, value=0)
FIGHT_PROP_FIRE_ADD_HURT: StatsPercentage = StatsPercentage(id=40, value=0) FIGHT_PROP_FIRE_ADD_HURT: StatsPercentage = StatsPercentage(id=40, value=0)
FIGHT_PROP_ELEC_ADD_HURT: StatsPercentage = StatsPercentage(id=41, value=0) FIGHT_PROP_ELEC_ADD_HURT: StatsPercentage = StatsPercentage(id=41, value=0)
FIGHT_PROP_WATER_ADD_HURT: StatsPercentage = StatsPercentage(id=42, value=0) FIGHT_PROP_WATER_ADD_HURT: StatsPercentage = StatsPercentage(id=42, value=0) # noqa: E501
FIGHT_PROP_GRASS_ADD_HURT: StatsPercentage = StatsPercentage(id=43, value=0) FIGHT_PROP_GRASS_ADD_HURT: StatsPercentage = StatsPercentage(id=43, value=0) # noqa: E501
FIGHT_PROP_WIND_ADD_HURT: StatsPercentage = StatsPercentage(id=44, value=0) FIGHT_PROP_WIND_ADD_HURT: StatsPercentage = StatsPercentage(id=44, value=0)
FIGHT_PROP_ROCK_ADD_HURT: StatsPercentage = StatsPercentage(id=45, value=0) FIGHT_PROP_ROCK_ADD_HURT: StatsPercentage = StatsPercentage(id=45, value=0)
FIGHT_PROP_ICE_ADD_HURT: StatsPercentage = StatsPercentage(id=46, value=0) FIGHT_PROP_ICE_ADD_HURT: StatsPercentage = StatsPercentage(id=46, value=0) # noqa: E501
FIGHT_PROP_HIT_HEAD_ADD_HURT: StatsPercentage = StatsPercentage(id=47, value=0) FIGHT_PROP_HIT_HEAD_ADD_HURT: StatsPercentage = StatsPercentage(id=47, value=0) # noqa: E501
FIGHT_PROP_FIRE_SUB_HURT: StatsPercentage = StatsPercentage(id=50, value=0) FIGHT_PROP_FIRE_SUB_HURT: StatsPercentage = StatsPercentage(id=50, value=0)
FIGHT_PROP_ELEC_SUB_HURT: StatsPercentage = StatsPercentage(id=51, value=0) FIGHT_PROP_ELEC_SUB_HURT: StatsPercentage = StatsPercentage(id=51, value=0)
FIGHT_PROP_WATER_SUB_HURT: StatsPercentage = StatsPercentage(id=52, value=0) FIGHT_PROP_WATER_SUB_HURT: StatsPercentage = StatsPercentage(id=52, value=0) # noqa: E501
FIGHT_PROP_GRASS_SUB_HURT: StatsPercentage = StatsPercentage(id=53, value=0) FIGHT_PROP_GRASS_SUB_HURT: StatsPercentage = StatsPercentage(id=53, value=0) # noqa: E501
FIGHT_PROP_WIND_SUB_HURT: StatsPercentage = StatsPercentage(id=54, value=0) FIGHT_PROP_WIND_SUB_HURT: StatsPercentage = StatsPercentage(id=54, value=0)
FIGHT_PROP_ROCK_SUB_HURT: StatsPercentage = StatsPercentage(id=55, value=0) FIGHT_PROP_ROCK_SUB_HURT: StatsPercentage = StatsPercentage(id=55, value=0)
FIGHT_PROP_ICE_SUB_HURT: StatsPercentage = StatsPercentage(id=56, value=0) FIGHT_PROP_ICE_SUB_HURT: StatsPercentage = StatsPercentage(id=56, value=0)
@ -95,35 +98,35 @@ class CharacterStats(BaseModel):
FIGHT_PROP_CUR_DEFENSE: Stats = Stats(id=2002, value=0) FIGHT_PROP_CUR_DEFENSE: Stats = Stats(id=2002, value=0)
FIGHT_PROP_CUR_SPEED: Stats = Stats(id=2003, value=0) FIGHT_PROP_CUR_SPEED: Stats = Stats(id=2003, value=0)
FIGHT_PROP_NONEXTRA_ATTACK: Stats = Stats(id=3000, value=0) FIGHT_PROP_NONEXTRA_ATTACK: Stats = Stats(id=3000, value=0) # noqa: E501
FIGHT_PROP_NONEXTRA_DEFENSE: Stats = Stats(id=3001, value=0) FIGHT_PROP_NONEXTRA_DEFENSE: Stats = Stats(id=3001, value=0)
FIGHT_PROP_NONEXTRA_CRITICAL: StatsPercentage = StatsPercentage(id=3002, value=0) FIGHT_PROP_NONEXTRA_CRITICAL: StatsPercentage = StatsPercentage(id=3002, value=0) # noqa: E501
FIGHT_PROP_CUR_SPEED: Stats = Stats(id=3003, value=0) FIGHT_PROP_CUR_SPEED: Stats = Stats(id=3003, value=0)
FIGHT_PROP_NONEXTRA_CRITICAL_HURT: StatsPercentage = StatsPercentage(id=3004, value=0) FIGHT_PROP_NONEXTRA_CRITICAL_HURT: StatsPercentage = StatsPercentage(id=3004, value=0) # noqa: E501
FIGHT_PROP_NONEXTRA_CHARGE_EFFICIENCY: StatsPercentage = StatsPercentage(id=3005, value=0) FIGHT_PROP_NONEXTRA_CHARGE_EFFICIENCY: StatsPercentage = StatsPercentage(id=3005, value=0) # noqa: E501
FIGHT_PROP_NONEXTRA_ELEMENT_MASTERY: Stats = Stats(id=3006, value=0) FIGHT_PROP_NONEXTRA_ELEMENT_MASTERY: Stats = Stats(id=3006, value=0)
FIGHT_PROP_NONEXTRA_PHYSICAL_SUB_HURT: StatsPercentage = StatsPercentage(id=3007, value=0) FIGHT_PROP_NONEXTRA_PHYSICAL_SUB_HURT: StatsPercentage = StatsPercentage(id=3007, value=0) # noqa: E501
FIGHT_PROP_NONEXTRA_FIRE_ADD_HURT: StatsPercentage = StatsPercentage(id=3008, value=0) FIGHT_PROP_NONEXTRA_FIRE_ADD_HURT: StatsPercentage = StatsPercentage(id=3008, value=0) # noqa: E501
FIGHT_PROP_NONEXTRA_ELEC_ADD_HURT: StatsPercentage = StatsPercentage(id=3009, value=0) FIGHT_PROP_NONEXTRA_ELEC_ADD_HURT: StatsPercentage = StatsPercentage(id=3009, value=0) # noqa: E501
FIGHT_PROP_NONEXTRA_WATER_ADD_HURT: StatsPercentage = StatsPercentage(id=3010, value=0) FIGHT_PROP_NONEXTRA_WATER_ADD_HURT: StatsPercentage = StatsPercentage(id=3010, value=0) # noqa: E501
FIGHT_PROP_NONEXTRA_GRASS_ADD_HURT: StatsPercentage = StatsPercentage(id=3011, value=0) FIGHT_PROP_NONEXTRA_GRASS_ADD_HURT: StatsPercentage = StatsPercentage(id=3011, value=0) # noqa: E501
FIGHT_PROP_NONEXTRA_WIND_ADD_HURT: StatsPercentage = StatsPercentage(id=3012, value=0) FIGHT_PROP_NONEXTRA_WIND_ADD_HURT: StatsPercentage = StatsPercentage(id=3012, value=0) # noqa: E501
FIGHT_PROP_NONEXTRA_ROCK_ADD_HURT: StatsPercentage = StatsPercentage(id=3013, value=0) FIGHT_PROP_NONEXTRA_ROCK_ADD_HURT: StatsPercentage = StatsPercentage(id=3013, value=0) # noqa: E501
FIGHT_PROP_NONEXTRA_ICE_ADD_HURT: StatsPercentage = StatsPercentage(id=3014, value=0) FIGHT_PROP_NONEXTRA_ICE_ADD_HURT: StatsPercentage = StatsPercentage(id=3014, value=0) # noqa: E501
FIGHT_PROP_NONEXTRA_FIRE_SUB_HURT: StatsPercentage = StatsPercentage(id=3015, value=0) FIGHT_PROP_NONEXTRA_FIRE_SUB_HURT: StatsPercentage = StatsPercentage(id=3015, value=0) # noqa: E501
FIGHT_PROP_NONEXTRA_ELEC_SUB_HURT: StatsPercentage = StatsPercentage(id=3016, value=0) FIGHT_PROP_NONEXTRA_ELEC_SUB_HURT: StatsPercentage = StatsPercentage(id=3016, value=0) # noqa: E501
FIGHT_PROP_NONEXTRA_WATER_SUB_HURT: StatsPercentage = StatsPercentage(id=3017, value=0) FIGHT_PROP_NONEXTRA_WATER_SUB_HURT: StatsPercentage = StatsPercentage(id=3017, value=0) # noqa: E501
FIGHT_PROP_NONEXTRA_GRASS_SUB_HURT: StatsPercentage = StatsPercentage(id=3018, value=0) FIGHT_PROP_NONEXTRA_GRASS_SUB_HURT: StatsPercentage = StatsPercentage(id=3018, value=0) # noqa: E501
FIGHT_PROP_NONEXTRA_WIND_SUB_HURT: StatsPercentage = StatsPercentage(id=3019, value=0) FIGHT_PROP_NONEXTRA_WIND_SUB_HURT: StatsPercentage = StatsPercentage(id=3019, value=0) # noqa: E501
FIGHT_PROP_NONEXTRA_ROCK_SUB_HURT: StatsPercentage = StatsPercentage(id=3020, value=0) FIGHT_PROP_NONEXTRA_ROCK_SUB_HURT: StatsPercentage = StatsPercentage(id=3020, value=0) # noqa: E501
FIGHT_PROP_NONEXTRA_ICE_SUB_HURT: StatsPercentage = StatsPercentage(id=3021, value=0) FIGHT_PROP_NONEXTRA_ICE_SUB_HURT: StatsPercentage = StatsPercentage(id=3021, value=0) # noqa: E501
FIGHT_PROP_NONEXTRA_SKILL_CD_MINUS_RATIO: Stats = Stats(id=3022, value=0) FIGHT_PROP_NONEXTRA_SKILL_CD_MINUS_RATIO: Stats = Stats(id=3022, value=0)
FIGHT_PROP_NONEXTRA_SHIELD_COST_MINUS_RATIO: Stats = Stats(id=3023, value=0) FIGHT_PROP_NONEXTRA_SHIELD_COST_MINUS_RATIO: Stats = Stats(id=3023, value=0) # noqa: E501
FIGHT_PROP_NONEXTRA_PHYSICAL_ADD_HURT: StatsPercentage = StatsPercentage(id=3024, value=0) FIGHT_PROP_NONEXTRA_PHYSICAL_ADD_HURT: StatsPercentage = StatsPercentage(id=3024, value=0) # noqa: E501
def __init__(__pydantic_self__, **data: Any) -> None: def __init__(__pydantic_self__, **data: Any) -> None:
super().__init__(**data) super().__init__(**data)
_stats = __pydantic_self__.__dict__ _stats = __pydantic_self__.__dict__
for key in _stats: for key in _stats:
_stats[key].value = data[str(_stats[key].id)] if str(_stats[key].id) in data else 0 _stats[key].value = data[str(_stats[key].id)] if str(_stats[key].id) in data else 0 # noqa: E501

View File

@ -16,24 +16,28 @@ BASE_URL = "https://enka.network/{PATH}"
CHUNK_SIZE = 1024 * 1024 * 1 CHUNK_SIZE = 1024 * 1024 * 1
RETRY_MAX = 10 RETRY_MAX = 10
def create_path(path: str) -> str: def create_path(path: str) -> str:
return BASE_URL.format(PATH=path) return BASE_URL.format(PATH=path)
def create_ui_path(filename: str) -> str: def create_ui_path(filename: str) -> str:
return create_path(f"ui/{filename}.png") return create_path(f"ui/{filename}.png")
def validate_uid(uid: str) -> bool: def validate_uid(uid: str) -> bool:
""" """
Validate UID Validate UID
""" """
return len(uid) == 9 and uid.isdigit() and re.match(r"([1,2,5-9])\d{8}", uid) return len(uid) == 9 and uid.isdigit() and re.match(r"([1,2,5-9])\d{8}", uid) # noqa: E501
def get_default_header(): def get_default_header():
# Get python version # Get python version
python_version = sys.version_info python_version = sys.version_info
return { return {
"User-Agent": "EnkaNetwork.py/{version} (Python {major}.{minor}.{micro})".format( "User-Agent": "EnkaNetwork.py/{version} (Python {major}.{minor}.{micro})".format( # noqa: E501
version=VERSION, version=VERSION,
major=python_version.major, major=python_version.major,
minor=python_version.minor, minor=python_version.minor,
@ -41,6 +45,7 @@ def get_default_header():
), ),
} }
async def request(url: str, headers: dict = None) -> dict: async def request(url: str, headers: dict = None) -> dict:
_url = url.strip(" ") _url = url.strip(" ")
if headers is None: if headers is None:
@ -49,14 +54,14 @@ async def request(url: str, headers: dict = None) -> dict:
retry = 0 retry = 0
async with aiohttp.ClientSession() as session: async with aiohttp.ClientSession() as session:
""" """
From https://gist.github.com/foobarna/19c132304e140bf5031c273f6dc27ece From https://gist.github.com/foobarna/19c132304e140bf5031c273f6dc27ece # noqa: E501
""" """
while True: while True:
response = await session.request("GET", _url, headers={**get_default_header(), **headers}) response = await session.request("GET", _url, headers={**get_default_header(), **headers}) # noqa: E501
if response.status >= 400: if response.status >= 400:
LOGGER.warning(f"Failure to fetch {_url} ({response.status}) Retry {retry} / {RETRY_MAX}") LOGGER.warning(f"Failure to fetch {_url} ({response.status}) Retry {retry} / {RETRY_MAX}") # noqa: E501
retry += 1 retry += 1
if retry > RETRY_MAX: if retry > RETRY_MAX:
raise Exception(f"Failed to download {url}") raise Exception(f"Failed to download {url}")