Module genshin.client.components.calculator.client
Calculator client.
Classes
class CalculatorClient (cookies: Union[ForwardRef('http.cookies.BaseCookie[Any]'), Mapping[Any, Any], str, Sequence[Union[ForwardRef('http.cookies.BaseCookie[Any]'), Mapping[Any, Any], str]], ForwardRef(None)] = None, *, authkey: Optional[str] = None, lang: str = 'en-us', region: Region = Region.OVERSEAS, proxy: Optional[str] = None, game: Optional[Game] = None, uid: Optional[int] = None, hoyolab_id: Optional[int] = None, device_id: Optional[str] = None, device_fp: Optional[str] = None, headers: Union[Mapping[str, str], Mapping[multidict._multidict.istr, str], multidict._multidict.CIMultiDict, multidict._multidict.CIMultiDictProxy, Iterable[Tuple[Union[str, multidict._multidict.istr], str]], ForwardRef(None)] = None, cache: Optional[BaseCache] = None, debug: bool = False)
-
Calculator component.
Expand source code
class CalculatorClient(base.BaseClient): """Calculator component.""" async def request_calculator( self, endpoint: str, *, method: str = "POST", lang: typing.Optional[str] = None, params: typing.Optional[typing.Mapping[str, typing.Any]] = None, data: typing.Optional[typing.Mapping[str, typing.Any]] = None, headers: typing.Optional[aiohttp.typedefs.LooseHeaders] = None, **kwargs: typing.Any, ) -> typing.Mapping[str, typing.Any]: """Make a request towards the calculator endpoint.""" params = dict(params or {}) headers = base.parse_loose_headers(headers) base_url = routes.CALCULATOR_URL.get_url(self.region) url = base_url / endpoint if method == "GET": params["lang"] = lang or self.lang data = None else: data = dict(data or {}) data["lang"] = lang or self.lang if self.region == types.Region.CHINESE: headers["referer"] = str(routes.CALCULATOR_REFERER_URL.get_url()) update_task = asyncio.create_task(utility.update_characters_any(lang or self.lang, lenient=True)) data = await self.request(url, method=method, params=params, data=data, headers=headers, **kwargs) try: await update_task except Exception as e: warnings.warn(f"Failed to update characters: {e!r}") return data async def _execute_calculator( self, data: typing.Mapping[str, typing.Any], *, lang: typing.Optional[str] = None, ) -> models.CalculatorResult: """Calculate the results of a builder.""" data = await self.request_calculator("compute", lang=lang, data=data) return models.CalculatorResult(**data) async def _execute_furnishings_calculator( self, data: typing.Mapping[str, typing.Any], *, lang: typing.Optional[str] = None, ) -> models.CalculatorFurnishingResults: """Calculate the results of a builder.""" data = await self.request_calculator("furniture/compute", lang=lang, data=data) return models.CalculatorFurnishingResults(**data) def calculator(self, *, lang: typing.Optional[str] = None) -> Calculator: """Create a calculator builder object.""" return Calculator(self, lang=lang) def furnishings_calculator(self, *, lang: typing.Optional[str] = None) -> FurnishingCalculator: """Create a calculator builder object.""" return FurnishingCalculator(self, lang=lang) async def _enable_calculator_sync(self, enabled: bool = True) -> None: """Enable data syncing in calculator.""" await self.request_calculator("avatar/auth", method="POST", data=dict(avatar_auth=int(enabled))) async def _get_calculator_items( self, slug: str, filters: typing.Mapping[str, typing.Any], query: typing.Optional[str] = None, *, uid: typing.Optional[int] = None, is_all: bool = False, sync: bool = False, lang: typing.Optional[str] = None, autoauth: bool = True, ) -> typing.Sequence[typing.Mapping[str, typing.Any]]: """Get all items of a specific slug from a calculator.""" endpoint = f"sync/{slug}/list" if sync else f"{slug}/list" if query: if any(filters.values()): raise TypeError("Cannot specify a query and filter at the same time") filters = dict(keywords=query, **filters) payload: dict[str, typing.Any] = dict(page=1, size=69420, is_all=is_all, **filters) if sync: uid = uid or await self._get_uid(types.Game.GENSHIN) payload["uid"] = uid payload["region"] = utility.recognize_genshin_server(uid) cache: typing.Optional[client_cache.CacheKey] = None if not any(filters.values()) and not sync: cache = client_cache.cache_key("calculator", slug=slug, lang=lang or self.lang) try: data = await self.request_calculator(endpoint, lang=lang, data=payload, cache=cache) except errors.GenshinException as e: if e.retcode != -502002: # Sync not enabled raise if not autoauth: raise errors.GenshinException(e.response, "Calculator sync is not enabled") from e await self._enable_calculator_sync() data = await self.request_calculator(endpoint, lang=lang, data=payload, cache=cache) return data["list"] async def get_calculator_characters( self, *, query: typing.Optional[str] = None, elements: typing.Optional[typing.Sequence[int]] = None, weapon_types: typing.Optional[typing.Sequence[int]] = None, include_traveler: bool = False, sync: bool = False, uid: typing.Optional[int] = None, lang: typing.Optional[str] = None, ) -> typing.Sequence[models.CalculatorCharacter]: """Get all characters provided by the Enhancement Progression Calculator.""" data = await self._get_calculator_items( "avatar", lang=lang, is_all=include_traveler, sync=sync, uid=uid, query=query, filters=dict( element_attr_ids=elements or [], weapon_cat_ids=weapon_types or [], ), ) return [models.CalculatorCharacter(**i) for i in data] async def get_calculator_weapons( self, *, query: typing.Optional[str] = None, types: typing.Optional[typing.Sequence[int]] = None, rarities: typing.Optional[typing.Sequence[int]] = None, lang: typing.Optional[str] = None, ) -> typing.Sequence[models.CalculatorWeapon]: """Get all weapons provided by the Enhancement Progression Calculator.""" data = await self._get_calculator_items( "weapon", lang=lang, query=query, filters=dict( weapon_cat_ids=types or [], weapon_levels=rarities or [], ), ) return [models.CalculatorWeapon(**i) for i in data] async def get_calculator_artifacts( self, *, query: typing.Optional[str] = None, pos: int = 1, rarities: typing.Optional[typing.Sequence[int]] = None, lang: typing.Optional[str] = None, ) -> typing.Sequence[models.CalculatorArtifact]: """Get all artifacts provided by the Enhancement Progression Calculator.""" data = await self._get_calculator_items( "reliquary", lang=lang, query=query, filters=dict( reliquary_cat_id=pos, reliquary_levels=rarities or [], ), ) return [models.CalculatorArtifact(**i) for i in data] async def get_calculator_furnishings( self, *, types: typing.Optional[int] = None, rarities: typing.Optional[int] = None, lang: typing.Optional[str] = None, ) -> typing.Sequence[models.CalculatorFurnishing]: """Get all furnishings provided by the Enhancement Progression Calculator.""" data = await self._get_calculator_items( "furniture", lang=lang, filters=dict( cat_id=types or 0, weapon_levels=rarities or 0, ), ) return [models.CalculatorFurnishing(**i) for i in data] async def get_character_details( self, character: types.IDOr[genshin_models.BaseCharacter], *, uid: typing.Optional[int] = None, lang: typing.Optional[str] = None, ) -> models.CalculatorCharacterDetails: """Get the weapon, artifacts and talents of a character. Not related to the Battle Chronicle. This data is always private. """ uid = uid or await self._get_uid(types.Game.GENSHIN) data = await self.request_calculator( "sync/avatar/detail", method="GET", lang=lang, params=dict( avatar_id=int(character), uid=uid, region=utility.recognize_genshin_server(uid), ), ) return models.CalculatorCharacterDetails(**data) async def get_character_talents( self, character: types.IDOr[genshin_models.BaseCharacter], *, lang: typing.Optional[str] = None, ) -> typing.Sequence[models.CalculatorTalent]: """Get the talents of a character. This only gets the talent names, not their levels. Use `get_character_details` for precise information. """ data = await self.request_calculator( "avatar/skill_list", method="GET", lang=lang, params=dict(avatar_id=int(character)), ) return [models.CalculatorTalent(**i) for i in data["list"]] async def get_complete_artifact_set( self, artifact: types.IDOr[typing.Union[genshin_models.Artifact, genshin_models.CalculatorArtifact]], *, lang: typing.Optional[str] = None, ) -> typing.Sequence[models.CalculatorArtifact]: """Get all other artifacts that share a set with any given artifact. Doesn't return the artifact passed into this function. """ data = await self.request_calculator( "reliquary/set", method="GET", lang=lang, params=dict(reliquary_id=int(artifact)), cache=client_cache.cache_key("calculator", slug="set", artifact=int(artifact), lang=lang or self.lang), ) return [models.CalculatorArtifact(**i) for i in data["reliquary_list"]] async def _get_all_artifact_ids(self, artifact_id: int) -> typing.Sequence[int]: """Get all artifact ids in the same set as a given artifact id.""" others = await self.get_complete_artifact_set(artifact_id) return [artifact_id] + [other.id for other in others] async def get_teapot_replica_blueprint( self, share_code: int, *, region: typing.Optional[str] = None, uid: typing.Optional[int] = None, lang: typing.Optional[str] = None, ) -> typing.Sequence[models.CalculatorFurnishing]: """Get furnishings used by a teapot replica blueprint.""" if not region: uid = uid or await self._get_uid(types.Game.GENSHIN) region = utility.recognize_genshin_server(uid) data = await self.request_calculator( "furniture/blueprint", method="GET", lang=lang, params=dict(share_code=share_code, region=region), cache=client_cache.cache_key("calculator", slug="blueprint", share_code=share_code, lang=lang or self.lang), ) return [models.CalculatorFurnishing(**i) for i in data["list"]] @deprecation.deprecated("await genshin.utility.update_characters_any()") async def update_character_names(self, *, lang: typing.Optional[str] = None) -> None: """Update stored db characters with the names from the calculator.""" characters = await self.get_calculator_characters(lang=lang, include_traveler=True) for char in characters: icon = genshin_models.character._parse_icon(char.icon) dbchar = genshin_models.DBChar( char.id, icon, char.name, "" if "Player" in icon else char.element, char.rarity ) genshin_models.CHARACTER_NAMES[lang or self.lang][dbchar.id] = dbchar
Ancestors
- BaseClient
- abc.ABC
Subclasses
Class variables
var logger : logging.Logger
Instance variables
var authkeys : dict[Game, str]
var cache : BaseCache
var custom_headers : multidict._multidict.CIMultiDict[str]
var uids : dict[Game, int]
Methods
def calculator(self, *, lang: typing.Optional[str] = None) ‑> Calculator
-
Create a calculator builder object.
def furnishings_calculator(self, *, lang: typing.Optional[str] = None) ‑> FurnishingCalculator
-
Create a calculator builder object.
async def get_calculator_artifacts(self, *, query: typing.Optional[str] = None, pos: int = 1, rarities: typing.Optional[typing.Sequence[int]] = None, lang: typing.Optional[str] = None) ‑> Sequence[CalculatorArtifact]
-
Get all artifacts provided by the Enhancement Progression Calculator.
async def get_calculator_characters(self, *, query: typing.Optional[str] = None, elements: typing.Optional[typing.Sequence[int]] = None, weapon_types: typing.Optional[typing.Sequence[int]] = None, include_traveler: bool = False, sync: bool = False, uid: typing.Optional[int] = None, lang: typing.Optional[str] = None) ‑> Sequence[CalculatorCharacter]
-
Get all characters provided by the Enhancement Progression Calculator.
async def get_calculator_furnishings(self, *, types: typing.Optional[int] = None, rarities: typing.Optional[int] = None, lang: typing.Optional[str] = None) ‑> Sequence[CalculatorFurnishing]
-
Get all furnishings provided by the Enhancement Progression Calculator.
async def get_calculator_weapons(self, *, query: typing.Optional[str] = None, types: typing.Optional[typing.Sequence[int]] = None, rarities: typing.Optional[typing.Sequence[int]] = None, lang: typing.Optional[str] = None) ‑> Sequence[CalculatorWeapon]
-
Get all weapons provided by the Enhancement Progression Calculator.
async def get_character_details(self, character: types.IDOr[genshin_models.BaseCharacter], *, uid: typing.Optional[int] = None, lang: typing.Optional[str] = None) ‑> CalculatorCharacterDetails
-
Get the weapon, artifacts and talents of a character.
Not related to the Battle Chronicle. This data is always private.
async def get_character_talents(self, character: types.IDOr[genshin_models.BaseCharacter], *, lang: typing.Optional[str] = None) ‑> Sequence[CalculatorTalent]
-
Get the talents of a character.
This only gets the talent names, not their levels. Use
get_character_details
for precise information. async def get_complete_artifact_set(self, artifact: types.IDOr[typing.Union[genshin_models.Artifact, genshin_models.CalculatorArtifact]], *, lang: typing.Optional[str] = None) ‑> Sequence[CalculatorArtifact]
-
Get all other artifacts that share a set with any given artifact.
Doesn't return the artifact passed into this function.
async def get_teapot_replica_blueprint(self, share_code: int, *, region: typing.Optional[str] = None, uid: typing.Optional[int] = None, lang: typing.Optional[str] = None) ‑> Sequence[CalculatorFurnishing]
-
Get furnishings used by a teapot replica blueprint.
async def request_calculator(self, endpoint: str, *, method: str = 'POST', lang: typing.Optional[str] = None, params: typing.Optional[typing.Mapping[str, typing.Any]] = None, data: typing.Optional[typing.Mapping[str, typing.Any]] = None, headers: typing.Optional[aiohttp.typedefs.LooseHeaders] = None, **kwargs: typing.Any) ‑> Mapping[str, Any]
-
Make a request towards the calculator endpoint.
async def update_character_names(self, *, lang: typing.Optional[str] = None) ‑> None
-
Update stored db characters with the names from the calculator.
Warning
This function is deprecated and will be removed in the following version. You can use
await genshin.utility.update_characters_any()
instead.
Inherited members