🚧 build

This commit is contained in:
Karako 2023-08-29 21:30:35 +08:00
parent 2982c4425d
commit 6501b16095
No known key found for this signature in database
68 changed files with 2656 additions and 1383 deletions

41
.gitignore vendored
View File

@ -20,7 +20,6 @@ parts/
sdist/ sdist/
var/ var/
wheels/ wheels/
pip-wheel-metadata/
share/python-wheels/ share/python-wheels/
*.egg-info/ *.egg-info/
.installed.cfg .installed.cfg
@ -50,6 +49,7 @@ coverage.xml
*.py,cover *.py,cover
.hypothesis/ .hypothesis/
.pytest_cache/ .pytest_cache/
cover/
# Translations # Translations
*.mo *.mo
@ -72,6 +72,7 @@ instance/
docs/_build/ docs/_build/
# PyBuilder # PyBuilder
.pybuilder/
target/ target/
# Jupyter Notebook # Jupyter Notebook
@ -82,7 +83,9 @@ profile_default/
ipython_config.py ipython_config.py
# pyenv # pyenv
.python-version # For a library or package, you might want to ignore these files since the code is
# intended to run in multiple environments; otherwise, check them in:
# .python-version
# pipenv # pipenv
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
@ -91,7 +94,24 @@ ipython_config.py
# install all needed dependencies. # install all needed dependencies.
#Pipfile.lock #Pipfile.lock
# PEP 582; used by e.g. github.com/David-OConnor/pyflow # poetry
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
# This is especially recommended for binary packages to ensure reproducibility, and is more
# commonly ignored for libraries.
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
#poetry.lock
# pdm
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
#pdm.lock
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
# in version control.
# https://pdm.fming.dev/#use-with-ide
.pdm.toml
.pdm-python
.pdm-build/
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
__pypackages__/ __pypackages__/
# Celery stuff # Celery stuff
@ -125,5 +145,18 @@ venv.bak/
.dmypy.json .dmypy.json
dmypy.json dmypy.json
# Pyre item_type checker # Pyre type checker
.pyre/ .pyre/
# pytype static type analyzer
.pytype/
# Cython debug symbols
cython_debug/
# PyCharm
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
# and can be added to the global gitignore or merged into this file. For a more nuclear
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
#.idea/

View File

@ -1,2 +1 @@
# GenshinWikiDataParser # genshin-wiki-py
原神 wiki 数据解析库

78
old/script/item.py Normal file
View File

@ -0,0 +1,78 @@
import regex as re
from ormar import QuerySet
from genshin_wiki.config import with_genshin_wiki_config
from genshin_wiki.item import Item, ItemDescription
from genshin_wiki.manager import resource_manager
from genshin_wiki.tools.typedefs import Lang
item_query_set: QuerySet[Item] = Item.objects
item_description_query_set: QuerySet[ItemDescription] = ItemDescription.objects
async def parse_item_data(lang: Lang = "chs"):
with with_genshin_wiki_config(lang=lang):
item_data_list: list[dict] = resource_manager.fetch_metadata(
"MaterialExcelConfigData"
)
item_codex_data_list: list[dict] = resource_manager.fetch_metadata(
"MaterialCodexExcelConfigData"
)
item_source_data_list: list[dict] = resource_manager.fetch_metadata(
"MaterialSourceDataExcelConfigData"
)
for item_data in item_data_list:
id = item_data["id"]
name = item_data["nameTextMapHash"]
if (true_name := resource_manager.get_text(name)) is None or re.findall(
r"^[(].*?[)]", true_name
): # 跳过无名称和测试物品
continue
type = item_data["typeDescTextMapHash"]
icon = item_data["icon"]
rarity = item_data.get("rankLevel", 5) % 100
main_description = item_data["descTextMapHash"]
code_description = next(
filter(lambda x: x["materialId"] == id, item_codex_data_list),
{"descTextMapHash": None},
)["descTextMapHash"]
special_description = item_data["specialDescTextMapHash"]
description, _ = await item_description_query_set.get_or_create(
id=id,
main=main_description,
codex=code_description,
special=special_description,
)
source_item = next(
filter(lambda x: x["id"] == id, item_source_data_list),
{"jumpList": [], "textList": []},
)
source = list(
set(
filter(
lambda x: resource_manager.get_text(x) is not None,
source_item["jumpList"] + source_item["textList"],
)
)
) or None
item, _ = await item_query_set.get_or_create(
id=id,
name=name,
type=type,
rarity=rarity,
_source=source,
description=description,
)
if source:
print()
print(source)
print(item._source)
breakpoint()
breakpoint()

165
old/scripts/avatar.py Normal file
View File

@ -0,0 +1,165 @@
from functools import lru_cache
from itertools import chain
from logging import getLogger
from ormar import QuerySet
from models.avatar import (
Avatar,
AvatarIcon,
AvatarBirthday,
AvatarSeuyu,
AvatarStory,
AvatarStories,
)
from models.enums import Association, AvatarQuality, Element, WeaponType
from utils.manager import ResourceManager
from utils.typedefs import Lang
logger = getLogger(__name__)
avatar_query_set: QuerySet[Avatar] = Avatar.objects
avatar_icon_query_set: QuerySet[AvatarIcon] = AvatarIcon.objects
avatar_birthday_query_set: QuerySet[AvatarBirthday] = AvatarBirthday.objects
avatar_seuyu_query_set: QuerySet[AvatarSeuyu] = AvatarSeuyu.objects
avatar_story_query_set: QuerySet[AvatarStory] = AvatarStory.objects
avatar_stories_query_set: QuerySet[AvatarStories] = AvatarStories.objects
@lru_cache
def get_element_data() -> dict[Element, set[int]]:
_manager = ResourceManager("chs")
_avatar_json_data = _manager.fetch("AvatarExcelConfigData")
_fetter_info_json_data = _manager.fetch("FetterInfoExcelConfigData")
text_map = {
"": Element.Pyro,
"": Element.Hydro,
"": Element.Anemo,
"": Element.Electro,
"": Element.Dendro,
"": Element.Cryo,
"": Element.Geo,
"": Element.Null,
}
result = {k: set() for k in text_map.values()}
for data in _avatar_json_data:
_id = data["id"]
if (
info_data := next(
chain(
filter(lambda x: x["avatarId"] == _id, _fetter_info_json_data),
[None],
)
)
) is None:
continue
if (
vision := _manager.get_text(
text_id := info_data["avatarVisionBeforTextMapHash"]
)
) is not None:
result[text_map[vision]] = set(list(result[text_map[vision]]) + [text_id])
return result
# noinspection PyUnusedLocal,PyShadowingBuiltins
async def parse_avatar_data(lang: Lang):
manager = ResourceManager(lang)
avatar_data_list: list[dict] = manager.fetch("AvatarExcelConfigData")
fetter_info_data_list = manager.fetch("FetterInfoExcelConfigData")
story_data_list = manager.fetch("FetterStoryExcelConfigData")
promote_data_list = manager.fetch("AvatarPromoteExcelConfigData")
avatar_hero_data_list = manager.fetch("AvatarHeroEntityExcelConfigData")
skill_depot_data_list = manager.fetch("AvatarSkillDepotExcelConfigData")
skill_data_list = manager.fetch("AvatarSkillExcelConfigData")
proud_skill_data_list = manager.fetch("ProudSkillExcelConfigData")
talent_data_list = manager.fetch("AvatarTalentExcelConfigData")
cook_bonus_data_list = manager.fetch("CookBonusExcelConfigData")
for data in avatar_data_list:
id = data["id"]
info_data = next(
chain(filter(lambda x: x["avatarId"] == id, fetter_info_data_list), [None])
)
if info_data is None:
continue
name = manager.get_text(data["nameTextMapHash"])
icon, _ = await avatar_icon_query_set.get_or_create(
icon_name=data["iconName"], side_icon_name=data["sideIconName"]
)
element = next(
filter(
lambda x: info_data["avatarVisionBeforTextMapHash"] in x[1],
get_element_data().items(),
)
)[0]
quality = AvatarQuality(
data["qualityType"].removeprefix("QUALITY_").replace("ORANGE_SP", "SPECIAL")
)
weapon_type = next(
filter(
lambda x: x in data["weaponType"].replace("POLE", "POLEARM"),
WeaponType.__members__.values(),
)
)
###########################################
############### 角色信息 #################
###########################################
title = manager.get_text(info_data["avatarTitleTextMapHash"])
birth, _ = (
(
await avatar_birthday_query_set.get_or_create(
month=info_data["infoBirthMonth"], day=info_data["infoBirthDay"]
)
)
if id not in list(map(lambda x: x["avatarId"], avatar_hero_data_list))
else (None, False)
)
occupation = manager.get_text(info_data["avatarNativeTextMapHash"])
vision = manager.get_text(info_data["avatarVisionBeforTextMapHash"])
constellation = manager.get_text(
info_data["avatarConstellationBeforTextMapHash"]
)
description = manager.get_text(info_data["avatarDetailTextMapHash"])
association = Association(
info_data["avatarAssocType"].removeprefix("ASSOC_TYPE_")
)
seuyu, _ = await avatar_seuyu_query_set.get_or_create(
chinese=manager.get_text(info_data["cvChineseTextMapHash"]),
japanese=manager.get_text(info_data["cvJapaneseTextMapHash"]),
english=manager.get_text(info_data["cvEnglishTextMapHash"]),
korean=manager.get_text(info_data["cvKoreanTextMapHash"]),
)
story_list: list[AvatarStory] = []
story_datas = sorted(
filter(lambda x: x["avatarId"] == id, story_data_list),
key=lambda x: x["fetterId"],
)
for story_data in story_datas:
tips = list(
filter(
lambda x: x is not None,
map(lambda x: manager.get_text(x), story_data["tips"]),
)
)
story, _ = await avatar_story_query_set.get_or_create(
title=manager.get_text(story_data["storyTitleTextMapHash"]),
content=manager.get_text(story_data["storyContextTextMapHash"]),
tips=tips,
)
story_list.append(story)
avatar_stories, _ = await avatar_stories_query_set.get_or_create(
**{
i[0]: i[1]
for i in zip(
filter(lambda x: x != "id", AvatarStories.__fields__), story_list
)
}
)
breakpoint()

84
old/scripts/item.py Normal file
View File

@ -0,0 +1,84 @@
from ormar import QuerySet
from models.enums import FoodQuality
from utils.manager import ResourceManager
from utils.typedefs import Lang
from models.item import OldItem
import regex as re
try:
from loguru import logger
except ImportError:
from logging import getLogger
logger = getLogger(__name__)
# noinspection PyShadowingBuiltins
async def parse_item_data(lang: Lang):
manager = ResourceManager(lang)
item_data_list: list[dict] = manager.fetch("MaterialExcelConfigData")
item_query_set: QuerySet[OldItem] = OldItem.objects
for item_data in item_data_list:
id = item_data["id"]
name = manager(item_data["nameTextMapHash"])
if name is None or re.findall(r"^[(].*?[)]", name): # 跳过无名称和测试物品
continue
type = manager.get_text(item_data["typeDescTextMapHash"])
icon = item_data["icon"]
rarity = item_data.get("rankLevel", 5) % 100
description = manager.get_text(item_data["descTextMapHash"])
special_description = manager.get_text(item_data["specialDescTextMapHash"])
is_virtual = item_data["itemType"] == "ITEM_VIRTUAL"
kwargs = {}
if (
"foodQuality" in item_data
or item_data.get("materialType", None) == "MATERIAL_FOOD"
):
if "foodQuality" in item_data:
kwargs["quality"] = FoodQuality(
item_data["foodQuality"].removeprefix("FOOD_QUALITY_").title()
)
kwargs["effect"] = manager.get_text(item_data["effectDescTextMapHash"])
kwargs["effect_icon"] = item_data["effectIcon"]
kwargs["cd_time"] = item_data.get("cdTime", None)
kwargs["cd_group"] = item_data.get("cdGroup", None)
if "picPath" in item_data and item_data["picPath"]:
kwargs["pictures"] = item_data["picPath"]
if "materialType" in item_data:
kwargs["material_type"] = item_data["materialType"].removeprefix(
"MATERIAL_"
)
kwargs["material_type_description"] = manager.get_text(
item_data["typeDescTextMapHash"]
)
kwargs["close_bag_after_used"] = item_data.get("closeBagAfterUsed", None)
kwargs["interaction_title"] = manager.get_text(
item_data["interactionTitleTextMapHash"]
)
kwargs["interaction_description"] = manager.get_text(
item_data.get("interactionDescTextMapHash", None)
)
kwargs["is_force_get_hint"] = item_data.get("isForceGetHint", None)
kwargs["no_first_get_hint"] = item_data.get("noFirstGetHint", None)
kwargs["use_on_gain"] = item_data.get("useOnGain", None)
kwargs["use_target"] = item_data.get("useTarget", None)
item, _ = await item_query_set.get_or_create(
id=id,
name=name,
type=type,
icon=icon,
rarity=rarity,
description=description,
special_description=special_description,
is_virtual=is_virtual,
**{k: v for k, v in kwargs.items() if v is not None},
)
logger.info(f"Item: {item.name} {item.type} {item.material_type}")
breakpoint()

View File

@ -0,0 +1,38 @@
from pathlib import Path
from pydantic import BaseModel
from genshin_wiki.tools.const import DATA_DIR
from genshin_wiki.tools.typedefs import Lang
from contextlib import contextmanager
__all__ = (
"genshin_wiki_config",
"with_genshin_wiki_config",
)
class _GenshinWikiConfig(BaseModel):
lang: Lang = "chs"
database_path: Path = DATA_DIR.joinpath('database.sqlite')
request_timeout: int = 10
request_retry_times: int = 5
metadata_link: str = "https://gitlab.com/Dimbreath/AnimeGameData/-/raw/master/"
genshin_wiki_config = _GenshinWikiConfig()
@contextmanager
def with_genshin_wiki_config(**kwargs):
global genshin_wiki_config
old_config = genshin_wiki_config
config_dict = genshin_wiki_config.dict()
config_dict.update(kwargs)
genshin_wiki_config = _GenshinWikiConfig(**config_dict)
yield
genshin_wiki_config = old_config

View File

@ -0,0 +1,126 @@
from enum import StrEnum
class AvatarQuality(StrEnum):
Orange = "ORANGE"
"""五星"""
Purple = "PURPLE"
"""四星"""
Special = "SPECIAL"
"""特殊"""
class ItemType(StrEnum):
Virtual = "VIRTUAL"
Material = "MATERIAL"
class WeaponType(StrEnum):
Sword = "SWORD"
"""单手剑"""
Claymore = "CLAYMORE"
"""双手剑"""
Bow = "BOW"
""""""
Catalyst = "CATALYST"
"""法器"""
Polearm = "POLEARM"
"""长柄武器"""
class Element(StrEnum):
Pyro = "PYRO"
""""""
Hydro = "HYDRO"
""""""
Anemo = "ANEMO"
""""""
Electro = "ELECTRO"
""""""
Dendro = "DENDRO"
""""""
Cryo = "CRYO"
""""""
Geo = "GEO"
""""""
Null = "NULL"
""""""
class PropType(StrEnum):
HealthPoints = "HP"
"""生命值"""
HealthPointsPercent = "HPPercent"
"""生命值百分比"""
Defense = "Defense"
"""防御力"""
DefensePercent = "DefensePercent"
"""防御力百分比"""
Attack = "Attack"
"""攻击力"""
AttackPercent = "AttackPercent"
"""攻击力百分比"""
CriticalRate = "Critical"
"""暴击率"""
CriticalHurtRate = "CriticalHurt"
"""暴击伤害"""
HealAdd = "HealAdd"
"""治疗加成"""
ElementMastery = "ElementMastery"
"""元素精通"""
ChargeEfficiency = "ChargeEfficiency"
"""元素充能效率"""
PhysicalAddHurt = "Physical"
"""物理伤害加成"""
PyroAddHurt = "Pyro"
"""火元素伤害加成"""
HydroAddHurt = "Hydro"
"""水元素伤害加成"""
AnemoAddHurt = "Anemo"
"""风元素伤害加成"""
ElectroAddHurt = "Electro"
"""雷元素伤害加成"""
DendroAddHurt = "Dendro"
"""草元素伤害加成"""
CryoAddHurt = "Cryo"
"""冰元素伤害加成"""
GeoAddHurt = "Geo"
"""岩元素伤害加成"""
class FoodQuality(StrEnum):
STRANGE = "Strange"
"""奇怪的"""
ORDINARY = "Ordinary"
"""普通的"""
DELICIOUS = "Delicious"
"""美味的"""
class Association(StrEnum):
Inazuma = "INAZUMA"
"""稻妻"""
Mondstadt = "MONDSTADT"
"""蒙德"""
Liyue = "LIYUE"
"""璃月"""
Sumeru = "SUMERU"
"""须弥"""
Fontaine = "FONTAINE"
"""枫丹"""
Natlan = "NATLAN"
"""纳塔"""
Snezhnaya = "SNEZHNAYA"
"""至冬"""
Mainactor = "MAINACTOR"
"""主角"""
Fatui = "FATUI"
"""愚人众"""
Ranger = "RANGER"
"""游侠"""

