Skip to content

Commit

Permalink
Use DateTimeField
Browse files Browse the repository at this point in the history
  • Loading branch information
seriaati committed Sep 19, 2024
1 parent dc9662d commit cac20dd
Show file tree
Hide file tree
Showing 9 changed files with 56 additions and 91 deletions.
16 changes: 5 additions & 11 deletions genshin/models/genshin/chronicle/abyss.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
import datetime
import typing

import pydantic

from genshin.constants import CN_TIMEZONE
from genshin.models.genshin import character
from genshin.models.model import Aliased, APIModel
from genshin.models.model import Aliased, APIModel, DateTimeField

__all__ = [
"AbyssCharacter",
Expand Down Expand Up @@ -50,7 +48,7 @@ class Battle(APIModel):
"""Battle in the spiral abyss."""

half: int = Aliased("index")
timestamp: datetime.datetime
timestamp: DateTimeField
characters: typing.Sequence[AbyssCharacter] = Aliased("avatars")


Expand Down Expand Up @@ -80,11 +78,11 @@ class SpiralAbyss(APIModel):

unlocked: bool = Aliased("is_unlock")
season: int = Aliased("schedule_id")
start_time: datetime.datetime
end_time: datetime.datetime
start_time: DateTimeField
end_time: DateTimeField

total_battles: int = Aliased("total_battle_times")
total_wins: str = Aliased("total_win_times")
total_wins: int = Aliased("total_win_times")
max_floor: str
total_stars: int = Aliased("total_star")

Expand All @@ -98,10 +96,6 @@ def __nest_ranks(cls, values: typing.Dict[str, typing.Any]) -> typing.Dict[str,
values.setdefault("ranks", {}).update(values)
return values

@pydantic.field_validator("start_time", "end_time", mode="before")
def __parse_timezones(cls, value: str) -> datetime.datetime:
return datetime.datetime.fromtimestamp(int(value), tz=CN_TIMEZONE)


class SpiralAbyssPair(APIModel):
"""Pair of both current and previous spiral abyss.
Expand Down
29 changes: 6 additions & 23 deletions genshin/models/genshin/chronicle/img_theater.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,8 @@

import pydantic

from genshin.constants import CN_TIMEZONE
from genshin.models.genshin import character
from genshin.models.model import Aliased, APIModel
from genshin.models.model import Aliased, APIModel, DateTimeField

__all__ = (
"Act",
Expand Down Expand Up @@ -68,19 +67,11 @@ class Act(APIModel):
medal_obtained: bool = Aliased("is_get_medal")
round_id: int
finish_time: int # As timestamp
finish_datetime: datetime.datetime = Aliased("finish_date_time")
finish_datetime: DateTimeField = Aliased("finish_date_time")

@pydantic.field_validator("finish_datetime", mode="before")
def __parse_datetime(cls, value: typing.Mapping[str, typing.Any]) -> datetime.datetime:
return datetime.datetime(
year=value["year"],
month=value["month"],
day=value["day"],
hour=value["hour"],
minute=value["minute"],
second=value["second"],
tzinfo=CN_TIMEZONE,
)
return datetime.datetime(**value)


class TheaterStats(APIModel):
Expand Down Expand Up @@ -109,20 +100,12 @@ class TheaterSchedule(APIModel):
end_time: int # As timestamp
schedule_type: int # Not sure what this is
id: int = Aliased("schedule_id")
start_datetime: datetime.datetime = Aliased("start_date_time")
end_datetime: datetime.datetime = Aliased("end_date_time")
start_datetime: DateTimeField = Aliased("start_date_time")
end_datetime: DateTimeField = Aliased("end_date_time")

@pydantic.field_validator("start_datetime", "end_datetime", mode="before")
def __parse_datetime(cls, value: typing.Mapping[str, typing.Any]) -> datetime.datetime:
return datetime.datetime(
year=value["year"],
month=value["month"],
day=value["day"],
hour=value["hour"],
minute=value["minute"],
second=value["second"],
tzinfo=CN_TIMEZONE,
)
return datetime.datetime(**value)


class BattleStatCharacter(APIModel):
Expand Down
10 changes: 2 additions & 8 deletions genshin/models/genshin/daily.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,8 @@
import datetime
import typing

import pydantic

from genshin.constants import CN_TIMEZONE
from genshin.models.model import Aliased, APIModel, Unique
from genshin.models.model import Aliased, APIModel, DateTimeField, Unique

__all__ = ["ClaimedDailyReward", "DailyReward", "DailyRewardInfo"]

Expand Down Expand Up @@ -38,8 +36,4 @@ class ClaimedDailyReward(APIModel, Unique):
name: str
amount: int = Aliased("cnt")
icon: str = Aliased("img")
time: datetime.datetime = Aliased("created_at")

@pydantic.field_validator("time")
def __add_timezone(cls, value: datetime.datetime) -> datetime.datetime:
return value.replace(tzinfo=CN_TIMEZONE)
time: DateTimeField = Aliased("created_at")
20 changes: 3 additions & 17 deletions genshin/models/genshin/diary.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,9 @@
"""Genshin diary models."""

import datetime
import enum
import typing

import pydantic

from genshin.constants import CN_TIMEZONE
from genshin.models.model import Aliased, APIModel
from genshin.models.model import Aliased, APIModel, DateTimeField

__all__ = [
"BaseDiary",
Expand Down Expand Up @@ -91,14 +87,9 @@ class DiaryAction(APIModel):

action_id: int
action: str
time: datetime.datetime
time: DateTimeField
amount: int = Aliased("num")

@pydantic.field_validator("time")
@classmethod
def __add_timezone(cls, value: datetime.datetime) -> datetime.datetime:
return value.replace(tzinfo=CN_TIMEZONE)


class DiaryPage(BaseDiary):
"""Page of a diary."""
Expand Down Expand Up @@ -162,14 +153,9 @@ class StarRailDiaryAction(APIModel):

action: str
action_name: str
time: datetime.datetime
time: DateTimeField
amount: int = Aliased("num")

@pydantic.field_validator("time")
@classmethod
def __add_timezone(cls, value: datetime.datetime) -> datetime.datetime:
return value.replace(tzinfo=CN_TIMEZONE)


class StarRailDiaryPage(BaseDiary):
"""Page of a diary."""
Expand Down
5 changes: 2 additions & 3 deletions genshin/models/genshin/lineup.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,12 @@

from __future__ import annotations

import datetime
import typing

import pydantic

from genshin.models.genshin import character
from genshin.models.model import Aliased, APIModel, Unique
from genshin.models.model import Aliased, APIModel, DateTimeField, Unique

__all__ = [
"Lineup",
Expand Down Expand Up @@ -280,7 +279,7 @@ class LineupPreview(APIModel, Unique):

likes: int = Aliased("like_cnt")
comments: int = Aliased("comment_cnt")
created_at: datetime.datetime
created_at: DateTimeField

original_lang: str = Aliased("trans_from")

Expand Down
5 changes: 2 additions & 3 deletions genshin/models/genshin/teapot.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,11 @@

from __future__ import annotations

import datetime
import typing

import pydantic

from genshin.models.model import Aliased, APIModel, Unique
from genshin.models.model import Aliased, APIModel, DateTimeField, Unique

__all__ = [
"TeapotReplica",
Expand Down Expand Up @@ -53,7 +52,7 @@ class TeapotReplica(APIModel, Unique):
title: str
content: str
images: typing.List[str] = Aliased("imgs")
created_at: datetime.datetime
created_at: DateTimeField
stats: TeapotReplicaStats
lang: str # type: ignore

Expand Down
5 changes: 2 additions & 3 deletions genshin/models/genshin/transaction.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
"""Genshin transaction models."""

import datetime
import enum
import typing

from genshin.models.model import Aliased, APIModel, Unique
from genshin.models.model import Aliased, APIModel, DateTimeField, Unique

__all__ = ["BaseTransaction", "ItemTransaction", "Transaction", "TransactionKind"]

Expand Down Expand Up @@ -34,7 +33,7 @@ class BaseTransaction(APIModel, Unique):
kind: TransactionKind

id: int
time: datetime.datetime = Aliased("datetime")
time: DateTimeField = Aliased("datetime")
amount: int = Aliased("add_num")
reason: str = Aliased("reason")

Expand Down
11 changes: 11 additions & 0 deletions genshin/models/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,13 @@
from __future__ import annotations

import abc
import datetime
import typing

import pydantic
from typing_extensions import Annotated

from genshin.constants import CN_TIMEZONE

__all__ = ["APIModel", "Aliased", "Unique"]

Expand Down Expand Up @@ -35,3 +39,10 @@ def Aliased(
) -> typing.Any:
"""Create an aliased field."""
return pydantic.Field(default, alias=alias, **kwargs)


def add_timezone(value: datetime.datetime) -> datetime.datetime:
return value.replace(tzinfo=CN_TIMEZONE)


DateTimeField = Annotated[datetime.datetime, pydantic.AfterValidator(add_timezone)]
46 changes: 23 additions & 23 deletions genshin/models/zzz/chronicle/challenge.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@

import pydantic

from genshin.constants import CN_TIMEZONE
from genshin.models.model import Aliased, APIModel
from genshin.models.model import Aliased, APIModel, DateTimeField
from genshin.models.zzz.character import ZZZElementType

__all__ = (
Expand Down Expand Up @@ -57,9 +56,16 @@ class ShiyuDefenseMonster(APIModel):

id: int
name: str
weakness: ZZZElementType = Aliased("weak_element_type")
weakness: typing.Optional[ZZZElementType] = Aliased("weak_element_type")
level: int

@pydantic.field_validator("weakness", mode="before")
@classmethod
def __parse_weakness(cls, value: int) -> typing.Optional[ZZZElementType]:
if value == 0:
return None
return ZZZElementType(value)


class ShiyuDefenseNode(APIModel):
"""Shiyu Defense node model."""
Expand Down Expand Up @@ -91,46 +97,40 @@ class ShiyuDefenseFloor(APIModel):
buffs: typing.List[ShiyuDefenseBuff]
node_1: ShiyuDefenseNode
node_2: ShiyuDefenseNode
challenge_time: datetime.datetime = Aliased("floor_challenge_time")
challenge_time: DateTimeField = Aliased("floor_challenge_time")
name: str = Aliased("zone_name")

@pydantic.field_validator("challenge_time", mode="before")
@classmethod
def __add_timezone(
cls, v: typing.Dict[typing.Literal["year", "month", "day", "hour", "minute", "second"], int]
) -> datetime.datetime:
return datetime.datetime(
v["year"], v["month"], v["day"], v["hour"], v["minute"], v["second"], tzinfo=CN_TIMEZONE
)
def __parse_datetime(cls, value: typing.Mapping[str, typing.Any]) -> typing.Optional[DateTimeField]:
if value:
return datetime.datetime(**value)
return None


class ShiyuDefense(APIModel):
"""ZZZ Shiyu Defense model."""

schedule_id: int
begin_time: typing.Optional[datetime.datetime] = Aliased("hadal_begin_time")
end_time: typing.Optional[datetime.datetime] = Aliased("hadal_end_time")
begin_time: typing.Optional[DateTimeField] = Aliased("hadal_begin_time")
end_time: typing.Optional[DateTimeField] = Aliased("hadal_end_time")
has_data: bool
ratings: typing.Mapping[typing.Literal["S", "A", "B"], int] = Aliased("rating_list")
floors: typing.List[ShiyuDefenseFloor] = Aliased("all_floor_detail")
fastest_clear_time: int = Aliased("fast_layer_time")
"""Fastest clear time this season in seconds."""
max_floor: int = Aliased("max_layer")

@pydantic.field_validator("begin_time", "end_time", mode="before")
@classmethod
def __parse_datetime(cls, value: typing.Mapping[str, typing.Any]) -> typing.Optional[DateTimeField]:
if value:
return datetime.datetime(**value)
return None

@pydantic.field_validator("ratings", mode="before")
@classmethod
def __convert_ratings(
cls, v: typing.List[typing.Dict[typing.Literal["times", "rating"], typing.Any]]
) -> typing.Mapping[typing.Literal["S", "A", "B"], int]:
return {d["rating"]: d["times"] for d in v}

@pydantic.field_validator("begin_time", "end_time", mode="before")
@classmethod
def __add_timezone(
cls, v: typing.Optional[typing.Dict[typing.Literal["year", "month", "day", "hour", "minute", "second"], int]]
) -> typing.Optional[datetime.datetime]:
if v is not None:
return datetime.datetime(
v["year"], v["month"], v["day"], v["hour"], v["minute"], v["second"], tzinfo=CN_TIMEZONE
)
return None

0 comments on commit cac20dd

Please sign in to comment.