commit fa3b4afa67b0e6793f821b95299ca9c9ba7ea9ea Author: ScuroNeko Date: Sun Nov 12 22:44:51 2023 +0300 initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..deb9613 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +.vscode/ +venv/ +__pycache__/ +tests/ \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..d9f08fa --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2023 + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..e69de29 diff --git a/pygidb/__init__.py b/pygidb/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/pygidb/constants.py b/pygidb/constants.py new file mode 100644 index 0000000..73b7306 --- /dev/null +++ b/pygidb/constants.py @@ -0,0 +1,6 @@ +DEFAULT_QUERY = ['English', 'Russian'] +DEFAULT_RESULT = 'Russian' + +LANGUAGES = ['English', 'French', 'German', 'Indonesian', 'Italian', + 'Japanese', 'Korean', 'Portuguese', 'Russian', 'Spanish', + 'Thai', 'Turkish', 'Vietnamese'] diff --git a/pygidb/pygidb.py b/pygidb/pygidb.py new file mode 100644 index 0000000..a0ea1cb --- /dev/null +++ b/pygidb/pygidb.py @@ -0,0 +1,58 @@ +from aiohttp import ClientSession +from pygidb.constants import DEFAULT_QUERY, DEFAULT_RESULT +from urllib.parse import urlencode + +from pygidb.types.api import Response +from pygidb.types.characters import Character + + +class GenshinDBException(Exception): + def __init__(self, error_text, error_code): + super().__init__(error_text) + self.message = error_text + self.code = error_code + + +class GenshinDBOptions: + def __init__(self, query=DEFAULT_QUERY, result=DEFAULT_RESULT): + self._query_languages = query + self._result_language: str = result + + def to_dict(self): + return { + 'query_languages': ','.join(self._query_languages), + 'result_language': self._result_language + } + + +class GenshinDB: + def __init__(self, options=None): + self.options = options + if not self.options: + self.options = GenshinDBOptions() + + self.client = ClientSession() + self.base_url = 'https://gidb.nix13.pw' + + def __del__(self): + pass + + async def __request(self, folder: str, query: str, **kwargs) -> Response: + params = urlencode({**self.options.to_dict(), **kwargs}) + async with self.client.get(f'{self.base_url}/{folder}/{query}?{params}') as r: + json = await r.json() + res = Response(**json) + if res.error: + raise GenshinDBException(**res.response) + return res + + async def get_characters(self) -> dict[str, list[str]]: + res = await self.__request('characters', '') + return res.response[0] + + async def get_character( + self, name: str, images=False, stats=False, url=False + ) -> Character: + res = await self.__request('characters', name, images=images, + stats=stats, url=url) + return Character(**res.response) diff --git a/pygidb/types/achievements.py b/pygidb/types/achievements.py new file mode 100644 index 0000000..2e67b6c --- /dev/null +++ b/pygidb/types/achievements.py @@ -0,0 +1,36 @@ +from typing import Optional + +from pydantic import BaseModel + + +class GroupReward(BaseModel): + name: str + + +class AchievementGroups(BaseModel): + name: str + sortorder: int + reward: GroupReward + + +# Achievement +class StageReward(BaseModel): + name: str + count: int + + +class Stage(BaseModel): + title: str + description: str + progress: int + reward: StageReward + + +class Achievement(BaseModel): + name: str + achievementgroup: str + sortorder: int + stages: int + stage1: Stage + stage2: Optional[Stage] + stage3: Optional[Stage] diff --git a/pygidb/types/adventureranks.py b/pygidb/types/adventureranks.py new file mode 100644 index 0000000..319f81f --- /dev/null +++ b/pygidb/types/adventureranks.py @@ -0,0 +1,16 @@ +from typing import List, Optional + +from pydantic import BaseModel + + +class RewardItem(BaseModel): + name: str + count: int + type: str + + +class AdventureRank(BaseModel): + name: str + exp: Optional[int] = 0 + unlockdescription: str + reward: List[RewardItem] diff --git a/pygidb/types/animals.py b/pygidb/types/animals.py new file mode 100644 index 0000000..0002292 --- /dev/null +++ b/pygidb/types/animals.py @@ -0,0 +1,9 @@ +from pydantic import BaseModel + + +class Animal(BaseModel): + name: str + description: str + category: str + counttype: str + sortorder: int diff --git a/pygidb/types/api.py b/pygidb/types/api.py new file mode 100644 index 0000000..b810138 --- /dev/null +++ b/pygidb/types/api.py @@ -0,0 +1,12 @@ +from typing import Any +from pydantic import BaseModel + + +class ErrorData(BaseModel): + error_code: int + error_text: str + + +class Response(BaseModel): + error: bool = False + response: Any | ErrorData diff --git a/pygidb/types/artifacts.py b/pygidb/types/artifacts.py new file mode 100644 index 0000000..fa4e7fb --- /dev/null +++ b/pygidb/types/artifacts.py @@ -0,0 +1,22 @@ +from typing import List + +from pydantic import BaseModel, Field + + +class Piece(BaseModel): + name: str + relictype: str + description: str + story: str + + +class Artifact(BaseModel): + name: str + rarity: List[str] + field_2pc: str = Field(..., alias='2pc') + field_4pc: str = Field(..., alias='4pc') + flower: Piece + plume: Piece + sands: Piece + goblet: Piece + circlet: Piece diff --git a/pygidb/types/characters.py b/pygidb/types/characters.py new file mode 100644 index 0000000..5082a55 --- /dev/null +++ b/pygidb/types/characters.py @@ -0,0 +1,158 @@ +from typing import List, Optional + +from pydantic import BaseModel, Field + + +class Cv(BaseModel): + english: str + chinese: str + japanese: str + korean: str + + +class AscendItem(BaseModel): + name: str + count: int + + +class Costs(BaseModel): + ascend1: List[AscendItem] + ascend2: List[AscendItem] + ascend3: List[AscendItem] + ascend4: List[AscendItem] + ascend5: List[AscendItem] + ascend6: List[AscendItem] + + +class Images(BaseModel): + card: Optional[str] = None + portrait: Optional[str] = None + icon: Optional[str] = None + sideicon: Optional[str] = None + cover1: Optional[str] = None + cover2: Optional[str] = None + hoyolab_avatar: Optional[str] = Field(None, alias='hoyolab-avatar') + nameicon: Optional[str] = None + nameiconcard: Optional[str] = None + namegachasplash: Optional[str] = None + namegachaslice: Optional[str] = None + namesideicon: Optional[str] = None + + +class Base(BaseModel): + hp: float + attack: float + defense: float + critrate: float + critdmg: float + + +class Curve(BaseModel): + hp: str + attack: str + defense: str + + +class PromotionItem(BaseModel): + maxlevel: int + hp: float + attack: float + defense: float + specialized: float + + +class Stats(BaseModel): + base: Base + curve: Curve + specialized: str + promotion: List[PromotionItem] + + +class URL(BaseModel): + fandom: str + + +class Character(BaseModel): + name: str + fullname: str + title: str + description: str + rarity: str + element: str + weapontype: str + substat: str + gender: str + body: str + association: str + region: str + affiliation: str + birthdaymmdd: str + birthday: str + constellation: str + cv: Cv + costs: Costs + images: Optional[Images] = None + stats: Optional[Stats] = None + url: Optional[URL] = None + version: str + + +# Constellations +class Constellation(BaseModel): + name: str + effect: str + + +class Constellations(BaseModel): + name: str + c1: Constellation + c2: Constellation + c3: Constellation + c4: Constellation + c5: Constellation + c6: Constellation + + +# Talents +class Attributes(BaseModel): + labels: List[str] + + +class Combat(BaseModel): + name: str + info: str + description: Optional[str] = None + attributes: Attributes + + +class Passive(BaseModel): + name: str + info: str + + +class LvlItem(BaseModel): + name: str + count: int + + +class TalentCosts(BaseModel): + lvl2: List[LvlItem] + lvl3: List[LvlItem] + lvl4: List[LvlItem] + lvl5: List[LvlItem] + lvl6: List[LvlItem] + lvl7: List[LvlItem] + lvl8: List[LvlItem] + lvl9: List[LvlItem] + lvl10: List[LvlItem] + + +class Talents(BaseModel): + name: str + combat1: Combat + combat2: Combat + combat3: Combat + passive1: Passive + passive2: Passive + passive3: Passive + costs: TalentCosts diff --git a/pygidb/types/crafts.py b/pygidb/types/crafts.py new file mode 100644 index 0000000..4f76acf --- /dev/null +++ b/pygidb/types/crafts.py @@ -0,0 +1,18 @@ +from typing import List, Optional + +from pydantic import BaseModel + + +class RecipeItem(BaseModel): + name: str + count: int + + +class Craft(BaseModel): + name: str + filter: str + sortorder: int + unlockrank: int + resultcount: int + moracost: Optional[int] = 0 + recipe: List[RecipeItem] diff --git a/pygidb/types/domains.py b/pygidb/types/domains.py new file mode 100644 index 0000000..71194ec --- /dev/null +++ b/pygidb/types/domains.py @@ -0,0 +1,23 @@ +from typing import List, Optional + +from pydantic import BaseModel + + +class RewardpreviewItem(BaseModel): + name: str + count: Optional[int] = None + rarity: Optional[str] = None + + +class Domain(BaseModel): + name: str + region: str + domainentrance: str + domaintype: str + description: str + recommendedlevel: int + recommendedelements: List[str] + unlockrank: int + rewardpreview: List[RewardpreviewItem] + disorder: List[str] + monsterlist: List[str] diff --git a/pygidb/types/elements.py b/pygidb/types/elements.py new file mode 100644 index 0000000..3bd3d11 --- /dev/null +++ b/pygidb/types/elements.py @@ -0,0 +1,10 @@ +from pydantic import BaseModel + + +class Element(BaseModel): + name: str + type: str + color: str + region: str + archon: str + theme: str diff --git a/pygidb/types/enemies.py b/pygidb/types/enemies.py new file mode 100644 index 0000000..9161016 --- /dev/null +++ b/pygidb/types/enemies.py @@ -0,0 +1,18 @@ +from typing import List, Optional + +from pydantic import BaseModel + + +class RewardpreviewItem(BaseModel): + name: str + count: Optional[float] = None + rarity: Optional[str] = None + + +class Enemy(BaseModel): + name: str + specialname: str + enemytype: str + category: str + description: str + rewardpreview: List[RewardpreviewItem] diff --git a/pygidb/types/foods.py b/pygidb/types/foods.py new file mode 100644 index 0000000..5dfbf7b --- /dev/null +++ b/pygidb/types/foods.py @@ -0,0 +1,29 @@ +from typing import List, Optional + +from pydantic import BaseModel + + +class Quality(BaseModel): + effect: str + description: str + + +class Ingredient(BaseModel): + name: str + count: int + + +class Food(BaseModel): + name: str + rarity: str + foodtype: str + foodfilter: str + foodcategory: str + effect: str + description: str + basedish: Optional[str] = None + character: Optional[str] = None + suspicious: Optional[Quality] = None + normal: Optional[Quality] = None + delicious: Optional[Quality] = None + ingredients: List[Ingredient] diff --git a/pygidb/types/geographies.py b/pygidb/types/geographies.py new file mode 100644 index 0000000..744443e --- /dev/null +++ b/pygidb/types/geographies.py @@ -0,0 +1,10 @@ +from pydantic import BaseModel + + +class Geography(BaseModel): + name: str + area: str + description: str + region: str + showonlyunlocked: bool = False + sortorder: int diff --git a/pygidb/types/gliders.py b/pygidb/types/gliders.py new file mode 100644 index 0000000..00129bf --- /dev/null +++ b/pygidb/types/gliders.py @@ -0,0 +1,12 @@ +from typing import List + +from pydantic import BaseModel + + +class Glider(BaseModel): + name: str + description: str + rarity: str + story: str + sortorder: int + source: List[str] \ No newline at end of file diff --git a/pygidb/types/materials.py b/pygidb/types/materials.py new file mode 100644 index 0000000..b3ccf18 --- /dev/null +++ b/pygidb/types/materials.py @@ -0,0 +1,13 @@ +from typing import List + +from pydantic import BaseModel + + +class Material(BaseModel): + name: str + description: str + sortorder: int + rarity: str + category: str + materialtype: str + source: List[str] diff --git a/pygidb/types/namecards.py b/pygidb/types/namecards.py new file mode 100644 index 0000000..2b25a59 --- /dev/null +++ b/pygidb/types/namecards.py @@ -0,0 +1,10 @@ +from typing import List + +from pydantic import BaseModel + + +class NameCard(BaseModel): + name: str + description: str + sortorder: int + source: List[str] diff --git a/pygidb/types/outfits.py b/pygidb/types/outfits.py new file mode 100644 index 0000000..195d06d --- /dev/null +++ b/pygidb/types/outfits.py @@ -0,0 +1,11 @@ +from typing import List, Optional + +from pydantic import BaseModel + + +class Outfit(BaseModel): + name: str + description: str + isdefault: bool + character: str + source: Optional[List[str]] = None diff --git a/pygidb/types/talentmaterialtypes.py b/pygidb/types/talentmaterialtypes.py new file mode 100644 index 0000000..da44596 --- /dev/null +++ b/pygidb/types/talentmaterialtypes.py @@ -0,0 +1,14 @@ +from typing import List + +from pydantic import BaseModel, Field + + +class TalentMaterialType(BaseModel): + name: str + field_2starname: str = Field(..., alias='2starname') + field_3starname: str = Field(..., alias='3starname') + field_4starname: str = Field(..., alias='4starname') + day: List[str] + location: str + region: str + domainofmastery: str diff --git a/pygidb/types/tcg.py b/pygidb/types/tcg.py new file mode 100644 index 0000000..bff3caa --- /dev/null +++ b/pygidb/types/tcg.py @@ -0,0 +1,152 @@ +from typing import List, Optional + +from pydantic import BaseModel + + +class Playcost(BaseModel): + costtype: str + count: int + + +# Action Cards +class ActionCard(BaseModel): + id: int + name: str + cardtype: str + cardtypetext: str + tags: List[str] + tagstext: List[str] + description: str + descriptionraw: str + descriptionreplaced: str + storytitle: str + storytext: str + source: str = None + playcost: List[Playcost] + + +# Card backs +class CardBack(BaseModel): + id: int + name: str + description: str + descriptionraw: str + source: str + rarity: int + + +class CardBox(BaseModel): + id: int + name: str + description: str + descriptionraw: str + source: str + rarity: int + + +# Character cards +class Skill(BaseModel): + id: int + name: str + descriptionraw: str + basedamage: Optional[int] = None + baseelement: Optional[str] = None + descriptionreplaced: str + description: str + typetag: str + type: str + playcost: List[Playcost] + + +class CharacterCard(BaseModel): + id: int + name: str + hp: int + maxenergy: int + tags: List[str] + tagstext: List[str] + storytitle: str + storytext: str + source: str + skills: List[Skill] + + +# Enemy card +class EnemyCard(BaseModel): + id: int + name: str + hp: int + maxenergy: int + tags: List[str] + tagstext: List[str] + skills: List[Skill] + + +# Detailed rules +class Rule(BaseModel): + title: str + titleraw: str + content: str + contentraw: str + filename_image: Optional[str] = None + + +class DetailedRule(BaseModel): + id: int + name: str + rules: List[Rule] + + +# Keywords +class Keyword(BaseModel): + id: int + name: str + nameraw: str + description: str + descriptionraw: str + + +# Level rewards +class Reward(BaseModel): + id: int + name: str + count: int + + +class LevelReward(BaseModel): + id: int + name: str + exp: int = None + icontype: str + unlockdescription: str + unlockdescriptionraw: str + rewards: List[Reward] + + +# Status effects +class StatusEffect(BaseModel): + id: int + name: str + statustypetext: str + cardtype: str + cardtypetext: str + tags: List[str] + description: str + descriptionraw: str + descriptionreplaced: str + + +# Summons +class Summon(BaseModel): + id: int + name: str + cardtypetext: str + tags: List + tagstext: List + description: str + descriptionraw: str + descriptionreplaced: str + countingtype: str + tokentype: str + hinttype: str + diff --git a/pygidb/types/weaponmaterialtypes.py b/pygidb/types/weaponmaterialtypes.py new file mode 100644 index 0000000..addeb65 --- /dev/null +++ b/pygidb/types/weaponmaterialtypes.py @@ -0,0 +1,15 @@ +from typing import List + +from pydantic import BaseModel, Field + + +class WeaponMaterialType(BaseModel): + name: str + field_2starname: str = Field(..., alias='2starname') + field_3starname: str = Field(..., alias='3starname') + field_4starname: str = Field(..., alias='4starname') + field_5starname: str = Field(..., alias='5starname') + day: List[str] + location: str + region: str + domainofforgery: str diff --git a/pygidb/types/weapons.py b/pygidb/types/weapons.py new file mode 100644 index 0000000..2a569d1 --- /dev/null +++ b/pygidb/types/weapons.py @@ -0,0 +1,75 @@ +from typing import List, Optional + +from pydantic import BaseModel + + +class AscendItem(BaseModel): + name: str + count: int + + +class Costs(BaseModel): + ascend1: List[AscendItem] + ascend2: List[AscendItem] + ascend3: List[AscendItem] + ascend4: List[AscendItem] + ascend5: List[AscendItem] + ascend6: List[AscendItem] + + +class URL(BaseModel): + fandom: str + + +class Images(BaseModel): + nameicon: str + namegacha: str + icon: str + nameawakenicon: str + awakenicon: Optional[str] = None + + +class Base(BaseModel): + attack: float + specialized: float + + +class Curve(BaseModel): + attack: str + specialized: str + + +class PromotionItem(BaseModel): + maxlevel: int + attack: float + + +class Stats(BaseModel): + base: Base + curve: Curve + specialized: str + promotion: List[PromotionItem] + + +class Weapon(BaseModel): + name: str + description: str + weapontype: str + rarity: str + story: str + baseatk: int + substat: str + subvalue: str + effectname: str + effect: str + r1: List[str] + r2: List[str] + r3: List[str] + r4: List[str] + r5: List[str] + weaponmaterialtype: str + costs: Costs + url: Optional[URL] = None + images: Optional[Images] = None + stats: Optional[Stats] = None + version: str diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..a4eab46 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,16 @@ +[project] +name = "py-aiovk" +version = "0.0.1" +authors = [{ name="ScuroNeko" }] +description = "Library for operating with Genshin Impact DB" +readme = "README.md" +requires-python = ">=3.7" +classifiers = [ + "Programming Language :: Python :: 3", + "License :: OSI Approved :: MIT License", + "Operating System :: OS Independent", +] + +[project.urls] +"Homepage" = "https://git.nix13.pw/gidb/py-gidb" +"Bug Tracker" = "https://git.nix13.pw/gidb/py-gidb/issues" \ No newline at end of file diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..1e14142 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,2 @@ +pydantic +aiohttp \ No newline at end of file