View File

@ -0,0 +1 @@
from genshin_wiki.item._item import Item, ItemDescription

View File

@ -0,0 +1,52 @@
from ormar import Integer, JSON, UniqueColumns, property_field
from pydantic import Json, PrivateAttr
from genshin_wiki._model import ForeignKey, MapString, MapText, Model, ModelMeta
from genshin_wiki.manager import resource_manager
class ItemDescription(Model):
class Meta(ModelMeta):
tablename = "item_description"
constraints = [UniqueColumns("main", "codex", "special")]
id: int = Integer(primary_key=True)
"""ID"""
main: str | None = MapText(nullable=True)
"""描述"""
codex: str | None = MapText(nullable=True)
"""图鉴描述"""
special: str | None = MapText(nullable=True)
"""特殊描述"""
class Item(Model):
class Meta(ModelMeta):
tablename = "item"
constraints = [UniqueColumns("name", "type")]
id: int = Integer(primary_key=True)
"""ID"""
name: str = MapString()
"""名称"""
type: str = MapString()
"""类型"""
rarity: int | None = Integer(minimum=0, maximum=5, default=None, nullable=True)
"""稀有度"""
_source: Json[list] | None = PrivateAttr(JSON(nullable=True, name="source", default=None))
"""来源"""
description: ItemDescription = ForeignKey(ItemDescription)
"""描述"""
@property_field
def source(self) -> Json[list[str]] | None:
if self._source is None:
return self._source
return list(
filter(
lambda x: x, map(lambda x: resource_manager.get_text(x), self._source)
)
)
ModelMeta.metadata.create_all()

View File

@ -0,0 +1,45 @@
from ormar import Integer, property_field
from genshin_wiki._model import Model, ModelMeta, String, Enum, ForeignKey
from genshin_wiki.enums import FoodQuality
from genshin_wiki.item._item import Item
class Food(Model):
class Meta(ModelMeta):
tablename = "food"
id: int = Integer(primary_key=True)
"""ID"""
_item: Item = ForeignKey(Item, name="item", nullable=False)
"""相关物品"""
@property_field
def name(self) -> str:
return self._item.name
@property_field
def type(self) -> str:
return self._item.type
@property_field
def rarity(self) -> int:
return self._item.rarity or 0
effect: str | None = String(nullable=True)
"""效果"""
@property_field
def source(self) -> list[str]:
return self._item._source or []
@property_field
def description(self) -> str | None:
return self._item.description
@property_field
def description_codex(self) -> str | None:
return self._item.description_codex
ModelMeta.metadata.create_all()

View File

@ -0,0 +1,84 @@
import os
from functools import lru_cache
from logging import getLogger
from pathlib import Path
import httpx
import ujson as json
from httpx import Client
from yarl import URL
from genshin_wiki.config import genshin_wiki_config
from genshin_wiki.tools.const import DATA_DIR
from genshin_wiki.tools.typedefs import Lang
__all__ = ("resource_manager",)
logger = getLogger(__name__)
class _ResourceManager:
_client: Client
_text_maps: dict[Lang, dict[str, str]] = {}
@property
def client(self) -> Client:
if not hasattr(self, "_client"):
self._client = Client(timeout=genshin_wiki_config.request_timeout)
return self._client
@lru_cache()
def fetch_metadata(
self,
name: str,
path: str = "ExcelBinOutput",
*,
output_dir: str | Path = DATA_DIR,
) -> dict:
logger.debug(f"Resource Manager is fetching metadata: {name} of {path}, to {output_dir}")
file_path = (
Path(output_dir)
.resolve()
.joinpath(name)
.with_suffix("")
.with_suffix(".json")
)
file_path.parent.mkdir(exist_ok=True, parents=True)
if not (file_path.exists() and os.stat(file_path)):
times = 0
while True:
try:
response = self.client.get(
str(URL(genshin_wiki_config.metadata_link) / path / file_path.name)
)
break
except httpx.RequestError as e:
if times < genshin_wiki_config.request_retry_times:
times += 1
continue
raise e
# noinspection PyUnboundLocalVariable,PyUnresolvedReferences
response.raise_for_status()
with open(file_path, encoding="utf-8", mode="w") as file:
file.write(content := response.text)
return json.loads(content)
with open(file_path, encoding="utf-8", mode="r") as file:
return json.loads(file.read())
@lru_cache(typed=True)
def get_text(self, key: int | str | None) -> str | None:
if key is None:
return None
_lang = genshin_wiki_config.lang
if self._text_maps.get(_lang) is None:
self._text_maps[_lang] = self.fetch_metadata("TextMap" + _lang.upper(), "TextMap")
result = self._text_maps[_lang].get(str(key), None)
if result is not None:
return result.replace("\\n", "\n")
return result
resource_manager = _ResourceManager()

View File

102
old/src/models/_base.py Normal file
View File

@ -0,0 +1,102 @@
import os
from datetime import datetime
# noinspection PyPep8Naming
from enum import Enum as E
from pathlib import Path
from typing import Any, Type
# noinspection PyPep8Naming
from ormar import (
BaseField,
Enum as ENUM,
String as STRING,
)
try:
import regex as re
except ImportError:
import re
import databases
import ormar
import sqlalchemy
import ujson as json
from pydantic import BaseConfig
from tools.const import OUTPUT_DIR
__all__ = (
"database_url",
"engine",
"databases",
"metadata",
"Model",
"ModelMeta",
"Enum",
"String",
)
database_url = (
"sqlite:///"
f"{OUTPUT_DIR.joinpath(os.environ.get('LANG', 'chs')).joinpath('database.sqlite').resolve()}"
).replace("\\", "/")
engine = sqlalchemy.create_engine(
database_url, json_serializer=json.dumps, json_deserializer=json.loads
)
database = databases.Database(database_url)
metadata = sqlalchemy.MetaData(engine)
class ModelMeta(ormar.ModelMeta):
database = database
metadata = metadata
class ModelConfig(BaseConfig):
json_encoders = {datetime: lambda v: v.timestamp()}
json_loads = json.loads
json_dumps = json.dumps
class Model(ormar.Model):
class Config(ModelConfig):
pass
class Meta(ModelMeta):
abstract = True
class String(STRING):
def __new__(
cls,
*,
max_length: int = 255,
min_length: int = None,
regex: str = None,
**kwargs: Any,
) -> BaseField:
return super().__new__(
cls=STRING,
max_length=max_length,
min_length=min_length,
regex=regex,
**kwargs,
)
class Enum(ENUM):
def __new__(cls, enum_class: Type[E], **kwargs: Any) -> BaseField:
return super().__new__(
cls,
**{
**kwargs,
**{
k: v
for k, v in locals().items()
if k not in ["cls", "__class__", "kwargs"]
},
},
)

View File

@ -0,0 +1 @@
from models.avatar._avatar import *

View File

@ -0,0 +1,212 @@
from ormar import Float, ForeignKey, Integer, JSON, ManyToMany, Text
from pydantic import Json
from models._base import Enum, Model, ModelMeta, String
from models.avatar.talente import AvatarTalents
from models.enums import Association, AvatarQuality, Element, PropType, WeaponType
from models.item import OldItem
from models.other import ItemCount
class AvatarIcon(Model):
"""角色图标"""
class Meta(ModelMeta):
tablename = "avatar_icon"
id: int = Integer(primary_key=True)
"""ID"""
icon_name: str = String()
"""图标名"""
side_icon_name: str = String()
"""侧视图图标名"""
class AvatarBirthday(Model):
"""角色生日"""
class Meta(ModelMeta):
tablename = "avatar_birthday"
id: int = Integer(primary_key=True)
month: int = Integer(minimum=1, maximum=12)
day: int = Integer(minimum=1, maximum=31)
class AvatarSeuyu(Model):
"""角色声优"""
class Meta(ModelMeta):
tablename = "avatar_seuyu"
id: int = Integer(primary_key=True)
chinese: str = String()
japanese: str = String()
english: str = String()
korean: str = String()
class AvatarStory(Model):
"""角色故事(单个)"""
class Meta(ModelMeta):
tablename = "avatar_story"
id: int = Integer(primary_key=True)
title: str = String()
content: str = Text()
tips: Json[list[str]] = JSON()
class AvatarStories(Model):
"""角色故事"""
class Meta(ModelMeta):
tablename = "avatar_story_list"
id: int = Integer(primary_key=True)
details: AvatarStory = ForeignKey(AvatarStory, skip_reverse=True, related_name='avatar_stories_details')
story_1: AvatarStory = ForeignKey(AvatarStory, skip_reverse=True, related_name='avatar_stories_story_1')
story_2: AvatarStory = ForeignKey(AvatarStory, skip_reverse=True, related_name='avatar_stories_story_2')
story_3: AvatarStory = ForeignKey(AvatarStory, skip_reverse=True, related_name='avatar_stories_story_3')
story_4: AvatarStory = ForeignKey(AvatarStory, skip_reverse=True, related_name='avatar_stories_story_4')
story_5: AvatarStory = ForeignKey(AvatarStory, skip_reverse=True, related_name='avatar_stories_story_5')
miscellaneous: AvatarStory | None = ForeignKey(
AvatarStory, nullable=True, skip_reverse=True, default=None, related_name='avatar_stories_miscellaneous'
)
vision: AvatarStory | None = ForeignKey(
AvatarStory, nullable=True, skip_reverse=True, default=None, related_name='avatar_stories_vision'
)
class AvatarInfo(Model):
class Meta(ModelMeta):
tablename = "avatar_info"
id: int = Integer(primary_key=True)
title: str | None = String(nullable=True)
"""称号"""
birthday: AvatarBirthday | None = ForeignKey(AvatarBirthday, skip_reverse=True)
"""称号"""
occupation: str = String()
"""所属"""
vision: str = String()
"""神之眼"""
special_food: OldItem | None = ForeignKey(OldItem, skip_reverse=True, nullable=True)
"""特殊料理"""
constellation: str = String()
"""星座"""
description: str = Text()
"""描述"""
association: Association = Enum(Association)
"""联系"""
seuyu: AvatarSeuyu = ForeignKey(AvatarSeuyu, skip_reverse=True)
"""声优"""
stories: AvatarStories = ForeignKey(AvatarStories, skip_reverse=True)
"""故事"""
class AvatarAttribute(Model):
"""角色属性"""
class Meta(ModelMeta):
tablename = "avatar_attribute"
id: int = Integer(primary_key=True)
HealthPoints: float = Float()
"""生命值"""
Attack: float = Float()
"""攻击力"""
Defense: float = Float()
"""防御力"""
CriticalRate: float = Float()
"""暴击率"""
CriticalHurtRate: float = Float()
"""暴击伤害"""
ChargeEfficiency: float = Float()
"""元素充能效率"""
class AddProp(Model):
"""属性加成"""
class Meta(ModelMeta):
tablename = "avatar_add_prop"
id: int = Integer(primary_key=True)
type: PropType = Enum(PropType)
"""属性类型"""
value: float = Float()
"""属性值"""
class AvatarPromote(Model):
"""角色突破数据"""
class Meta(ModelMeta):
tablename = "avatar_promote"
id: int = Integer(primary_key=True)
promote_level: int = Integer(default=0)
"""突破等级"""
max_level: int = Integer()
"""解锁的等级上限"""
add_props: list[AddProp] | None = ManyToMany(AddProp)
"""属性加成"""
coin: int = Integer(default=0)
"""消耗摩拉"""
cost_item: list[ItemCount] | None = ManyToMany(ItemCount)
"""突破所需材料"""
class AvatarConstellation(Model):
"""角色命座信息"""
class Meta(ModelMeta):
tablename = "avatar_constellation"
id: int = Integer(primary_key=True)
name: str = String()
"""命座名"""
description: str = Text()
"""描述"""
icon: str = String()
"""命座图标"""
param_list: Json[list[float]] = JSON()
"""命座数据参数列表"""
class Avatar(Model):
"""角色"""
class Meta(ModelMeta):
tablename = "avatar"
id: int = Integer(primary_key=True)
"""ID"""
name: str = String()
"""名称"""
icon: AvatarIcon = ForeignKey(AvatarIcon, skip_reverse=True)
"""图标"""
element: Element = Enum(Element)
"""元素"""
quality: AvatarQuality = Enum(AvatarQuality)
"""品质"""
weapon_type: WeaponType = Enum(WeaponType)
"""武器类型"""
information: AvatarInfo = ForeignKey(AvatarInfo, skip_reverse=True)
"""角色信息"""
attributes: AvatarAttribute = ForeignKey(AvatarAttribute)
"""角色基础属性"""
talents: AvatarTalents = ForeignKey(AvatarTalents, skip_reverse=True)
"""角色天赋信息"""
promotes: list[AvatarPromote] = ManyToMany(AvatarPromote)
"""角色突破数据"""
constellations: list[AvatarConstellation] = ManyToMany(AvatarConstellation)
"""角色命座信息"""
ModelMeta.metadata.create_all()

View File

