From 5af9afd474d9357a0a8c0aa58b365d60cb2d5436 Mon Sep 17 00:00:00 2001 From: seriaati Date: Thu, 5 Sep 2024 16:27:16 +0800 Subject: [PATCH] Make wish record time timezone aware --- genshin/client/components/gacha.py | 28 ++++++++++++++-------- genshin/models/genshin/gacha.py | 37 +++++++++++++++--------------- 2 files changed, 38 insertions(+), 27 deletions(-) diff --git a/genshin/client/components/gacha.py b/genshin/client/components/gacha.py index bd41b7bb..64ff90b6 100644 --- a/genshin/client/components/gacha.py +++ b/genshin/client/components/gacha.py @@ -57,7 +57,7 @@ async def _get_gacha_page( game: typing.Optional[types.Game] = None, lang: typing.Optional[str] = None, authkey: typing.Optional[str] = None, - ) -> typing.Sequence[typing.Any]: + ) -> typing.Tuple[typing.Sequence[typing.Any], int]: """Get a single page of wishes.""" data = await self.request_gacha_info( "getGachaLog", @@ -66,7 +66,18 @@ async def _get_gacha_page( authkey=authkey, params=dict(gacha_type=banner_type, real_gacha_type=banner_type, size=20, end_id=end_id), ) - return data["list"] + + if game is types.Game.GENSHIN: + # Genshin doesn't return timezone data + # America: UTC-5, Europe: UTC+1, others are UTC+8 + tz_offsets = {"os_usa": -13, "os_euro": -7} + tz_offset = tz_offsets.get(data["region"], 0) + + tz_offset = data["region_time_zone"] + if game is types.Game.STARRAIL: + tz_offset -= 8 # Star rail returns UTC+n for this value + + return data["list"], tz_offset async def _get_wish_page( self, @@ -77,15 +88,14 @@ async def _get_wish_page( authkey: typing.Optional[str] = None, ) -> typing.Sequence[models.Wish]: """Get a single page of wishes.""" - data = await self._get_gacha_page( + data, tz_offset = await self._get_gacha_page( end_id=end_id, banner_type=banner_type, lang=lang, authkey=authkey, game=types.Game.GENSHIN, ) - - return [models.Wish(**i, banner_type=banner_type) for i in data] + return [models.Wish(**i, banner_type=banner_type, tz_offset=tz_offset) for i in data] async def _get_warp_page( self, @@ -96,7 +106,7 @@ async def _get_warp_page( authkey: typing.Optional[str] = None, ) -> typing.Sequence[models.Warp]: """Get a single page of warps.""" - data = await self._get_gacha_page( + data, tz_offset = await self._get_gacha_page( end_id=end_id, banner_type=banner_type, lang=lang, @@ -104,7 +114,7 @@ async def _get_warp_page( game=types.Game.STARRAIL, ) - return [models.Warp(**i, banner_type=banner_type) for i in data] + return [models.Warp(**i, banner_type=banner_type, tz_offset=tz_offset) for i in data] async def _get_signal_page( self, @@ -115,7 +125,7 @@ async def _get_signal_page( authkey: typing.Optional[str] = None, ) -> typing.Sequence[models.SignalSearch]: """Get a single page of warps.""" - data = await self._get_gacha_page( + data, tz_offset = await self._get_gacha_page( end_id=end_id, banner_type=banner_type, lang=lang, @@ -123,7 +133,7 @@ async def _get_signal_page( game=types.Game.ZZZ, ) - return [models.SignalSearch(**i, banner_type=banner_type) for i in data] + return [models.SignalSearch(**i, banner_type=banner_type, tz_offset=tz_offset) for i in data] def wish_history( self, diff --git a/genshin/models/genshin/gacha.py b/genshin/models/genshin/gacha.py index 551b1cb7..ab75afd1 100644 --- a/genshin/models/genshin/gacha.py +++ b/genshin/models/genshin/gacha.py @@ -85,17 +85,30 @@ class ZZZBannerType(enum.IntEnum): """Bangboo banner.""" -class Wish(APIModel, Unique): - """Wish made on any banner.""" +class BaseWish(APIModel, Unique): + """Base wish model.""" uid: int - id: int - type: str = Aliased("item_type") name: str rarity: int = Aliased("rank_type") + + tz_offset: int + """Number of hours from UTC+8.""" time: datetime.datetime + """Timezone-aware time of when the wish was made""" + + @pydantic.validator("time", pre=True) + def __parse_time(cls, v: str, values: typing.Dict[str, typing.Any]) -> datetime.datetime: + return datetime.datetime.fromisoformat(v).replace( + tzinfo=datetime.timezone(datetime.timedelta(hours=8 + values["tz_offset"])) + ) + +class Wish(BaseWish): + """Wish made on any banner.""" + + type: str = Aliased("item_type") banner_type: GenshinBannerType @pydantic.validator("banner_type", pre=True) @@ -103,17 +116,11 @@ def __cast_banner_type(cls, v: typing.Any) -> int: return int(v) -class Warp(APIModel, Unique): +class Warp(BaseWish): """Warp made on any banner.""" - uid: int - - id: int item_id: int type: str = Aliased("item_type") - name: str - rarity: int = Aliased("rank_type") - time: datetime.datetime banner_type: StarRailBannerType banner_id: int = Aliased("gacha_id") @@ -123,17 +130,11 @@ def __cast_banner_type(cls, v: typing.Any) -> int: return int(v) -class SignalSearch(APIModel, Unique): +class SignalSearch(BaseWish): """Signal Search made on any banner.""" - uid: int - - id: int item_id: int type: str = Aliased("item_type") - name: str - rarity: int = Aliased("rank_type") - time: datetime.datetime banner_type: ZZZBannerType