From 722f99f94ae896f1036cf36796a27358b956c606 Mon Sep 17 00:00:00 2001 From: Miwory Date: Wed, 26 Nov 2025 23:57:26 +0300 Subject: [PATCH] =?UTF-8?q?=D0=9F=D0=BE=D0=BF=D1=8B=D1=82=D0=BA=D0=B0=20?= =?UTF-8?q?=D1=84=D0=B8=D0=BA=D1=81=D0=B0=20=D0=BA=D0=BE=D0=B4=D0=B8=D1=80?= =?UTF-8?q?=D0=BE=D0=B2=D0=BA=D0=B8=20dt?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pyproject.toml | 2 +- src/osuclient/schema.py | 131 +++++++++++----------------------------- 2 files changed, 37 insertions(+), 96 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index fd9ff2e..cd21e03 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "osuclient" -version = "0.5.3" +version = "0.5.4" description = "Client for osu! API" readme = "README.md" authors = [ diff --git a/src/osuclient/schema.py b/src/osuclient/schema.py index 08b1e5a..e7f8faa 100644 --- a/src/osuclient/schema.py +++ b/src/osuclient/schema.py @@ -24,24 +24,25 @@ class UserToken(Token): refresh_token: str -class Country(BaseModel): - model_config = ConfigDict(extra='forbid', json_encoders={datetime: str}) +class CustomModel(BaseModel): + model_config = ConfigDict( + extra='forbid', + json_encoders={datetime: lambda dt: dt.isoformat() if dt else None}, + ) + +class Country(CustomModel): code: str name: str -class Cover(BaseModel): - model_config = ConfigDict(extra='forbid', json_encoders={datetime: str}) - +class Cover(CustomModel): custom_url: str | None url: str id: int | None -class DailyChallengeUserStats(BaseModel): - model_config = ConfigDict(extra='forbid', json_encoders={datetime: str}) - +class DailyChallengeUserStats(CustomModel): daily_streak_best: int daily_streak_current: int last_update: str @@ -54,51 +55,37 @@ class DailyChallengeUserStats(BaseModel): weekly_streak_current: int -class MonthlyPlaycount(BaseModel): - model_config = ConfigDict(extra='forbid', json_encoders={datetime: str}) - +class MonthlyPlaycount(CustomModel): start_date: str count: int -class Page(BaseModel): - model_config = ConfigDict(extra='forbid', json_encoders={datetime: str}) - +class Page(CustomModel): html: str raw: str -class RankHighest(BaseModel): - model_config = ConfigDict(extra='forbid', json_encoders={datetime: str}) - +class RankHighest(CustomModel): rank: int updated_at: str -class Kudosu(BaseModel): - model_config = ConfigDict(extra='forbid', json_encoders={datetime: str}) - +class Kudosu(CustomModel): available: int total: int -class ReplaysWatchedCount(BaseModel): - model_config = ConfigDict(extra='forbid', json_encoders={datetime: str}) - +class ReplaysWatchedCount(CustomModel): start_date: str count: int -class Level(BaseModel): - model_config = ConfigDict(extra='forbid', json_encoders={datetime: str}) - +class Level(CustomModel): current: int progress: int -class GradeCounts(BaseModel): - model_config = ConfigDict(extra='forbid', json_encoders={datetime: str}) - +class GradeCounts(CustomModel): ss: int ssh: int s: int @@ -106,15 +93,11 @@ class GradeCounts(BaseModel): a: int -class Rank(BaseModel): - model_config = ConfigDict(extra='forbid', json_encoders={datetime: str}) - +class Rank(CustomModel): country: int -class UserStatistics(BaseModel): - model_config = ConfigDict(extra='forbid', json_encoders={datetime: str}) - +class UserStatistics(CustomModel): count_100: int count_300: int count_50: int @@ -139,32 +122,24 @@ class UserStatistics(BaseModel): rank: Rank -class UserAchievement(BaseModel): - model_config = ConfigDict(extra='forbid', json_encoders={datetime: str}) - +class UserAchievement(CustomModel): achieved_at: str achievement_id: int -class RankHistory(BaseModel): - model_config = ConfigDict(extra='forbid', json_encoders={datetime: str}) - +class RankHistory(CustomModel): mode: Literal['osu', 'taiko', 'fruits', 'mania'] data: list[int] -class ActiveTournamentBanner(BaseModel): - model_config = ConfigDict(extra='forbid', json_encoders={datetime: str}) - +class ActiveTournamentBanner(CustomModel): id: int tournament_id: int image: str image_2x: str = Field(alias='image@2x') -class Badge(BaseModel): - model_config = ConfigDict(extra='forbid', json_encoders={datetime: str}) - +class Badge(CustomModel): awarded_at: datetime description: str image_2x_url: str = Field(alias='image@2x_url') @@ -172,18 +147,14 @@ class Badge(BaseModel): url: str -class Team(BaseModel): - model_config = ConfigDict(extra='forbid', json_encoders={datetime: str}) - +class Team(CustomModel): id: int name: str short_name: str flag_url: str -class ScoreStatistics(BaseModel): - model_config = ConfigDict(extra='forbid', json_encoders={datetime: str}) - +class ScoreStatistics(CustomModel): count_100: int count_300: int count_50: int @@ -192,15 +163,11 @@ class ScoreStatistics(BaseModel): count_miss: int -class CurrentUserAttributes(BaseModel): - model_config = ConfigDict(extra='forbid', json_encoders={datetime: str}) - +class CurrentUserAttributes(CustomModel): pin: None -class Covers(BaseModel): - model_config = ConfigDict(extra='forbid', json_encoders={datetime: str}) - +class Covers(CustomModel): cover: str cover_2x: str = Field(..., alias='cover@2x') card: str @@ -211,9 +178,7 @@ class Covers(BaseModel): slimcover_2x: str = Field(..., alias='slimcover@2x') -class Beatmapset(BaseModel): - model_config = ConfigDict(extra='forbid', json_encoders={datetime: str}) - +class Beatmapset(CustomModel): anime_cover: bool artist: str artist_unicode: str @@ -238,9 +203,7 @@ class Beatmapset(BaseModel): video: bool -class User(BaseModel): - model_config = ConfigDict(extra='forbid', json_encoders={datetime: str}) - +class User(CustomModel): avatar_url: str country_code: str default_group: str @@ -260,38 +223,28 @@ class User(BaseModel): groups: list[str] | None = None -class Weight(BaseModel): - model_config = ConfigDict(extra='forbid', json_encoders={datetime: str}) - +class Weight(CustomModel): percentage: float pp: float -class BeatmapsetAvailability(BaseModel): - model_config = ConfigDict(extra='forbid', json_encoders={datetime: str}) - +class BeatmapsetAvailability(CustomModel): download_disabled: bool more_information: str | None -class BeatmapsetNominationsSummaryRequiredMeta(BaseModel): - model_config = ConfigDict(extra='forbid', json_encoders={datetime: str}) - +class BeatmapsetNominationsSummaryRequiredMeta(CustomModel): main_ruleset: int non_main_ruleset: int -class BeatmapsetNominationsSummary(BaseModel): - model_config = ConfigDict(extra='forbid', json_encoders={datetime: str}) - +class BeatmapsetNominationsSummary(CustomModel): current: int eligible_main_rulesets: list[str] required_meta: BeatmapsetNominationsSummaryRequiredMeta class BeatmapsetExtended(Beatmapset): - model_config = ConfigDict(extra='forbid', json_encoders={datetime: str}) - bpm: float can_be_hyped: bool deleted_at: datetime | None @@ -311,23 +264,17 @@ class BeatmapsetExtended(Beatmapset): nominations_summary: BeatmapsetNominationsSummary -class BeatmapOwner(BaseModel): - model_config = ConfigDict(extra='forbid', json_encoders={datetime: str}) - +class BeatmapOwner(CustomModel): id: int username: str -class BeatmapFailtimes(BaseModel): - model_config = ConfigDict(extra='forbid', json_encoders={datetime: str}) - +class BeatmapFailtimes(CustomModel): fail: list[int] exit: list[int] -class Beatmap(BaseModel): - model_config = ConfigDict(extra='forbid', json_encoders={datetime: str}) - +class Beatmap(CustomModel): beatmapset_id: int difficulty_rating: float id: int @@ -361,8 +308,6 @@ class Beatmap(BaseModel): class BeatmapExtended(Beatmap): - model_config = ConfigDict(extra='forbid', json_encoders={datetime: str}) - beatmapset: BeatmapsetExtended max_combo: int # type: ignore current_user_playcount: int @@ -370,9 +315,7 @@ class BeatmapExtended(Beatmap): failtimes: BeatmapFailtimes -class Score(BaseModel): - model_config = ConfigDict(extra='forbid', json_encoders={datetime: str}) - +class Score(CustomModel): accuracy: float best_id: int | None created_at: str @@ -399,8 +342,6 @@ class Score(BaseModel): class GetUser(User): - model_config = ConfigDict(extra='forbid', json_encoders={datetime: str}) - cover_url: str discord: str | None has_supported: bool