@ -0,0 +1,195 @@
from ormar import Float, ForeignKey, Integer, JSON, ManyToMany, String, Text
from pydantic import Json
from models._base import Model, ModelMeta
from models.other import ItemCount
__all__ = (
"Talent",
"NormalAttack",
"ElementalBurst",
"ElementalSkill",
"AlternateSprint",
"PassiveTalent",
"AscensionPassive",
"FirstAscensionPassive",
"FourthAscensionPassive",
"UtilityPassive",
"MiscellaneousPassive",
"AvatarTalents",
"TalentAttribute",
)
class Talent(Model):
class Meta(ModelMeta):
abstract = True
id: int = Integer(primary_key=True)
"""ID"""
name: str = String(max_length=255)
"""天赋名称"""
description: str = Text()
"""天赋描述"""
icon: str = String(max_length=255)
"""天赋图标名"""
promote_level: int = Integer(default=0)
"""解锁等级"""
class TalentAttribute(Model):
class Meta(ModelMeta):
tablename = "avatar_talent_attribute"
id: int = Integer(primary_key=True)
"""ID"""
level: int = Integer(default=1)
"""等级"""
params: Json[list[float]] = JSON(default=[])
"""参数数值"""
break_level: int = Integer(default=0)
"""突破所需等级"""
coin: int = Integer(default=0)
"""摩拉"""
cost_items: list[ItemCount] = ManyToMany(ItemCount)
"""消耗物品"""
class CombatTalent(Model):
"""战斗天赋"""
class Meta:
abstract = True
id: int = Integer(primary_key=True)
cooldown: float = Float()
"""冷却时间"""
param_descriptions: Json[list[str]] = JSON(default=[])
"""参数描述"""
class NormalAttack(CombatTalent):
"""普通攻击"""
class Meta(ModelMeta):
tablename = "avatar_talent_normal_attack"
attributes: list[TalentAttribute] = ManyToMany(TalentAttribute)
"""数值参数"""
class ElementalSkill(CombatTalent):
"""元素战技"""
class Meta(ModelMeta):
tablename = "avatar_talent_elemental_skill"
attributes: list[TalentAttribute] = ManyToMany(TalentAttribute)
"""数值参数"""
class ElementalBurst(CombatTalent):
"""元素爆发"""
class Meta(ModelMeta):
tablename = "avatar_talent_elemental_burst"
attributes: list[TalentAttribute] = ManyToMany(TalentAttribute)
"""数值参数"""
class AlternateSprint(CombatTalent):
"""冲刺技能"""
class Meta(ModelMeta):
tablename = "avatar_talent_alternate_sprint"
attributes: list[TalentAttribute] = ManyToMany(TalentAttribute)
"""数值参数"""
class PassiveTalent(Talent):
"""固有天赋"""
class Meta(ModelMeta):
abstract = True
attribute: TalentAttribute = ForeignKey(TalentAttribute)
"""数值参数"""
class AscensionPassive(PassiveTalent):
"""突破固有天赋"""
class Meta(ModelMeta):
abstract = True
ascension: int
"""突破次数"""
class FirstAscensionPassive(AscensionPassive):
"""第一次突破固有天赋"""
class Meta(ModelMeta):
tablename = "avatar_talent_first_ascension_passive"
ascension = 1
class FourthAscensionPassive(AscensionPassive):
"""第四次突破固有天赋"""
class Meta(ModelMeta):
tablename = "avatar_talent_fourth_ascension_passive"
ascension = 4
class UtilityPassive(PassiveTalent):
"""实用固有天赋"""
class Meta(ModelMeta):
tablename = "avatar_talent_utility_passive"
class MiscellaneousPassive(PassiveTalent):
"""杂项固有天赋"""
class Meta(ModelMeta):
tablename = "avatar_talent_miscellaneous_passive"
class AvatarTalents(Model):
"""角色天赋"""
class Meta(ModelMeta):
tablename = "avatar_talents"
id: int = Integer(primary_key=True)
normal_attack: NormalAttack = ForeignKey(NormalAttack)
"""普通攻击"""
elemental_skill: ElementalSkill | None = ForeignKey(ElementalSkill, nullable=True)
"""元素战技"""
elemental_burst: ElementalBurst | None = ForeignKey(ElementalBurst, nullable=True)
"""元素爆发"""
alternate_sprint: AlternateSprint | None = ForeignKey(
AlternateSprint, nullable=True
)
"""冲刺技能"""
first_ascension_passive: FirstAscensionPassive | None = ForeignKey(
FirstAscensionPassive, nullable=True
)
"""第一次突破固有天赋"""
fourth_ascension_passive: FourthAscensionPassive | None = ForeignKey(
FourthAscensionPassive, nullable=True
)
"""第四次突破固有天赋"""
utility_passive: UtilityPassive | None = ForeignKey(UtilityPassive, nullable=True)
"""实用固有天赋"""
miscellaneous_passive: MiscellaneousPassive | None = ForeignKey(
MiscellaneousPassive, nullable=True
)
"""杂项固有天赋"""
ModelMeta.metadata.create_all()

126
old/src/models/enums.py Normal file
View File

@ -0,0 +1,126 @@
from enum import StrEnum
class AvatarQuality(StrEnum):
Orange = "ORANGE"
"""五星"""
Purple = "PURPLE"
"""四星"""
Special = "SPECIAL"
"""特殊"""
class ItemType(StrEnum):
Virtual = "VIRTUAL"
Material = "MATERIAL"
class WeaponType(StrEnum):
Sword = "SWORD"
"""单手剑"""
Claymore = "CLAYMORE"
"""双手剑"""
Bow = "BOW"
""""""
Catalyst = "CATALYST"
"""法器"""
Polearm = "POLEARM"
"""长柄武器"""
class Element(StrEnum):
Pyro = "PYRO"
""""""
Hydro = "HYDRO"
""""""
Anemo = "ANEMO"
""""""
Electro = "ELECTRO"
""""""
Dendro = "DENDRO"
""""""
Cryo = "CRYO"
""""""
Geo = "GEO"
""""""
Null = "NULL"
""""""
class PropType(StrEnum):
HealthPoints = "HP"
"""生命值"""
HealthPointsPercent = "HPPercent"
"""生命值百分比"""
Defense = "Defense"
"""防御力"""
DefensePercent = "DefensePercent"
"""防御力百分比"""
Attack = "Attack"
"""攻击力"""
AttackPercent = "AttackPercent"
"""攻击力百分比"""
CriticalRate = "Critical"
"""暴击率"""
CriticalHurtRate = "CriticalHurt"
"""暴击伤害"""
HealAdd = "HealAdd"
"""治疗加成"""
ElementMastery = "ElementMastery"
"""元素精通"""
ChargeEfficiency = "ChargeEfficiency"
"""元素充能效率"""
PhysicalAddHurt = "Physical"
"""物理伤害加成"""
PyroAddHurt = "Pyro"
"""火元素伤害加成"""
HydroAddHurt = "Hydro"
"""水元素伤害加成"""
AnemoAddHurt = "Anemo"
"""风元素伤害加成"""
ElectroAddHurt = "Electro"
"""雷元素伤害加成"""
DendroAddHurt = "Dendro"
"""草元素伤害加成"""
CryoAddHurt = "Cryo"
"""冰元素伤害加成"""
GeoAddHurt = "Geo"
"""岩元素伤害加成"""
class FoodQuality(StrEnum):
STRANGE = "Strange"
"""奇怪的"""
ORDINARY = "Ordinary"
"""普通的"""
DELICIOUS = "Delicious"
"""美味的"""
class Association(StrEnum):
Inazuma = "INAZUMA"
"""稻妻"""
Mondstadt = "MONDSTADT"
"""蒙德"""
Liyue = "LIYUE"
"""璃月"""
Sumeru = "SUMERU"
"""须弥"""
Fontaine = "FONTAINE"
"""枫丹"""
Natlan = "NATLAN"
"""纳塔"""
Snezhnaya = "SNEZHNAYA"
"""至冬"""
Mainactor = "MAINACTOR"
"""主角"""
Fatui = "FATUI"
"""愚人众"""
Ranger = "RANGER"
"""游侠"""

0
old/src/models/item.py Normal file
View File

View File

@ -0,0 +1 @@
from models.item._item import OldItem

View File

@ -0,0 +1,86 @@
from ormar import Boolean, Integer, JSON, Text, ForeignKey
from pydantic import Json
from models._base import Enum, Model, ModelMeta, String
from models.enums import FoodQuality
class Item(Model):
class Meta(ModelMeta):
tablename = 'item_simple'
id: int = Integer(primary_key=True)
"""ID"""
name: str = String()
"""名称"""
type: str = String()
"""类型"""
rarity: int | None = Integer(minimum=0, maximum=5, default=None, nullable=True)
"""稀有度"""
description: str | None = Text()
"""描述"""
description_codex: str | None = Text(nullable=True)
"""图鉴描述"""
class OldItem(Model):
class Meta(ModelMeta):
tablename = "item"
id: int = Integer(primary_key=True)
"""ID"""
name: str = String()
"""名称"""
type: str | None = String(nullable=True)
"""类型"""
icon: str = String()
"""图标名"""
rarity: int | None = Integer(minimum=0, maximum=5, default=None, nullable=True)
"""稀有度"""
description: str | None = Text(nullable=True)
"""描述"""
special_description: str | None = Text(nullable=True)
"""特殊描述"""
is_virtual: bool = Boolean()
"""是否为虚拟物品"""
########################################
################# Food #################
########################################
quality: FoodQuality | None = Enum(FoodQuality, nullable=True, default=None)
"""食物质量"""
effect: str | None = Text(nullable=True, default=None)
"""效果"""
effect_icon: str | None = String(nullable=True, default=None)
"""效果图标"""
cd_time: int | None = Integer(nullable=True, default=None)
"""效果持续时间"""
cd_group: int | None = Integer(nullable=True, default=None)
"""效果CD组"""
########################################
############### Material ###############
########################################
material_type: str | None = String(nullable=True, default=None)
"""材料类型"""
material_type_description: str | None = Text(nullable=True, default=None)
"""材料类型描述"""
########################################
############### Namecard ###############
########################################
pictures: Json[list[str]] | None = JSON(default=None, nullable=True)
"""名片对应图标名"""
########################################
############### Other ##################
########################################
close_bag_after_used: bool | None = Boolean(nullable=True, default=None)
"""使用后是否关闭背包"""
interaction_title: str | None = String(nullable=True, default=None)
"""交互标题"""
is_force_get_hint: bool | None = Boolean(nullable=True, default=None)
"""是否强制获取提示"""
no_first_get_hint: bool | None = Boolean(nullable=True, default=None)
"""是否没有第一次获取提示"""
use_on_gain: bool | None = Boolean(nullable=True, default=None)
"""在获取时使用"""
use_target: str | None = String(nullable=True, default=None)
"""使用目标"""
ModelMeta.metadata.create_all()

View File

@ -0,0 +1,22 @@
from ormar import ForeignKey, Integer, Text
from models._base import Enum, Model, ModelMeta, String
from models.enums import FoodQuality
from models.item._item import OldItem
class Food(Model):
"""食物"""
class Meta(ModelMeta):
tablename = "item_food"
id: int = Integer(primary_key=True)
item: OldItem = ForeignKey(OldItem)
"""相关物品"""
quality: FoodQuality | None = Enum(FoodQuality, nullable=True)
"""食物质量"""
effect: str | None = Text(nullable=True)
"""效果"""
effect_icon: str = String()
"""效果图标"""

21
old/src/models/other.py Normal file
View File

@ -0,0 +1,21 @@
from ormar import Integer
from models._base import Model, ModelMeta
__all__ = ("ItemCount", )
class ItemCount(Model):
class Meta(ModelMeta):
tablename = 'item_count'
id: int = Integer(primary_key=True)
"""ID"""
item_id: int = Integer()
"""物品ID"""
count: int = Integer()
"""数量"""
ModelMeta.metadata.create_all()

View File

12
old/src/tools/const.py Normal file
View File

@ -0,0 +1,12 @@
from pathlib import Path
__all__ = (
"PROJECT_ROOT",
"OUTPUT_DIR",
)
PROJECT_ROOT = Path(__file__).joinpath("../../../").resolve()
OUTPUT_DIR = PROJECT_ROOT.joinpath("out").resolve()
OUTPUT_DIR.mkdir(exist_ok=True, parents=True)

67
old/src/tools/manager.py Normal file
View File

@ -0,0 +1,67 @@
import ujson as json
import ssl
from functools import lru_cache
import os
from pydantic import Json
from yarl import URL
from httpx import AsyncClient as Client
from utils.const import DATA_DIR
from utils.typedefs import Lang
ssl_context = ssl.SSLContext()
class ResourceManager:
_lang: Lang
_base_url: URL
_client: Client | None = None
_lang_data: dict[str, str] | None = None
def __init__(self, lang: Lang | None = None, *, base_url: str | None = None):
self._base_url = URL(
base_url or "https://gitlab.com/Dimbreath/AnimeGameData/-/raw/master/"
)
self._lang = lang or os.environ.get("LANG", None) or "chs"
@property
def lang(self) -> Lang:
return self._lang
@property
def client(self) -> Client:
from httpx import Timeout
if self._client is None or self._client.is_closed:
self._client = Client(verify=ssl_context, timeout=Timeout(timeout=30))
return self._client
# @lru_cache()
async def fetch(self, name: str, file_dir: str = "ExcelBinOutput") -> Json:
file_path = DATA_DIR.joinpath(file_dir).joinpath(name).with_suffix(".json")
file_path.parent.mkdir(exist_ok=True, parents=True)
if not (file_path.exists() and os.stat(file_path)):
response = await self.client.get(
str(self._base_url / file_dir / file_path.name)
)
response.raise_for_status()
with open(file_path, encoding="utf-8", mode="w") as file:
file.write(content := response.text)
return json.loads(content)
with open(file_path, encoding="utf-8", mode="r") as file:
return json.loads(file.read())
@lru_cache(256, typed=True)
async def __call__(self, text_id: int | str | None) -> str | None:
if text_id is None:
return None
if self._lang_data is None:
self._lang_data = await self.fetch("TextMap" + self.lang.upper(), "TextMap")
result = self._lang_data.get(str(text_id), None)
if result is not None:
return result.replace("\\n", "\n")
return result

View File

View File

@ -2,6 +2,7 @@ import os
import ssl import ssl
from functools import lru_cache from functools import lru_cache
import httpx
import ujson as json import ujson as json
from httpx import Client from httpx import Client
from pydantic import Json from pydantic import Json
@ -22,12 +23,6 @@ class ResourceManager:
_client: Client | None = None _client: Client | None = None
_lang_data: dict[str, str] | None = None _lang_data: dict[str, str] | None = None
def __init__(self, base_url: str | None = None, lang: Lang | None = None):
self._base_url = URL(
base_url or "https://gitlab.com/Dimbreath/AnimeGameData/-/raw/master/"
)
self._lang = lang or "chs"
@property @property
def lang(self) -> Lang: def lang(self) -> Lang:
return self._lang return self._lang
@ -40,6 +35,15 @@ class ResourceManager:
self._client = Client(verify=ssl_context, timeout=Timeout(timeout=30)) self._client = Client(verify=ssl_context, timeout=Timeout(timeout=30))
return self._client return self._client
def __init__(self, lang: Lang | None = None, *, base_url: str | None = None):
self._base_url = URL(
base_url or "https://gitlab.com/Dimbreath/AnimeGameData/-/raw/master/"
)
self._lang = lang or os.environ.get("LANG", None) or "chs"
def __call__(self, text_id: int | str | None) -> str | None:
return self.get_text(text_id)
def refresh(self) -> None: def refresh(self) -> None:
"""删除缓存数据的文件夹,需要数据时会重新从网络上下载,达到刷新缓存数据的目的""" """删除缓存数据的文件夹,需要数据时会重新从网络上下载,达到刷新缓存数据的目的"""
if self._client is not None: if self._client is not None:
@ -67,9 +71,13 @@ class ResourceManager:
file_path.parent.mkdir(exist_ok=True, parents=True) file_path.parent.mkdir(exist_ok=True, parents=True)
if not (file_path.exists() and os.stat(file_path)): if not (file_path.exists() and os.stat(file_path)):
response = self.client.get( while True:
str(self._base_url / file_dir / file_path.name) try:
) response = self.client.get(str(self._base_url / file_dir / file_path.name))
break
except httpx.ReadTimeout:
continue
# noinspection PyUnboundLocalVariable
response.raise_for_status() response.raise_for_status()
with open(file_path, encoding="utf-8", mode="w") as file: with open(file_path, encoding="utf-8", mode="w") as file:
file.write(content := response.text) file.write(content := response.text)

View File

View File

@ -1,5 +1,6 @@
from model.avatar._talente import AvatarTalents from model.avatar._talente import AvatarTalents
from model.enums import Association, AvatarQuality, Element, PropType, WeaponType from model.enums import Association, AvatarQuality, Element, PropType, WeaponType
from model.item import Food
from model.other import ItemCount from model.other import ItemCount
from utils.model import BaseModel from utils.model import BaseModel
@ -87,6 +88,8 @@ class AvatarInfo(BaseModel):
"""所属""" """所属"""
vision: str vision: str
"""神之眼""" """神之眼"""
special_food: Food
"""特殊料理"""
constellation: str constellation: str
"""星座""" """星座"""
description: str description: str
@ -152,6 +155,15 @@ class AvatarAttribute(BaseModel):
"""元素充能效率""" """元素充能效率"""
class AvatarIcon(BaseModel):
"""角色图标"""
name: str
"""证件照"""
side_name: str
"""侧面照"""
class Avatar(BaseModel): class Avatar(BaseModel):
"""角色""" """角色"""
@ -159,6 +171,8 @@ class Avatar(BaseModel):
"""角色ID""" """角色ID"""
name: str name: str
"""名称""" """名称"""
icon: AvatarIcon
"""图标"""
element: Element element: Element
"""元素""" """元素"""
quality: AvatarQuality quality: AvatarQuality

View File

@ -35,8 +35,8 @@ class Food(Item):
"""效果""" """效果"""
effect_icon: str effect_icon: str
"""效果图标""" """效果图标"""
effect_name: str # effect_name: str
"""效果名称""" # """效果名称"""
class Namecard(Item): class Namecard(Item):

View File

View File

@ -32,6 +32,7 @@ from model.avatar import (
TalentAttribute, TalentAttribute,
UtilityPassive, UtilityPassive,
) )
from model.avatar._avatar import AvatarIcon
from model.enums import Association, AvatarQuality, Element, PropType, WeaponType from model.enums import Association, AvatarQuality, Element, PropType, WeaponType
from model.other import ItemCount from model.other import ItemCount
from utils.const import PROJECT_ROOT from utils.const import PROJECT_ROOT
@ -241,6 +242,7 @@ async def parse_avatar_data(lang: Lang):
) is None: ) is None:
continue continue
name = manager.get_text(data["nameTextMapHash"]) name = manager.get_text(data["nameTextMapHash"])
icon = AvatarIcon(name=data["iconName"], side_name=data["sideIconName"])
element = next( element = next(
filter( filter(
lambda x: info_data["avatarVisionBeforTextMapHash"] in x[1], lambda x: info_data["avatarVisionBeforTextMapHash"] in x[1],
@ -448,6 +450,7 @@ async def parse_avatar_data(lang: Lang):
avatar = Avatar( avatar = Avatar(
id=id, id=id,
name=name, name=name,
icon=icon,
element=element, element=element,
quality=quality, quality=quality,
weapon_type=weapon_type, weapon_type=weapon_type,

749
pdm.lock Normal file
View File

@ -0,0 +1,749 @@
# This file is @generated by PDM.
# It is not intended for manual editing.
[metadata]
groups = ["default", "sqlite"]
cross_platform = true
static_urls = false
lock_version = "4.3"
content_hash = "sha256:d6e8399bd56ac79d004edf42f2d700c865dfc865dbb7a9d6bfab690bcc18e2e4"
[[package]]
name = "aiodns"
version = "3.0.0"
summary = "Simple DNS resolver for asyncio"
dependencies = [
"pycares>=4.0.0",
]
files = [
{file = "aiodns-3.0.0-py3-none-any.whl", hash = "sha256:2b19bc5f97e5c936638d28e665923c093d8af2bf3aa88d35c43417fa25d136a2"},
{file = "aiodns-3.0.0.tar.gz", hash = "sha256:946bdfabe743fceeeb093c8a010f5d1645f708a241be849e17edfb0e49e08cd6"},
]
[[package]]
name = "aiofiles"
version = "23.2.1"
requires_python = ">=3.7"
summary = "File support for asyncio."
files = [
{file = "aiofiles-23.2.1-py3-none-any.whl", hash = "sha256:19297512c647d4b27a2cf7c34caa7e405c0d60b5560618a29a9fe027b18b0107"},
{file = "aiofiles-23.2.1.tar.gz", hash = "sha256:84ec2218d8419404abcb9f0c02df3f34c6e0a68ed41072acfb1cef5cbc29051a"},
]
[[package]]
name = "aiohttp"
version = "3.8.5"
requires_python = ">=3.6"
summary = "Async http client/server framework (asyncio)"
dependencies = [
"aiosignal>=1.1.2",
"async-timeout<5.0,>=4.0.0a3",
"attrs>=17.3.0",
"charset-normalizer<4.0,>=2.0",
"frozenlist>=1.1.1",
"multidict<7.0,>=4.5",
"yarl<2.0,>=1.0",
]
files = [
{file = "aiohttp-3.8.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:ae871a964e1987a943d83d6709d20ec6103ca1eaf52f7e0d36ee1b5bebb8b9b9"},
{file = "aiohttp-3.8.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:461908b2578955045efde733719d62f2b649c404189a09a632d245b445c9c975"},
{file = "aiohttp-3.8.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:72a860c215e26192379f57cae5ab12b168b75db8271f111019509a1196dfc780"},
{file = "aiohttp-3.8.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cc14be025665dba6202b6a71cfcdb53210cc498e50068bc088076624471f8bb9"},
{file = "aiohttp-3.8.5-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8af740fc2711ad85f1a5c034a435782fbd5b5f8314c9a3ef071424a8158d7f6b"},
{file = "aiohttp-3.8.5-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:841cd8233cbd2111a0ef0a522ce016357c5e3aff8a8ce92bcfa14cef890d698f"},
{file = "aiohttp-3.8.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5ed1c46fb119f1b59304b5ec89f834f07124cd23ae5b74288e364477641060ff"},
{file = "aiohttp-3.8.5-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:84f8ae3e09a34f35c18fa57f015cc394bd1389bce02503fb30c394d04ee6b938"},
{file = "aiohttp-3.8.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:62360cb771707cb70a6fd114b9871d20d7dd2163a0feafe43fd115cfe4fe845e"},
{file = "aiohttp-3.8.5-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:23fb25a9f0a1ca1f24c0a371523546366bb642397c94ab45ad3aedf2941cec6a"},
{file = "aiohttp-3.8.5-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:b0ba0d15164eae3d878260d4c4df859bbdc6466e9e6689c344a13334f988bb53"},
{file = "aiohttp-3.8.5-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:5d20003b635fc6ae3f96d7260281dfaf1894fc3aa24d1888a9b2628e97c241e5"},
{file = "aiohttp-3.8.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:0175d745d9e85c40dcc51c8f88c74bfbaef9e7afeeeb9d03c37977270303064c"},
{file = "aiohttp-3.8.5-cp311-cp311-win32.whl", hash = "sha256:2e1b1e51b0774408f091d268648e3d57f7260c1682e7d3a63cb00d22d71bb945"},
{file = "aiohttp-3.8.5-cp311-cp311-win_amd64.whl", hash = "sha256:043d2299f6dfdc92f0ac5e995dfc56668e1587cea7f9aa9d8a78a1b6554e5755"},
{file = "aiohttp-3.8.5.tar.gz", hash = "sha256:b9552ec52cc147dbf1944ac7ac98af7602e51ea2dcd076ed194ca3c0d1c7d0bc"},
]
[[package]]
name = "aiohttp"
version = "3.8.5"
extras = ["speedups"]
requires_python = ">=3.6"
summary = "Async http client/server framework (asyncio)"
dependencies = [
"Brotli",
"aiodns",
"aiohttp==3.8.5",
]
files = [
{file = "aiohttp-3.8.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:ae871a964e1987a943d83d6709d20ec6103ca1eaf52f7e0d36ee1b5bebb8b9b9"},
{file = "aiohttp-3.8.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:461908b2578955045efde733719d62f2b649c404189a09a632d245b445c9c975"},
{file = "aiohttp-3.8.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:72a860c215e26192379f57cae5ab12b168b75db8271f111019509a1196dfc780"},
{file = "aiohttp-3.8.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cc14be025665dba6202b6a71cfcdb53210cc498e50068bc088076624471f8bb9"},
{file = "aiohttp-3.8.5-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8af740fc2711ad85f1a5c034a435782fbd5b5f8314c9a3ef071424a8158d7f6b"},
{file = "aiohttp-3.8.5-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:841cd8233cbd2111a0ef0a522ce016357c5e3aff8a8ce92bcfa14cef890d698f"},
{file = "aiohttp-3.8.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5ed1c46fb119f1b59304b5ec89f834f07124cd23ae5b74288e364477641060ff"},
{file = "aiohttp-3.8.5-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:84f8ae3e09a34f35c18fa57f015cc394bd1389bce02503fb30c394d04ee6b938"},
{file = "aiohttp-3.8.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:62360cb771707cb70a6fd114b9871d20d7dd2163a0feafe43fd115cfe4fe845e"},
{file = "aiohttp-3.8.5-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:23fb25a9f0a1ca1f24c0a371523546366bb642397c94ab45ad3aedf2941cec6a"},
{file = "aiohttp-3.8.5-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:b0ba0d15164eae3d878260d4c4df859bbdc6466e9e6689c344a13334f988bb53"},
{file = "aiohttp-3.8.5-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:5d20003b635fc6ae3f96d7260281dfaf1894fc3aa24d1888a9b2628e97c241e5"},
{file = "aiohttp-3.8.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:0175d745d9e85c40dcc51c8f88c74bfbaef9e7afeeeb9d03c37977270303064c"},
{file = "aiohttp-3.8.5-cp311-cp311-win32.whl", hash = "sha256:2e1b1e51b0774408f091d268648e3d57f7260c1682e7d3a63cb00d22d71bb945"},
{file = "aiohttp-3.8.5-cp311-cp311-win_amd64.whl", hash = "sha256:043d2299f6dfdc92f0ac5e995dfc56668e1587cea7f9aa9d8a78a1b6554e5755"},
{file = "aiohttp-3.8.5.tar.gz", hash = "sha256:b9552ec52cc147dbf1944ac7ac98af7602e51ea2dcd076ed194ca3c0d1c7d0bc"},
]
[[package]]
name = "aiomysql"
version = "0.2.0"
requires_python = ">=3.7"
summary = "MySQL driver for asyncio."
dependencies = [
"PyMySQL>=1.0",
]
files = [
{file = "aiomysql-0.2.0-py3-none-any.whl", hash = "sha256:b7c26da0daf23a5ec5e0b133c03d20657276e4eae9b73e040b72787f6f6ade0a"},
{file = "aiomysql-0.2.0.tar.gz", hash = "sha256:558b9c26d580d08b8c5fd1be23c5231ce3aeff2dadad989540fee740253deb67"},
]
[[package]]
name = "aiosignal"
version = "1.3.1"
requires_python = ">=3.7"
summary = "aiosignal: a list of registered asynchronous callbacks"
dependencies = [
"frozenlist>=1.1.0",
]
files = [
{file = "aiosignal-1.3.1-py3-none-any.whl", hash = "sha256:f8376fb07dd1e86a584e4fcdec80b36b7f81aac666ebc724e2c090300dd83b17"},
{file = "aiosignal-1.3.1.tar.gz", hash = "sha256:54cd96e15e1649b75d6c87526a6ff0b6c1b0dd3459f43d9ca11d48c339b68cfc"},
]
[[package]]
name = "annotated-types"
version = "0.5.0"
requires_python = ">=3.7"
summary = "Reusable constraint types to use with typing.Annotated"
files = [
{file = "annotated_types-0.5.0-py3-none-any.whl", hash = "sha256:58da39888f92c276ad970249761ebea80ba544b77acddaa1a4d6cf78287d45fd"},
{file = "annotated_types-0.5.0.tar.gz", hash = "sha256:47cdc3490d9ac1506ce92c7aaa76c579dc3509ff11e098fc867e5130ab7be802"},
]
[[package]]
name = "apsw"
version = "3.43.0.0"
requires_python = ">=3.6"
summary = "Another Python SQLite Wrapper"
files = [
{file = "apsw-3.43.0.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:7fc11344de2361fb2fdcdb6ee592c3edd910379d38e3e86f2d1f77196f0bf1df"},
{file = "apsw-3.43.0.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b770a2cbf7e2975e944076d1a776cc571a4b0fbc6693e0c30c5648d0f39e36f9"},
{file = "apsw-3.43.0.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d42e3cafe7e5a6dc8aec1d8b1792f017d30c17accd5a1d5f362ea77ef601f8b1"},
{file = "apsw-3.43.0.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4b9f7b68430f7cade468acd2a97be31341f504268e9175b41c1b616c94cbe32e"},
{file = "apsw-3.43.0.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2e830f588c085fd219b2f2c35455786070bcdb3a3dd2ebab21bdd0dae182928a"},
{file = "apsw-3.43.0.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f9915d84e0962461523f5c4934a2f7e75fbd5982a986e1d84b68f526f0d3fc06"},
{file = "apsw-3.43.0.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:4a0af14f7a232b47f952b8b73d8d8f145818f43e9e6e877b8828115b32a126cc"},
{file = "apsw-3.43.0.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:ee1251c143c0205df49e40de912aa84f8d760a5f41b964bd38a6af6238826a9a"},
{file = "apsw-3.43.0.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:a5e31440fc763c31fb30e973242df1c1ec23d14796a8eb76a3f75582feea38f8"},
{file = "apsw-3.43.0.0-cp311-cp311-win32.whl", hash = "sha256:b4a96a8698bc5e302e8af6932262772dab4603c354cbb2506986bee1ee3d2e60"},
{file = "apsw-3.43.0.0-cp311-cp311-win_amd64.whl", hash = "sha256:41df9d5c64e795200a49c09ae174db2858c104ccca0d8e2405025e2f997ab9fc"},
{file = "apsw-3.43.0.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:3a47f71c0bbb9e43d8eeb94edb48f9c4d938d3edc5c526bb319ade37457c7a7e"},
{file = "apsw-3.43.0.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:6fe73e350ce7c180add1501b924e3646473c2196d9af2e6c4e13edd57a1b75c9"},
{file = "apsw-3.43.0.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:875feb8ffbb26b09ad46d4af9c243c547033e822ee16e1c59e7bf1898a1692e8"},
{file = "apsw-3.43.0.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9087a8c11fb421bfaa3eae5b22fe58c7027c2f8c9cfb2d7348524df8d8177dd3"},
{file = "apsw-3.43.0.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:24d01cb175c4c33a9973f4f9dc42602904d38a55882f2777e520ae7e39d32668"},
{file = "apsw-3.43.0.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fa33f14d64e173dbca4699abb6153b7abcb82d67d673ef06a5cd4fd9030f5185"},
{file = "apsw-3.43.0.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:8589a3157abab06263618dd4fbb9a5e414716d19a317bf445428bc56354eb1b9"},
{file = "apsw-3.43.0.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:ac28cc62150c4c6d52a18dc47a462aa1e271c120b8d939bc00fd047dda997b51"},
{file = "apsw-3.43.0.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:f188ab0e28466c2bd7d8aae0cb9263b1f162a15e3352aebe5315628a171e6c38"},
{file = "apsw-3.43.0.0-cp312-cp312-win32.whl", hash = "sha256:1fb264bdfd64a2412e3a0c6468845d684ecb4effc4a1d69a79efb65b473f88cc"},
{file = "apsw-3.43.0.0-cp312-cp312-win_amd64.whl", hash = "sha256:5df0bb580d95b79e1720b2cec3df0c659fd072a3289f5e29b22fbe50d4f9ba76"},
{file = "apsw-3.43.0.0.tar.gz", hash = "sha256:81d7db94047d8de91192b5ddac833f9ad131760d98fc478ab805965309d4a7d9"},
]
[[package]]
name = "arko-wrapper"
version = "0.2.8"
requires_python = ">=3.7"
summary = "给你的Python迭代器加上魔法"
dependencies = [
"typing-extensions",
]
files = [
{file = "arko-wrapper-0.2.8.tar.gz", hash = "sha256:85167bc6f1dd48e3415a23a7f2f193c1544a450fd6d219ce28043af796c9b4c3"},
{file = "arko_wrapper-0.2.8-py3-none-any.whl", hash = "sha256:c56b8cdbbd273cc1b7737667374ee600766e9e7f9f9546871b20912024aa0fb2"},
]
[[package]]
name = "async-timeout"
version = "4.0.3"
requires_python = ">=3.7"
summary = "Timeout context manager for asyncio programs"
files = [
{file = "async-timeout-4.0.3.tar.gz", hash = "sha256:4640d96be84d82d02ed59ea2b7105a0f7b33abe8703703cd0ab0bf87c427522f"},
{file = "async_timeout-4.0.3-py3-none-any.whl", hash = "sha256:7405140ff1230c310e51dc27b3145b9092d659ce68ff733fb0cefe3ee42be028"},
]
[[package]]
name = "attrs"
version = "23.1.0"
requires_python = ">=3.7"
summary = "Classes Without Boilerplate"
files = [
{file = "attrs-23.1.0-py3-none-any.whl", hash = "sha256:1f28b4522cdc2fb4256ac1a020c78acf9cba2c6b461ccd2c126f3aa8e8335d04"},
{file = "attrs-23.1.0.tar.gz", hash = "sha256:6279836d581513a26f1bf235f9acd333bc9115683f14f7e8fae46c98fc50e015"},
]
[[package]]
name = "brotli"
version = "1.0.9"
summary = "Python bindings for the Brotli compression library"
files = [
{file = "Brotli-1.0.9-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:cc0283a406774f465fb45ec7efb66857c09ffefbe49ec20b7882eff6d3c86d3a"},
{file = "Brotli-1.0.9-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:11d3283d89af7033236fa4e73ec2cbe743d4f6a81d41bd234f24bf63dde979df"},
{file = "Brotli-1.0.9-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3c1306004d49b84bd0c4f90457c6f57ad109f5cc6067a9664e12b7b79a9948ad"},
{file = "Brotli-1.0.9-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b1375b5d17d6145c798661b67e4ae9d5496920d9265e2f00f1c2c0b5ae91fbde"},
{file = "Brotli-1.0.9-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cab1b5964b39607a66adbba01f1c12df2e55ac36c81ec6ed44f2fca44178bf1a"},
{file = "Brotli-1.0.9-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:8ed6a5b3d23ecc00ea02e1ed8e0ff9a08f4fc87a1f58a2530e71c0f48adf882f"},
{file = "Brotli-1.0.9-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:cb02ed34557afde2d2da68194d12f5719ee96cfb2eacc886352cb73e3808fc5d"},
{file = "Brotli-1.0.9-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:b3523f51818e8f16599613edddb1ff924eeb4b53ab7e7197f85cbc321cdca32f"},
{file = "Brotli-1.0.9-cp311-cp311-win32.whl", hash = "sha256:ba72d37e2a924717990f4d7482e8ac88e2ef43fb95491eb6e0d124d77d2a150d"},
{file = "Brotli-1.0.9-cp311-cp311-win_amd64.whl", hash = "sha256:3ffaadcaeafe9d30a7e4e1e97ad727e4f5610b9fa2f7551998471e3736738679"},
{file = "Brotli-1.0.9-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:9749a124280a0ada4187a6cfd1ffd35c350fb3af79c706589d98e088c5044267"},
{file = "Brotli-1.0.9-pp37-pypy37_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:73fd30d4ce0ea48010564ccee1a26bfe39323fde05cb34b5863455629db61dc7"},
{file = "Brotli-1.0.9-pp37-pypy37_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:02177603aaca36e1fd21b091cb742bb3b305a569e2402f1ca38af471777fb019"},
{file = "Brotli-1.0.9-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:76ffebb907bec09ff511bb3acc077695e2c32bc2142819491579a695f77ffd4d"},
{file = "Brotli-1.0.9-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:b43775532a5904bc938f9c15b77c613cb6ad6fb30990f3b0afaea82797a402d8"},
{file = "Brotli-1.0.9-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:5bf37a08493232fbb0f8229f1824b366c2fc1d02d64e7e918af40acd15f3e337"},
{file = "Brotli-1.0.9-pp38-pypy38_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:330e3f10cd01da535c70d09c4283ba2df5fb78e915bea0a28becad6e2ac010be"},
{file = "Brotli-1.0.9-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:e1abbeef02962596548382e393f56e4c94acd286bd0c5afba756cffc33670e8a"},
{file = "Brotli-1.0.9-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:3148362937217b7072cf80a2dcc007f09bb5ecb96dae4617316638194113d5be"},
{file = "Brotli-1.0.9-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:336b40348269f9b91268378de5ff44dc6fbaa2268194f85177b53463d313842a"},
{file = "Brotli-1.0.9-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3b8b09a16a1950b9ef495a0f8b9d0a87599a9d1f179e2d4ac014b2ec831f87e7"},
{file = "Brotli-1.0.9-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:c8e521a0ce7cf690ca84b8cc2272ddaf9d8a50294fd086da67e517439614c755"},
{file = "Brotli-1.0.9.zip", hash = "sha256:4d1b810aa0ed773f81dceda2cc7b403d01057458730e309856356d4ef4188438"},
]
[[package]]
name = "cffi"
version = "1.15.1"
summary = "Foreign Function Interface for Python calling C code."
dependencies = [
"pycparser",
]
files = [
{file = "cffi-1.15.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3d08afd128ddaa624a48cf2b859afef385b720bb4b43df214f85616922e6a5ac"},
{file = "cffi-1.15.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:3799aecf2e17cf585d977b780ce79ff0dc9b78d799fc694221ce814c2c19db83"},
{file = "cffi-1.15.1-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a591fe9e525846e4d154205572a029f653ada1a78b93697f3b5a8f1f2bc055b9"},
{file = "cffi-1.15.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3548db281cd7d2561c9ad9984681c95f7b0e38881201e157833a2342c30d5e8c"},
{file = "cffi-1.15.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:91fc98adde3d7881af9b59ed0294046f3806221863722ba7d8d120c575314325"},
{file = "cffi-1.15.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:94411f22c3985acaec6f83c6df553f2dbe17b698cc7f8ae751ff2237d96b9e3c"},
{file = "cffi-1.15.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:03425bdae262c76aad70202debd780501fabeaca237cdfddc008987c0e0f59ef"},
{file = "cffi-1.15.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:cc4d65aeeaa04136a12677d3dd0b1c0c94dc43abac5860ab33cceb42b801c1e8"},
{file = "cffi-1.15.1-cp311-cp311-win32.whl", hash = "sha256:a0f100c8912c114ff53e1202d0078b425bee3649ae34d7b070e9697f93c5d52d"},
{file = "cffi-1.15.1-cp311-cp311-win_amd64.whl", hash = "sha256:04ed324bda3cda42b9b695d51bb7d54b680b9719cfab04227cdd1e04e5de3104"},
{file = "cffi-1.15.1.tar.gz", hash = "sha256:d400bfb9a37b1351253cb402671cea7e89bdecc294e8016a707f6d1d8ac934f9"},
]
[[package]]
name = "charset-normalizer"
version = "3.2.0"
requires_python = ">=3.7.0"
summary = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet."
files = [
{file = "charset-normalizer-3.2.0.tar.gz", hash = "sha256:3bb3d25a8e6c0aedd251753a79ae98a093c7e7b471faa3aa9a93a81431987ace"},
{file = "charset_normalizer-3.2.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:4957669ef390f0e6719db3613ab3a7631e68424604a7b448f079bee145da6e09"},
{file = "charset_normalizer-3.2.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:46fb8c61d794b78ec7134a715a3e564aafc8f6b5e338417cb19fe9f57a5a9bf2"},
{file = "charset_normalizer-3.2.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f779d3ad205f108d14e99bb3859aa7dd8e9c68874617c72354d7ecaec2a054ac"},
{file = "charset_normalizer-3.2.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f25c229a6ba38a35ae6e25ca1264621cc25d4d38dca2942a7fce0b67a4efe918"},
{file = "charset_normalizer-3.2.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2efb1bd13885392adfda4614c33d3b68dee4921fd0ac1d3988f8cbb7d589e72a"},
{file = "charset_normalizer-3.2.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1f30b48dd7fa1474554b0b0f3fdfdd4c13b5c737a3c6284d3cdc424ec0ffff3a"},
{file = "charset_normalizer-3.2.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:246de67b99b6851627d945db38147d1b209a899311b1305dd84916f2b88526c6"},
{file = "charset_normalizer-3.2.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9bd9b3b31adcb054116447ea22caa61a285d92e94d710aa5ec97992ff5eb7cf3"},
{file = "charset_normalizer-3.2.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:8c2f5e83493748286002f9369f3e6607c565a6a90425a3a1fef5ae32a36d749d"},
{file = "charset_normalizer-3.2.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:3170c9399da12c9dc66366e9d14da8bf7147e1e9d9ea566067bbce7bb74bd9c2"},
{file = "charset_normalizer-3.2.0-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:7a4826ad2bd6b07ca615c74ab91f32f6c96d08f6fcc3902ceeedaec8cdc3bcd6"},
{file = "charset_normalizer-3.2.0-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:3b1613dd5aee995ec6d4c69f00378bbd07614702a315a2cf6c1d21461fe17c23"},
{file = "charset_normalizer-3.2.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:9e608aafdb55eb9f255034709e20d5a83b6d60c054df0802fa9c9883d0a937aa"},
{file = "charset_normalizer-3.2.0-cp311-cp311-win32.whl", hash = "sha256:f2a1d0fd4242bd8643ce6f98927cf9c04540af6efa92323e9d3124f57727bfc1"},
{file = "charset_normalizer-3.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:681eb3d7e02e3c3655d1b16059fbfb605ac464c834a0c629048a30fad2b27489"},
{file = "charset_normalizer-3.2.0-py3-none-any.whl", hash = "sha256:8e098148dd37b4ce3baca71fb394c81dc5d9c7728c95df695d2dca218edf40e6"},
]
[[package]]
name = "cython"
version = "3.0.1"
requires_python = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
summary = "The Cython compiler for writing C extensions in the Python language."
files = [
{file = "Cython-3.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:5e544e91efa287de31014550aa6e8525507ea6d5727c36ff5f96e9dcf9c40133"},
{file = "Cython-3.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:182ae584dbaa6fd73161a6f8cc7d350eeefc43c091cabc2b70fa1a802a7ef729"},
{file = "Cython-3.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:05dba6b214a12aa66421d810d24d0298ff37cb6036d00d4e851b61a54948540c"},
{file = "Cython-3.0.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:35c28fc53745e7ebabb54d13d6cd3d3659f65ef50d324dadd9146212adb236cc"},
{file = "Cython-3.0.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:6d9dbcecd61f4f22ae6a035628e803490af7f0e16fd91e97fec63face61873a5"},
{file = "Cython-3.0.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:4acd382eb6d8cd34df421c42f1bfc8c7c0c38cd213fa35222a65a2a988fe50da"},
{file = "Cython-3.0.1-cp311-cp311-win32.whl", hash = "sha256:c43adbc5a3a1d678314734f69dba3eb4f24438ba668e08a438b8067ac5a6494e"},
{file = "Cython-3.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:35701606862989d5db641cf8cb85f62eaab9beaafb09a102839aebe5a70a1060"},
{file = "Cython-3.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:9dbdb0019304ec84c7209a967043fc4923ed2d911a37ed695c3d1548c99b1285"},
{file = "Cython-3.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:92f0dda50c11770673c332603b52ce0cb4abf32f2562e53dbdc4b674b6be7faa"},
{file = "Cython-3.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c6f7ead11cfb2d6c6dd7a1fd1987ce221c5c1061b47d747b0bb84b5704045cf9"},
{file = "Cython-3.0.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5936dd43207a3f0269d033463195e201072b9b594c9693ff142985c0c33cd2d2"},
{file = "Cython-3.0.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:768044473afd9fca3ba65d92deb80f16aa10d2776c9c2a8f667dbb480a58c528"},
{file = "Cython-3.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:79f3ea7233e8a8856e57acdb7a30e8548009732649ffabe94049b35e2e5d7b8a"},
{file = "Cython-3.0.1-cp312-cp312-win32.whl", hash = "sha256:b0917b84af48616124dfead2235b36c64c0d024c4d19cefa1a5da2f106a0854a"},
{file = "Cython-3.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:bde58bda00d4689eb51ad3129873b09c695a64d3b6b8573cbc450e177a87173a"},
{file = "Cython-3.0.1-py2.py3-none-any.whl", hash = "sha256:7894efe3b47231bfdf8be1a8a2852a2b07dd83cad16bbdf666591894198c82dd"},
{file = "Cython-3.0.1.tar.gz", hash = "sha256:f3e49c4eaaa11345486ac0fa2b350636e44a4b45bd7521a6b133924c5ff20bba"},
]
[[package]]
name = "frozenlist"
version = "1.4.0"
requires_python = ">=3.8"
summary = "A list-like structure which implements collections.abc.MutableSequence"
files = [
{file = "frozenlist-1.4.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:de343e75f40e972bae1ef6090267f8260c1446a1695e77096db6cfa25e759a95"},
{file = "frozenlist-1.4.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ad2a9eb6d9839ae241701d0918f54c51365a51407fd80f6b8289e2dfca977cc3"},
{file = "frozenlist-1.4.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:bd7bd3b3830247580de99c99ea2a01416dfc3c34471ca1298bccabf86d0ff4dc"},
{file = "frozenlist-1.4.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bdf1847068c362f16b353163391210269e4f0569a3c166bc6a9f74ccbfc7e839"},
{file = "frozenlist-1.4.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:38461d02d66de17455072c9ba981d35f1d2a73024bee7790ac2f9e361ef1cd0c"},
{file = "frozenlist-1.4.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d5a32087d720c608f42caed0ef36d2b3ea61a9d09ee59a5142d6070da9041b8f"},
{file = "frozenlist-1.4.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dd65632acaf0d47608190a71bfe46b209719bf2beb59507db08ccdbe712f969b"},
{file = "frozenlist-1.4.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:261b9f5d17cac914531331ff1b1d452125bf5daa05faf73b71d935485b0c510b"},
{file = "frozenlist-1.4.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:b89ac9768b82205936771f8d2eb3ce88503b1556324c9f903e7156669f521472"},
{file = "frozenlist-1.4.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:008eb8b31b3ea6896da16c38c1b136cb9fec9e249e77f6211d479db79a4eaf01"},
{file = "frozenlist-1.4.0-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:e74b0506fa5aa5598ac6a975a12aa8928cbb58e1f5ac8360792ef15de1aa848f"},
{file = "frozenlist-1.4.0-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:490132667476f6781b4c9458298b0c1cddf237488abd228b0b3650e5ecba7467"},
{file = "frozenlist-1.4.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:76d4711f6f6d08551a7e9ef28c722f4a50dd0fc204c56b4bcd95c6cc05ce6fbb"},
{file = "frozenlist-1.4.0-cp311-cp311-win32.whl", hash = "sha256:a02eb8ab2b8f200179b5f62b59757685ae9987996ae549ccf30f983f40602431"},
{file = "frozenlist-1.4.0-cp311-cp311-win_amd64.whl", hash = "sha256:515e1abc578dd3b275d6a5114030b1330ba044ffba03f94091842852f806f1c1"},
{file = "frozenlist-1.4.0.tar.gz", hash = "sha256:09163bdf0b2907454042edb19f887c6d33806adc71fbd54afc14908bfdc22251"},
]
[[package]]
name = "gevent"
version = "23.7.0"
requires_python = ">=3.8"
summary = "Coroutine-based network library"
dependencies = [
"cffi>=1.12.2; platform_python_implementation == \"CPython\" and sys_platform == \"win32\"",
"greenlet>=2.0.0; platform_python_implementation == \"CPython\" and python_version < \"3.12\"",
"greenlet>=3.0a1; platform_python_implementation == \"CPython\" and python_version >= \"3.12\"",
"zope-event",
"zope-interface",
]
files = [
{file = "gevent-23.7.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:5da07d65dfa23fe419c37cea110bf951b42af6bf3a1fff244043a75c9185dbd5"},
{file = "gevent-23.7.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:df4d7be3352126458cc818309ca6a3b678c209b1ae33e56b6975c6a8309f2068"},
{file = "gevent-23.7.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:76ca6f893953ab898ebbff5d772103318a85044e55d0bad401d6b49d71bb76e7"},
{file = "gevent-23.7.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:aeb1511cf0786152af741c47ee462dac81b57bbd1fbbe08ab562b6c8c9ad75ed"},
{file = "gevent-23.7.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:919423e803939726c99ab2d29ea46b8676af549cee72d263f2b24758ec607b2c"},
{file = "gevent-23.7.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:cea93f4f77badbddc711620cca164ad75c74056603908e621a5ba1b97adbc39c"},
{file = "gevent-23.7.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:dec7b08daf08385fb281b81ec2e7e703243975d867f40ae0a8a3e30b380eb9ea"},
{file = "gevent-23.7.0-cp311-cp311-win_amd64.whl", hash = "sha256:f522b6b015f1bfa9d8d3716ddffb23e3d4a8933df3e4ebf0a29a65a9fa74382b"},
{file = "gevent-23.7.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:746a1e12f280dab07389e6709164b1e1a6caaf50493ea5b1dcaa73cff005174c"},
{file = "gevent-23.7.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5b230007a665d2cf5cf8878c9f56a2b8bacbdc4fe0235afc5269b71cd00528e5"},
{file = "gevent-23.7.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a1d2f1e67d04fde47ca2deac89733df28ef3a7ec1d7359a79f57d4778cced16d"},
{file = "gevent-23.7.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:debc177e88a8c876cb1a4d974f985d03670177bdc61e1c084a8d525f1a50b12d"},
{file = "gevent-23.7.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6b3dd449c80814357f6568eb095a2be2421b805d59fa97c65094707e04a181f9"},
{file = "gevent-23.7.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:769e8811ded08fe7d8b09ad8ebb72d47aecc112411e0726e7296b7ed187ed629"},
{file = "gevent-23.7.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:11b9bb0bce45170ff992760385a86e6955ccb88dba4a82a64d5ce9459290d8d6"},
{file = "gevent-23.7.0.tar.gz", hash = "sha256:d0d3630674c1b344b256a298ab1ff43220f840b12af768131b5d74e485924237"},
]
[[package]]
name = "greenlet"
version = "3.0.0a1"
requires_python = ">=3.7"
summary = "Lightweight in-process concurrent programming"
files = [
{file = "greenlet-3.0.0a1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:a4a2d6ed0515c05afd5cc435361ced0baabd9ba4536ddfe8ad9a95bcb702c8ce"},
{file = "greenlet-3.0.0a1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ffb9f8969789771e95d3c982a36be81f0adfaa7302a1d56e29f168ca15e284b8"},
{file = "greenlet-3.0.0a1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1b3f3568478bc21b85968e8038c4f98f4bf0039a692791bc324b5e0d1522f4b1"},
{file = "greenlet-3.0.0a1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2e160a65cc6023a237be870f2072513747d512a1d018efa083acce0b673cccc0"},
{file = "greenlet-3.0.0a1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e31d1a33dc9006b278f72cb0aacfe397606c2693aa2fdc0c2f2dcddbad9e0b53"},
{file = "greenlet-3.0.0a1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a00550757fca1b9cbc479f8eb1cf3514dbc0103b3f76eae46341c26ddcca67a9"},
{file = "greenlet-3.0.0a1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:2840187a94e258445e62ff1545e34f0b1a14aef4d0078e5c88246688d2b6515e"},
{file = "greenlet-3.0.0a1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:271ed380389d2f7e4c1545b6e0837986e62504ab561edbaff05da9c9f3f98f96"},
{file = "greenlet-3.0.0a1-cp311-cp311-win_amd64.whl", hash = "sha256:4ff2a765f4861fc018827eab4df1992f7508d06c62de5d2fe8a6ac2233d4f1d0"},
{file = "greenlet-3.0.0a1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:463d63ca5d8c236788284a9a44b9715372a64d5318a6b5eee36815df1ea0ba3d"},
{file = "greenlet-3.0.0a1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f3530c0ec1fc98c43d5b7061781a8c55bd0db44f789f8152e19d9526cbed6021"},
{file = "greenlet-3.0.0a1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bce5cf2b0f0b29680396c5c98ab39a011bd70f2dfa8b8a6811a69ee6d920cf9f"},
{file = "greenlet-3.0.0a1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f5672082576d0e9f52fa0fa732ff57254d65faeb4a471bc339fe54b58b3e79d2"},
{file = "greenlet-3.0.0a1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5552d7be37d878e9b6359bbffa0512d857bb9703616a4c0656b49c10739d5971"},
{file = "greenlet-3.0.0a1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:36cebce1f30964d5672fd956860e7e7b69772da69658d5743cb676b442eeff36"},
{file = "greenlet-3.0.0a1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:665942d3a954c3e4c976581715f57fb3b86f4cf6bae3ac30b133f8ff777ac6c7"},
{file = "greenlet-3.0.0a1-cp312-cp312-win_amd64.whl", hash = "sha256:ce70aa089ec589b5d5fab388af9f8c9f9dfe8fe4ad844820a92eb240d8628ddf"},
{file = "greenlet-3.0.0a1.tar.gz", hash = "sha256:1bd4ea36f0aeb14ca335e0c9594a5aaefa1ac4e2db7d86ba38f0be96166b3102"},
]
[[package]]
name = "idna"
version = "3.4"
requires_python = ">=3.5"
summary = "Internationalized Domain Names in Applications (IDNA)"
files = [
{file = "idna-3.4-py3-none-any.whl", hash = "sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2"},
{file = "idna-3.4.tar.gz", hash = "sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4"},
]
[[package]]
name = "multidict"
version = "6.0.4"
requires_python = ">=3.7"
summary = "multidict implementation"
files = [
{file = "multidict-6.0.4-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:0dfad7a5a1e39c53ed00d2dd0c2e36aed4650936dc18fd9a1826a5ae1cad6f03"},
{file = "multidict-6.0.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:64da238a09d6039e3bd39bb3aee9c21a5e34f28bfa5aa22518581f910ff94af3"},
{file = "multidict-6.0.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ff959bee35038c4624250473988b24f846cbeb2c6639de3602c073f10410ceba"},
{file = "multidict-6.0.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:01a3a55bd90018c9c080fbb0b9f4891db37d148a0a18722b42f94694f8b6d4c9"},
{file = "multidict-6.0.4-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c5cb09abb18c1ea940fb99360ea0396f34d46566f157122c92dfa069d3e0e982"},
{file = "multidict-6.0.4-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:666daae833559deb2d609afa4490b85830ab0dfca811a98b70a205621a6109fe"},
{file = "multidict-6.0.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:11bdf3f5e1518b24530b8241529d2050014c884cf18b6fc69c0c2b30ca248710"},
{file = "multidict-6.0.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7d18748f2d30f94f498e852c67d61261c643b349b9d2a581131725595c45ec6c"},
{file = "multidict-6.0.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:458f37be2d9e4c95e2d8866a851663cbc76e865b78395090786f6cd9b3bbf4f4"},
{file = "multidict-6.0.4-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:b1a2eeedcead3a41694130495593a559a668f382eee0727352b9a41e1c45759a"},
{file = "multidict-6.0.4-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:7d6ae9d593ef8641544d6263c7fa6408cc90370c8cb2bbb65f8d43e5b0351d9c"},
{file = "multidict-6.0.4-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:5979b5632c3e3534e42ca6ff856bb24b2e3071b37861c2c727ce220d80eee9ed"},
{file = "multidict-6.0.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:dcfe792765fab89c365123c81046ad4103fcabbc4f56d1c1997e6715e8015461"},
{file = "multidict-6.0.4-cp311-cp311-win32.whl", hash = "sha256:3601a3cece3819534b11d4efc1eb76047488fddd0c85a3948099d5da4d504636"},
{file = "multidict-6.0.4-cp311-cp311-win_amd64.whl", hash = "sha256:81a4f0b34bd92df3da93315c6a59034df95866014ac08535fc819f043bfd51f0"},
{file = "multidict-6.0.4.tar.gz", hash = "sha256:3666906492efb76453c0e7b97f2cf459b0682e7402c0489a95484965dbc1da49"},
]
[[package]]
name = "orjson"
version = "3.9.5"
requires_python = ">=3.7"
summary = "Fast, correct Python JSON library supporting dataclasses, datetimes, and numpy"
files = [
{file = "orjson-3.9.5-cp311-cp311-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:8547b95ca0e2abd17e1471973e6d676f1d8acedd5f8fb4f739e0612651602d66"},
{file = "orjson-3.9.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:87ce174d6a38d12b3327f76145acbd26f7bc808b2b458f61e94d83cd0ebb4d76"},
{file = "orjson-3.9.5-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a960bb1bc9a964d16fcc2d4af5a04ce5e4dfddca84e3060c35720d0a062064fe"},
{file = "orjson-3.9.5-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1a7aa5573a949760d6161d826d34dc36db6011926f836851fe9ccb55b5a7d8e8"},
{file = "orjson-3.9.5-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8b2852afca17d7eea85f8e200d324e38c851c96598ac7b227e4f6c4e59fbd3df"},
{file = "orjson-3.9.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aa185959c082475288da90f996a82e05e0c437216b96f2a8111caeb1d54ef926"},
{file = "orjson-3.9.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:89c9332695b838438ea4b9a482bce8ffbfddde4df92750522d928fb00b7b8dce"},
{file = "orjson-3.9.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:2493f1351a8f0611bc26e2d3d407efb873032b4f6b8926fed8cfed39210ca4ba"},
{file = "orjson-3.9.5-cp311-none-win32.whl", hash = "sha256:ffc544e0e24e9ae69301b9a79df87a971fa5d1c20a6b18dca885699709d01be0"},
{file = "orjson-3.9.5-cp311-none-win_amd64.whl", hash = "sha256:89670fe2732e3c0c54406f77cad1765c4c582f67b915c74fda742286809a0cdc"},
{file = "orjson-3.9.5-cp312-cp312-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:15df211469625fa27eced4aa08dc03e35f99c57d45a33855cc35f218ea4071b8"},
{file = "orjson-3.9.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d9f17c59fe6c02bc5f89ad29edb0253d3059fe8ba64806d789af89a45c35269a"},
{file = "orjson-3.9.5-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ca6b96659c7690773d8cebb6115c631f4a259a611788463e9c41e74fa53bf33f"},
{file = "orjson-3.9.5-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a26fafe966e9195b149950334bdbe9026eca17fe8ffe2d8fa87fdc30ca925d30"},
{file = "orjson-3.9.5-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9006b1eb645ecf460da067e2dd17768ccbb8f39b01815a571bfcfab7e8da5e52"},
{file = "orjson-3.9.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ebfdbf695734b1785e792a1315e41835ddf2a3e907ca0e1c87a53f23006ce01d"},
{file = "orjson-3.9.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:4a3943234342ab37d9ed78fb0a8f81cd4b9532f67bf2ac0d3aa45fa3f0a339f3"},
{file = "orjson-3.9.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:e6762755470b5c82f07b96b934af32e4d77395a11768b964aaa5eb092817bc31"},
{file = "orjson-3.9.5-cp312-none-win_amd64.whl", hash = "sha256:c74df28749c076fd6e2157190df23d43d42b2c83e09d79b51694ee7315374ad5"},
{file = "orjson-3.9.5.tar.gz", hash = "sha256:6daf5ee0b3cf530b9978cdbf71024f1c16ed4a67d05f6ec435c6e7fe7a52724c"},
]
[[package]]
name = "peewee"
version = "3.16.3"
summary = "a little orm"
files = [
{file = "peewee-3.16.3.tar.gz", hash = "sha256:12b30e931193bc37b11f7c2ac646e3f67125a8b1a543ad6ab37ad124c8df7d16"},
]
[[package]]
name = "peewee-async"
version = "0.8.1"
summary = "Asynchronous interface for peewee ORM powered by asyncio."
dependencies = [
"peewee<4.0,>=3.15.4",
]
files = [
{file = "peewee-async-0.8.1.tar.gz", hash = "sha256:2ecc99fbee5b4be6e8423dd851996249adda2111ee5e7b60ba666ede2f796cd0"},
{file = "peewee_async-0.8.1-py3-none-any.whl", hash = "sha256:e08a09fa9f104c352342abaf7f5bff6327490f5b931552f27bc1aac26b58ad44"},
]
[[package]]
name = "pycares"
version = "4.3.0"
summary = "Python interface for c-ares"
dependencies = [
"cffi>=1.5.0",
]
files = [
{file = "pycares-4.3.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:4e7a24ecef0b1933f2a3fdbf328d1b529a76cda113f8364fa0742e5b3bd76566"},
{file = "pycares-4.3.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:e7abccc2aa4771c06994e4d9ed596453061e2b8846f887d9c98a64ccdaf4790a"},
{file = "pycares-4.3.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:531fed46c5ed798a914c3207be4ae7b297c4d09e4183d3cf8fd9ee59a55d5080"},
{file = "pycares-4.3.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2c9335175af0c64a1e0ba67bdd349eb62d4eea0ad02c235ccdf0d535fd20f323"},
{file = "pycares-4.3.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c5f0e95535027d2dcd51e780410632b0d3ed7e9e5ceb25dc0fe937f2c2960079"},
{file = "pycares-4.3.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:3692179ce5fb96908ba342e1e5303608d0c976f0d5d4619fa9d3d6d9d5a9a1b4"},
{file = "pycares-4.3.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:5c4cb6cc7fe8e0606d30b60367f59fe26d1472e88555d61e202db70dea5c8edb"},
{file = "pycares-4.3.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:3215445396c74103e2054e6b349d9e85883ceda2006d0039fc2d58c9b11818a2"},
{file = "pycares-4.3.0-cp311-cp311-win32.whl", hash = "sha256:6a0c0c3a0adf490bba9dbb37dbd07ec81e4a6584f095036ac34f06a633710ffe"},
{file = "pycares-4.3.0-cp311-cp311-win_amd64.whl", hash = "sha256:995cb37cc39bd40ca87bb16555a0f7724f3be30d9f9059a4caab2fde45b1b903"},
{file = "pycares-4.3.0.tar.gz", hash = "sha256:c542696f6dac978e9d99192384745a65f80a7d9450501151e4a7563e06010d45"},
]
[[package]]
name = "pycparser"
version = "2.21"
requires_python = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
summary = "C parser in Python"
files = [
{file = "pycparser-2.21-py2.py3-none-any.whl", hash = "sha256:8ee45429555515e1f6b185e78100aea234072576aa43ab53aefcae078162fca9"},
{file = "pycparser-2.21.tar.gz", hash = "sha256:e644fdec12f7872f86c58ff790da456218b10f863970249516d60a5eaca77206"},
]
[[package]]
name = "pydantic"
version = "2.3.0"
requires_python = ">=3.7"
summary = "Data validation using Python type hints"
dependencies = [
"annotated-types>=0.4.0",
"pydantic-core==2.6.3",
"typing-extensions>=4.6.1",
]
files = [
{file = "pydantic-2.3.0-py3-none-any.whl", hash = "sha256:45b5e446c6dfaad9444819a293b921a40e1db1aa61ea08aede0522529ce90e81"},
{file = "pydantic-2.3.0.tar.gz", hash = "sha256:1607cc106602284cd4a00882986570472f193fde9cb1259bceeaedb26aa79a6d"},
]
[[package]]
name = "pydantic-core"
version = "2.6.3"
requires_python = ">=3.7"
summary = ""
dependencies = [
"typing-extensions!=4.7.0,>=4.6.0",
]
files = [
{file = "pydantic_core-2.6.3-cp311-cp311-macosx_10_7_x86_64.whl", hash = "sha256:6bcc1ad776fffe25ea5c187a028991c031a00ff92d012ca1cc4714087e575973"},
{file = "pydantic_core-2.6.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:df14f6332834444b4a37685810216cc8fe1fe91f447332cd56294c984ecbff1c"},
{file = "pydantic_core-2.6.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a0b7486d85293f7f0bbc39b34e1d8aa26210b450bbd3d245ec3d732864009819"},
{file = "pydantic_core-2.6.3-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a892b5b1871b301ce20d40b037ffbe33d1407a39639c2b05356acfef5536d26a"},
{file = "pydantic_core-2.6.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:883daa467865e5766931e07eb20f3e8152324f0adf52658f4d302242c12e2c32"},
{file = "pydantic_core-2.6.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d4eb77df2964b64ba190eee00b2312a1fd7a862af8918ec70fc2d6308f76ac64"},
{file = "pydantic_core-2.6.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1ce8c84051fa292a5dc54018a40e2a1926fd17980a9422c973e3ebea017aa8da"},
{file = "pydantic_core-2.6.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:22134a4453bd59b7d1e895c455fe277af9d9d9fbbcb9dc3f4a97b8693e7e2c9b"},
{file = "pydantic_core-2.6.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:02e1c385095efbd997311d85c6021d32369675c09bcbfff3b69d84e59dc103f6"},
{file = "pydantic_core-2.6.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:d79f1f2f7ebdb9b741296b69049ff44aedd95976bfee38eb4848820628a99b50"},
{file = "pydantic_core-2.6.3-cp311-none-win32.whl", hash = "sha256:430ddd965ffd068dd70ef4e4d74f2c489c3a313adc28e829dd7262cc0d2dd1e8"},
{file = "pydantic_core-2.6.3-cp311-none-win_amd64.whl", hash = "sha256:84f8bb34fe76c68c9d96b77c60cef093f5e660ef8e43a6cbfcd991017d375950"},
{file = "pydantic_core-2.6.3-cp311-none-win_arm64.whl", hash = "sha256:5a2a3c9ef904dcdadb550eedf3291ec3f229431b0084666e2c2aa8ff99a103a2"},
{file = "pydantic_core-2.6.3-cp312-cp312-macosx_10_7_x86_64.whl", hash = "sha256:8421cf496e746cf8d6b677502ed9a0d1e4e956586cd8b221e1312e0841c002d5"},
{file = "pydantic_core-2.6.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:bb128c30cf1df0ab78166ded1ecf876620fb9aac84d2413e8ea1594b588c735d"},
{file = "pydantic_core-2.6.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:37a822f630712817b6ecc09ccc378192ef5ff12e2c9bae97eb5968a6cdf3b862"},
{file = "pydantic_core-2.6.3-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:240a015102a0c0cc8114f1cba6444499a8a4d0333e178bc504a5c2196defd456"},
{file = "pydantic_core-2.6.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3f90e5e3afb11268628c89f378f7a1ea3f2fe502a28af4192e30a6cdea1e7d5e"},
{file = "pydantic_core-2.6.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:340e96c08de1069f3d022a85c2a8c63529fd88709468373b418f4cf2c949fb0e"},
{file = "pydantic_core-2.6.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1480fa4682e8202b560dcdc9eeec1005f62a15742b813c88cdc01d44e85308e5"},
{file = "pydantic_core-2.6.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f14546403c2a1d11a130b537dda28f07eb6c1805a43dae4617448074fd49c282"},
{file = "pydantic_core-2.6.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:a87c54e72aa2ef30189dc74427421e074ab4561cf2bf314589f6af5b37f45e6d"},
{file = "pydantic_core-2.6.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:f93255b3e4d64785554e544c1c76cd32f4a354fa79e2eeca5d16ac2e7fdd57aa"},
{file = "pydantic_core-2.6.3-cp312-none-win32.whl", hash = "sha256:f70dc00a91311a1aea124e5f64569ea44c011b58433981313202c46bccbec0e1"},
{file = "pydantic_core-2.6.3-cp312-none-win_amd64.whl", hash = "sha256:23470a23614c701b37252618e7851e595060a96a23016f9a084f3f92f5ed5881"},
{file = "pydantic_core-2.6.3-cp312-none-win_arm64.whl", hash = "sha256:1ac1750df1b4339b543531ce793b8fd5c16660a95d13aecaab26b44ce11775e9"},
{file = "pydantic_core-2.6.3-pp310-pypy310_pp73-macosx_10_7_x86_64.whl", hash = "sha256:d7050899026e708fb185e174c63ebc2c4ee7a0c17b0a96ebc50e1f76a231c057"},
{file = "pydantic_core-2.6.3-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:99faba727727b2e59129c59542284efebbddade4f0ae6a29c8b8d3e1f437beb7"},
{file = "pydantic_core-2.6.3-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5fa159b902d22b283b680ef52b532b29554ea2a7fc39bf354064751369e9dbd7"},
{file = "pydantic_core-2.6.3-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:046af9cfb5384f3684eeb3f58a48698ddab8dd870b4b3f67f825353a14441418"},
{file = "pydantic_core-2.6.3-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:930bfe73e665ebce3f0da2c6d64455098aaa67e1a00323c74dc752627879fc67"},
{file = "pydantic_core-2.6.3-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:85cc4d105747d2aa3c5cf3e37dac50141bff779545ba59a095f4a96b0a460e70"},
{file = "pydantic_core-2.6.3-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:b25afe9d5c4f60dcbbe2b277a79be114e2e65a16598db8abee2a2dcde24f162b"},
{file = "pydantic_core-2.6.3-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:e49ce7dc9f925e1fb010fc3d555250139df61fa6e5a0a95ce356329602c11ea9"},
{file = "pydantic_core-2.6.3-pp37-pypy37_pp73-macosx_10_7_x86_64.whl", hash = "sha256:2dd50d6a1aef0426a1d0199190c6c43ec89812b1f409e7fe44cb0fbf6dfa733c"},
{file = "pydantic_core-2.6.3-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c6595b0d8c8711e8e1dc389d52648b923b809f68ac1c6f0baa525c6440aa0daa"},
{file = "pydantic_core-2.6.3-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4ef724a059396751aef71e847178d66ad7fc3fc969a1a40c29f5aac1aa5f8784"},
{file = "pydantic_core-2.6.3-pp37-pypy37_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:3c8945a105f1589ce8a693753b908815e0748f6279959a4530f6742e1994dcb6"},
{file = "pydantic_core-2.6.3-pp37-pypy37_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:c8c6660089a25d45333cb9db56bb9e347241a6d7509838dbbd1931d0e19dbc7f"},
{file = "pydantic_core-2.6.3-pp37-pypy37_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:692b4ff5c4e828a38716cfa92667661a39886e71136c97b7dac26edef18767f7"},
{file = "pydantic_core-2.6.3-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:f1a5d8f18877474c80b7711d870db0eeef9442691fcdb00adabfc97e183ee0b0"},
{file = "pydantic_core-2.6.3-pp38-pypy38_pp73-macosx_10_7_x86_64.whl", hash = "sha256:3796a6152c545339d3b1652183e786df648ecdf7c4f9347e1d30e6750907f5bb"},
{file = "pydantic_core-2.6.3-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:b962700962f6e7a6bd77e5f37320cabac24b4c0f76afeac05e9f93cf0c620014"},
{file = "pydantic_core-2.6.3-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:56ea80269077003eaa59723bac1d8bacd2cd15ae30456f2890811efc1e3d4413"},
{file = "pydantic_core-2.6.3-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:75c0ebbebae71ed1e385f7dfd9b74c1cff09fed24a6df43d326dd7f12339ec34"},
{file = "pydantic_core-2.6.3-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:252851b38bad3bfda47b104ffd077d4f9604a10cb06fe09d020016a25107bf98"},
{file = "pydantic_core-2.6.3-pp38-pypy38_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:6656a0ae383d8cd7cc94e91de4e526407b3726049ce8d7939049cbfa426518c8"},
{file = "pydantic_core-2.6.3-pp38-pypy38_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:d9140ded382a5b04a1c030b593ed9bf3088243a0a8b7fa9f071a5736498c5483"},
{file = "pydantic_core-2.6.3-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:d38bbcef58220f9c81e42c255ef0bf99735d8f11edef69ab0b499da77105158a"},
{file = "pydantic_core-2.6.3-pp39-pypy39_pp73-macosx_10_7_x86_64.whl", hash = "sha256:c9d469204abcca28926cbc28ce98f28e50e488767b084fb3fbdf21af11d3de26"},
{file = "pydantic_core-2.6.3-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:48c1ed8b02ffea4d5c9c220eda27af02b8149fe58526359b3c07eb391cb353a2"},
{file = "pydantic_core-2.6.3-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8b2b1bfed698fa410ab81982f681f5b1996d3d994ae8073286515ac4d165c2e7"},
{file = "pydantic_core-2.6.3-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bf9d42a71a4d7a7c1f14f629e5c30eac451a6fc81827d2beefd57d014c006c4a"},
{file = "pydantic_core-2.6.3-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:4292ca56751aebbe63a84bbfc3b5717abb09b14d4b4442cc43fd7c49a1529efd"},
{file = "pydantic_core-2.6.3-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:7dc2ce039c7290b4ef64334ec7e6ca6494de6eecc81e21cb4f73b9b39991408c"},
{file = "pydantic_core-2.6.3-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:615a31b1629e12445c0e9fc8339b41aaa6cc60bd53bf802d5fe3d2c0cda2ae8d"},
{file = "pydantic_core-2.6.3-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:1fa1f6312fb84e8c281f32b39affe81984ccd484da6e9d65b3d18c202c666149"},
{file = "pydantic_core-2.6.3.tar.gz", hash = "sha256:1508f37ba9e3ddc0189e6ff4e2228bd2d3c3a4641cbe8c07177162f76ed696c7"},
]
[[package]]
name = "pydantic-settings"
version = "2.0.3"
requires_python = ">=3.7"
summary = "Settings management using Pydantic"
dependencies = [
"pydantic>=2.0.1",
"python-dotenv>=0.21.0",
]
files = [
{file = "pydantic_settings-2.0.3-py3-none-any.whl", hash = "sha256:ddd907b066622bd67603b75e2ff791875540dc485b7307c4fffc015719da8625"},
{file = "pydantic_settings-2.0.3.tar.gz", hash = "sha256:962dc3672495aad6ae96a4390fac7e593591e144625e5112d359f8f67fb75945"},
]
[[package]]
name = "pymysql"
version = "1.1.0"
requires_python = ">=3.7"
summary = "Pure Python MySQL Driver"
files = [
{file = "PyMySQL-1.1.0-py3-none-any.whl", hash = "sha256:8969ec6d763c856f7073c4c64662882675702efcb114b4bcbb955aea3a069fa7"},
{file = "PyMySQL-1.1.0.tar.gz", hash = "sha256:4f13a7df8bf36a51e81dd9f3605fede45a4878fe02f9236349fd82a3f0612f96"},
]
[[package]]
name = "python-dotenv"
version = "1.0.0"
requires_python = ">=3.8"
summary = "Read key-value pairs from a .env file and set them as environment variables"
files = [
{file = "python-dotenv-1.0.0.tar.gz", hash = "sha256:a8df96034aae6d2d50a4ebe8216326c61c3eb64836776504fcca410e5937a3ba"},
{file = "python_dotenv-1.0.0-py3-none-any.whl", hash = "sha256:f5971a9226b701070a4bf2c38c89e5a3f0d64de8debda981d1db98583009122a"},
]
[[package]]
name = "regex"
version = "2022.10.31"
requires_python = ">=3.6"
summary = "Alternative regular expression module, to replace re."
files = [
{file = "regex-2022.10.31-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4b4b1fe58cd102d75ef0552cf17242705ce0759f9695334a56644ad2d83903fe"},
{file = "regex-2022.10.31-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:542e3e306d1669b25936b64917285cdffcd4f5c6f0247636fec037187bd93542"},
{file = "regex-2022.10.31-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c27cc1e4b197092e50ddbf0118c788d9977f3f8f35bfbbd3e76c1846a3443df7"},
{file = "regex-2022.10.31-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b8e38472739028e5f2c3a4aded0ab7eadc447f0d84f310c7a8bb697ec417229e"},
{file = "regex-2022.10.31-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:76c598ca73ec73a2f568e2a72ba46c3b6c8690ad9a07092b18e48ceb936e9f0c"},
{file = "regex-2022.10.31-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c28d3309ebd6d6b2cf82969b5179bed5fefe6142c70f354ece94324fa11bf6a1"},
{file = "regex-2022.10.31-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9af69f6746120998cd9c355e9c3c6aec7dff70d47247188feb4f829502be8ab4"},
{file = "regex-2022.10.31-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:a5f9505efd574d1e5b4a76ac9dd92a12acb2b309551e9aa874c13c11caefbe4f"},
{file = "regex-2022.10.31-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:5ff525698de226c0ca743bfa71fc6b378cda2ddcf0d22d7c37b1cc925c9650a5"},
{file = "regex-2022.10.31-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:4fe7fda2fe7c8890d454f2cbc91d6c01baf206fbc96d89a80241a02985118c0c"},
{file = "regex-2022.10.31-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:2cdc55ca07b4e70dda898d2ab7150ecf17c990076d3acd7a5f3b25cb23a69f1c"},
{file = "regex-2022.10.31-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:44a6c2f6374e0033873e9ed577a54a3602b4f609867794c1a3ebba65e4c93ee7"},
{file = "regex-2022.10.31-cp311-cp311-win32.whl", hash = "sha256:d8716f82502997b3d0895d1c64c3b834181b1eaca28f3f6336a71777e437c2af"},
{file = "regex-2022.10.31-cp311-cp311-win_amd64.whl", hash = "sha256:61edbca89aa3f5ef7ecac8c23d975fe7261c12665f1d90a6b1af527bba86ce61"},
{file = "regex-2022.10.31.tar.gz", hash = "sha256:a3a98921da9a1bf8457aeee6a551948a83601689e5ecdd736894ea9bbec77e83"},
]
[[package]]
name = "setuptools"
version = "68.1.2"
requires_python = ">=3.8"
summary = "Easily download, build, install, upgrade, and uninstall Python packages"
files = [
{file = "setuptools-68.1.2-py3-none-any.whl", hash = "sha256:3d8083eed2d13afc9426f227b24fd1659489ec107c0e86cec2ffdde5c92e790b"},
{file = "setuptools-68.1.2.tar.gz", hash = "sha256:3d4dfa6d95f1b101d695a6160a7626e15583af71a5f52176efa5d39a054d475d"},
]
[[package]]
name = "typing-extensions"
version = "4.7.1"
requires_python = ">=3.7"
summary = "Backported and Experimental Type Hints for Python 3.7+"
files = [
{file = "typing_extensions-4.7.1-py3-none-any.whl", hash = "sha256:440d5dd3af93b060174bf433bccd69b0babc3b15b1a8dca43789fd7f61514b36"},
{file = "typing_extensions-4.7.1.tar.gz", hash = "sha256:b75ddc264f0ba5615db7ba217daeb99701ad295353c45f9e95963337ceeeffb2"},
]
[[package]]
name = "ujson"
version = "5.8.0"
requires_python = ">=3.8"
summary = "Ultra fast JSON encoder and decoder for Python"
files = [
{file = "ujson-5.8.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:193349a998cd821483a25f5df30b44e8f495423840ee11b3b28df092ddfd0f7f"},
{file = "ujson-5.8.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4ddeabbc78b2aed531f167d1e70387b151900bc856d61e9325fcdfefb2a51ad8"},
{file = "ujson-5.8.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5ce24909a9c25062e60653073dd6d5e6ec9d6ad7ed6e0069450d5b673c854405"},
{file = "ujson-5.8.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:27a2a3c7620ebe43641e926a1062bc04e92dbe90d3501687957d71b4bdddaec4"},
{file = "ujson-5.8.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2b852bdf920fe9f84e2a2c210cc45f1b64f763b4f7d01468b33f7791698e455e"},
{file = "ujson-5.8.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:20768961a6a706170497129960762ded9c89fb1c10db2989c56956b162e2a8a3"},
{file = "ujson-5.8.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:e0147d41e9fb5cd174207c4a2895c5e24813204499fd0839951d4c8784a23bf5"},
{file = "ujson-5.8.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e3673053b036fd161ae7a5a33358ccae6793ee89fd499000204676baafd7b3aa"},
{file = "ujson-5.8.0-cp311-cp311-win32.whl", hash = "sha256:a89cf3cd8bf33a37600431b7024a7ccf499db25f9f0b332947fbc79043aad879"},
{file = "ujson-5.8.0-cp311-cp311-win_amd64.whl", hash = "sha256:3659deec9ab9eb19e8646932bfe6fe22730757c4addbe9d7d5544e879dc1b721"},
{file = "ujson-5.8.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:102bf31c56f59538cccdfec45649780ae00657e86247c07edac434cb14d5388c"},
{file = "ujson-5.8.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:299a312c3e85edee1178cb6453645217ba23b4e3186412677fa48e9a7f986de6"},
{file = "ujson-5.8.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f2e385a7679b9088d7bc43a64811a7713cc7c33d032d020f757c54e7d41931ae"},
{file = "ujson-5.8.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ad24ec130855d4430a682c7a60ca0bc158f8253ec81feed4073801f6b6cb681b"},
{file = "ujson-5.8.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:16fde596d5e45bdf0d7de615346a102510ac8c405098e5595625015b0d4b5296"},
{file = "ujson-5.8.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:6d230d870d1ce03df915e694dcfa3f4e8714369cce2346686dbe0bc8e3f135e7"},
{file = "ujson-5.8.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:9571de0c53db5cbc265945e08f093f093af2c5a11e14772c72d8e37fceeedd08"},
{file = "ujson-5.8.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:7cba16b26efe774c096a5e822e4f27097b7c81ed6fb5264a2b3f5fd8784bab30"},
{file = "ujson-5.8.0-cp312-cp312-win32.whl", hash = "sha256:48c7d373ff22366eecfa36a52b9b55b0ee5bd44c2b50e16084aa88b9de038916"},
{file = "ujson-5.8.0-cp312-cp312-win_amd64.whl", hash = "sha256:5ac97b1e182d81cf395ded620528c59f4177eee024b4b39a50cdd7b720fdeec6"},
{file = "ujson-5.8.0-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:efeddf950fb15a832376c0c01d8d7713479fbeceaed1eaecb2665aa62c305aec"},
{file = "ujson-5.8.0-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7d8283ac5d03e65f488530c43d6610134309085b71db4f675e9cf5dff96a8282"},
{file = "ujson-5.8.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eb0142f6f10f57598655340a3b2c70ed4646cbe674191da195eb0985a9813b83"},
{file = "ujson-5.8.0-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:07d459aca895eb17eb463b00441986b021b9312c6c8cc1d06880925c7f51009c"},
{file = "ujson-5.8.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:d524a8c15cfc863705991d70bbec998456a42c405c291d0f84a74ad7f35c5109"},
{file = "ujson-5.8.0-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:d6f84a7a175c75beecde53a624881ff618e9433045a69fcfb5e154b73cdaa377"},
{file = "ujson-5.8.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b748797131ac7b29826d1524db1cc366d2722ab7afacc2ce1287cdafccddbf1f"},
{file = "ujson-5.8.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2e72ba76313d48a1a3a42e7dc9d1db32ea93fac782ad8dde6f8b13e35c229130"},
{file = "ujson-5.8.0-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f504117a39cb98abba4153bf0b46b4954cc5d62f6351a14660201500ba31fe7f"},
{file = "ujson-5.8.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:a8c91b6f4bf23f274af9002b128d133b735141e867109487d17e344d38b87d94"},
{file = "ujson-5.8.0.tar.gz", hash = "sha256:78e318def4ade898a461b3d92a79f9441e7e0e4d2ad5419abed4336d702c7425"},
]
[[package]]
name = "yarl"
version = "1.9.2"
requires_python = ">=3.7"
summary = "Yet another URL library"
dependencies = [
"idna>=2.0",
"multidict>=4.0",
]
files = [
{file = "yarl-1.9.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:646d663eb2232d7909e6601f1a9107e66f9791f290a1b3dc7057818fe44fc2b6"},
{file = "yarl-1.9.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:aff634b15beff8902d1f918012fc2a42e0dbae6f469fce134c8a0dc51ca423bb"},
{file = "yarl-1.9.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a83503934c6273806aed765035716216cc9ab4e0364f7f066227e1aaea90b8d0"},
{file = "yarl-1.9.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b25322201585c69abc7b0e89e72790469f7dad90d26754717f3310bfe30331c2"},
{file = "yarl-1.9.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:22a94666751778629f1ec4280b08eb11815783c63f52092a5953faf73be24191"},
{file = "yarl-1.9.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8ec53a0ea2a80c5cd1ab397925f94bff59222aa3cf9c6da938ce05c9ec20428d"},
{file = "yarl-1.9.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:159d81f22d7a43e6eabc36d7194cb53f2f15f498dbbfa8edc8a3239350f59fe7"},
{file = "yarl-1.9.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:832b7e711027c114d79dffb92576acd1bd2decc467dec60e1cac96912602d0e6"},
{file = "yarl-1.9.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:95d2ecefbcf4e744ea952d073c6922e72ee650ffc79028eb1e320e732898d7e8"},
{file = "yarl-1.9.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:d4e2c6d555e77b37288eaf45b8f60f0737c9efa3452c6c44626a5455aeb250b9"},
{file = "yarl-1.9.2-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:783185c75c12a017cc345015ea359cc801c3b29a2966c2655cd12b233bf5a2be"},
{file = "yarl-1.9.2-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:b8cc1863402472f16c600e3e93d542b7e7542a540f95c30afd472e8e549fc3f7"},
{file = "yarl-1.9.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:822b30a0f22e588b32d3120f6d41e4ed021806418b4c9f0bc3048b8c8cb3f92a"},
{file = "yarl-1.9.2-cp311-cp311-win32.whl", hash = "sha256:a60347f234c2212a9f0361955007fcf4033a75bf600a33c88a0a8e91af77c0e8"},
{file = "yarl-1.9.2-cp311-cp311-win_amd64.whl", hash = "sha256:be6b3fdec5c62f2a67cb3f8c6dbf56bbf3f61c0f046f84645cd1ca73532ea051"},
{file = "yarl-1.9.2.tar.gz", hash = "sha256:04ab9d4b9f587c06d801c2abfe9317b77cdf996c65a90d5e84ecc45010823571"},
]
[[package]]
name = "zope-event"
version = "5.0"
requires_python = ">=3.7"
summary = "Very basic event publishing system"
dependencies = [
"setuptools",
]
files = [
{file = "zope.event-5.0-py3-none-any.whl", hash = "sha256:2832e95014f4db26c47a13fdaef84cef2f4df37e66b59d8f1f4a8f319a632c26"},
{file = "zope.event-5.0.tar.gz", hash = "sha256:bac440d8d9891b4068e2b5a2c5e2c9765a9df762944bda6955f96bb9b91e67cd"},
]
[[package]]
name = "zope-interface"
version = "6.0"
requires_python = ">=3.7"
summary = "Interfaces for Python"
dependencies = [
"setuptools",
]
files = [
{file = "zope.interface-6.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f2363e5fd81afb650085c6686f2ee3706975c54f331b426800b53531191fdf28"},
{file = "zope.interface-6.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:af169ba897692e9cd984a81cb0f02e46dacdc07d6cf9fd5c91e81f8efaf93d52"},
{file = "zope.interface-6.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fa90bac61c9dc3e1a563e5babb3fd2c0c1c80567e815442ddbe561eadc803b30"},
{file = "zope.interface-6.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:89086c9d3490a0f265a3c4b794037a84541ff5ffa28bb9c24cc9f66566968464"},
{file = "zope.interface-6.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:809fe3bf1a91393abc7e92d607976bbb8586512913a79f2bf7d7ec15bd8ea518"},
{file = "zope.interface-6.0-cp311-cp311-win_amd64.whl", hash = "sha256:0ec9653825f837fbddc4e4b603d90269b501486c11800d7c761eee7ce46d1bbb"},
{file = "zope.interface-6.0.tar.gz", hash = "sha256:aab584725afd10c710b8f1e6e208dbee2d0ad009f57d674cb9d1b3964037275d"},
]

1328
poetry.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -1,25 +1,37 @@
[tool.poetry] [project]
name = "genshinwikidataparser" name = "genshin-wiki-py"
version = "0.1.0" version = "0.1.0"
description = "原神 wiki 数据解析库" description = "Pydantic Genshin Impact Wiki API Wrapper"
authors = ["Karako <karakohear@gmail.com>"] authors = [
license = "MIT" { name = "Karako", email = "karakohear@gmail.com" },
]
dependencies = [
"ujson<6.0.0,>=5.7.0",
"orjson<4.0.0,>=3.8.8",
"aiohttp[speedups]<4.0.0,>=3.8.4",
"aiofiles<24.0.0,>=23.1.0",
"regex<2023.0.0,>=2022.10.31",
"arko-wrapper<1.0.0,>=0.2.8",
"peewee>=3.16.3",
"peewee-async>=0.8.1",
"pydantic>=2.3.0",
"aiomysql>=0.2.0",
"pydantic-settings>=2.0.3",
"Cython>=3.0.1",
"apsw>=3.43.0.0",
"gevent>=23.7.0",
]
requires-python = ">=3.11,<4.0"
readme = "README.md" readme = "README.md"
license = { text = "MIT" }
[tool.poetry.dependencies] [project.optional-dependencies]
python = "^3.11" sqlite = []
ujson = "^5.7.0"
orjson = "^3.8.8"
aiohttp = {extras = ["speedups"], version = "^3.8.4"}
pydantic = {extras = ["dotenv", "email"], version = "^1.10.6"}
aiofiles = "^23.1.0"
regex = "^2022.10.31"
pyhumps = "^3.8.0"
httpx = {extras = ["http2"], version = "^0.23.3"}
arko-wrapper = "^0.2.8"
[tool.pdm.build]
includes = ["genshin_wiki_py", "pyproject.toml", "README.md", "LICENSE"]
[build-system] [build-system]
requires = ["poetry-core"] requires = ["pdm-backend"]
build-backend = "poetry.core.masonry.api" build-backend = "pdm.backend"

26
run.py
View File

@ -1,24 +1,12 @@
from scripts.avatar import parse_avatar_data from genshin.wiki.config import genshin_wiki_config, use_genshin_wiki_config
from scripts.item import parse_item_data
from utils.typedefs import Lang
async def parse(lang: Lang): def main():
await parse_item_data(lang) print(genshin_wiki_config.lang)
await parse_avatar_data(lang) with use_genshin_wiki_config(lang="EN"):
print(genshin_wiki_config.lang)
print(genshin_wiki_config.lang)
async def main():
for lang in Lang.__args__:
await parse(lang)
def __main__():
import asyncio
loop = asyncio.new_event_loop()
loop.run_until_complete(main())
if __name__ == "__main__": if __name__ == "__main__":
__main__() main()

0
src/genshin/__init__.py Normal file
View File

View File

View File

View File

@ -0,0 +1,6 @@
from peewee import IntegerField, CharField
from genshin.wiki._mode import Model
class Item(Model):
name = CharField()

38
src/genshin/wiki/_mode.py Normal file
View File

@ -0,0 +1,38 @@
from typing import TYPE_CHECKING, TypeVar
import peewee
from peewee import CharField, SqliteDatabase
from peewee_async import MySQLDatabase
from genshin.wiki.config import genshin_wiki_config
if TYPE_CHECKING:
from peewee import Database
__all__ = (
"Model",
"ModelMeta",
)
T = TypeVar("T")
database = MySQLDatabase(genshin_wiki_config.database_url)
database.connect()
class ModelMeta:
database: "Database" = database
class Model(peewee.Model):
class Meta(ModelMeta):
abstract = True
class MapStringField(CharField):
def db_value(self, value):
return value.hex # convert UUID to hex string.
def python_value(self, value):
return value

View File

@ -0,0 +1,55 @@
import inspect
from contextlib import contextmanager
from typing import Any, Generator
from pydantic_settings import BaseSettings
from genshin.wiki.tools.typedefs import Lang
__all__ = ("genshin_wiki_config", "use_genshin_wiki_config")
class _GenshinWikiConfig(BaseSettings, env_prefix='genshin_wiki_'):
lang: Lang = "chs"
"""Language of the data to be used."""
database_url: str = "mysql://root:123456@localhost:3306/genshin_wiki?charset=utf8mb4"
"""The connection url of the database."""
metadata_repo: str = "https://gitlab.com/Dimbreath/AnimeGameData/"
"""The repo link of the GenshinData."""
genshin_wiki_config = _GenshinWikiConfig()
@contextmanager
def use_genshin_wiki_config(**kwargs) -> Generator[_GenshinWikiConfig, Any, None]:
global genshin_wiki_config
old_config = genshin_wiki_config
config_dict = genshin_wiki_config.model_dump()
config_dict.update(kwargs)
new_config = _GenshinWikiConfig(**config_dict)
frame = inspect.currentframe().f_back.f_back
local_keys = []
for k, v in frame.f_locals.items():
if type(v).__name__ == _GenshinWikiConfig.__name__:
frame.f_locals[k] = new_config
local_keys.append(k)
global_keys = []
for k, v in frame.f_globals.items():
if type(v).__name__ == _GenshinWikiConfig.__name__:
frame.f_globals[k] = new_config
global_keys.append(k)
genshin_wiki_config = _GenshinWikiConfig(**config_dict)
yield genshin_wiki_config
genshin_wiki_config = old_config
for k in local_keys:
frame.f_locals[k] = old_config
for k in global_keys:
frame.f_globals[k] = old_config

View File

View File

@ -0,0 +1,72 @@
from peewee import SqliteDatabase
from typing import Any
import orjson as json
from aiofiles import open as async_open
from pydantic import Json
from genshin.wiki.config import genshin_wiki_config
from genshin.wiki.tools.const import DATA_DIR
from genshin.wiki.tools.typedefs import Lang
from genshin.wiki.utils.funcs import get_repo_raw
from genshin.wiki.utils.net import Net
LANG_DATA_DIR = DATA_DIR.joinpath("lang")
database_map: dict[Lang, SqliteDatabase] = {}
class MappingText:
_id: int | None = None
_context: str | None = None
def __init__(self, target: int | str) -> None:
if genshin_wiki_config.lang not in database_map:
self._database = SqliteDatabase(
f"sqlite:///{LANG_DATA_DIR.joinpath(genshin_wiki_config.lang)}.sqlite"
)
database_map[genshin_wiki_config.lang] = self._database
else:
self._database = database_map[genshin_wiki_config.lang]
if isinstance(target, int):
self._id = target
self._context = self._database.execute_sql(
"SELECT context FROM mapping_text WHERE id = ?", (target,)
).fetchone()[0]
else:
self._context = target
self._id = self._database.execute_sql(
"SELECT id FROM mapping_text WHERE context = ?", (target,)
).fetchone()[0]
def __eq__(self, other) -> bool:
if isinstance(other, MappingText):
return self._id == other._id
return False
def __hash__(self) -> int:
return self._id
class ResourceManager(Net):
@property
def lang(self) -> Lang:
return genshin_wiki_config.lang
async def metadata(
self, file_path: str, *, overwritten: bool = False
) -> Json[dict[str, Any]]:
"""Download metadata from the GenshinData repo."""
url = get_repo_raw(genshin_wiki_config.metadata_repo) + file_path
if (path := DATA_DIR.joinpath(file_path)).exists():
if not overwritten:
async with async_open(path, "r") as f:
return json.loads(await f.read())
else:
async with async_open(path, "w") as f:
async with await self._get(url) as resp:
await f.write(await resp.text())
return await resp.json()
async def text(self, text_id: int) -> str:
...

View File

View File

@ -0,0 +1,25 @@
import os
from pathlib import Path
__all__ = (
"PKG_DIR",
"DATA_DIR",
"PROJECT_ROOT",
"CACHE_DIR",
)
PKG_DIR = Path(__file__).joinpath("../../").resolve()
"""The root directory of the package."""
DATA_DIR = PKG_DIR.joinpath("data")
"""The directory where data files are stored."""
DATA_DIR.mkdir(parents=True, exist_ok=True)
PROJECT_ROOT = Path(os.curdir).resolve()
"""The root directory of the project."""
CACHE_DIR = PKG_DIR.joinpath("cache")
"""The directory where cache files are stored."""
CACHE_DIR.mkdir(parents=True, exist_ok=True)

View File

@ -0,0 +1,33 @@
from typing_extensions import Literal
__all__ = ("Lang",)
Lang = Literal[
"chs",
"cht",
"de",
"en",
"es",
"fr",
"id",
"jp",
"kr",
"pt",
"ru",
"th",
"vi",
"CHS",
"CHT",
"DE",
"EN",
"ES",
"FR",
"ID",
"JP",
"KR",
"PT",
"RU",
"TH",
"VI",
]

View File

View File

@ -0,0 +1,5 @@
def get_repo_raw(url: str) -> str:
"""Get the raw url of the repo."""
if 'gitlab.com' in url:
return url + "/-/raw/master/"
return url + "/raw/master/"

View File

@ -0,0 +1,43 @@
from multiprocessing import Lock
from typing import TYPE_CHECKING
from aiohttp import ClientResponse, ClientSession
if TYPE_CHECKING:
from multiprocessing.synchronize import Lock as LockType
class Net:
_lock: "LockType" = Lock()
_session: ClientSession | None = None
@property
def session(self) -> ClientSession:
with self._lock:
if self._session is None:
self._session = ClientSession()
return self._session
def __exit__(self, exc_type, exc_val, exc_tb):
if self._session and not self._session.closed:
# noinspection PyBroadException
try:
import asyncio
asyncio.run(self._session.close())
except:
pass
async def _request(self, *args, **kwargs) -> ClientResponse:
time = 0
while True:
try:
return await self.session.request(*args, **kwargs)
except Exception as e:
if time > 3:
raise e
time += 1
async def _get(self, *args, **kwargs) -> ClientResponse:
return await self._request("GET", *args, **kwargs)