from datetime import datetime from typing import Literal from pydantic import BaseModel, Field class Error(Exception): status_code: int error: str def __init__(self, status_code: int, error: str) -> None: self.status_code = status_code self.error = error super().__init__(f'{status_code}: {error}') class Token(BaseModel): access_token: str expires_in: int token_type: Literal['Bearer'] class UserToken(Token): refresh_token: str class Country(BaseModel): code: str name: str class Beatmap(BaseModel): beatmapset_id: int difficulty_rating: float id: int mode: Literal['fruits', 'mania', 'osu', 'taiko'] status: int total_length: int user_id: int version: str class BeatmapDifficultyAttributes(BaseModel): star_rating: float max_combo: int class osuBeatmapDifficultyAttributes(BeatmapDifficultyAttributes): aim_difficulty: float aim_difficult_slider_count: float speed_difficulty: float speed_note_count: float slider_factor: float aim_difficult_strain_count: float speed_difficult_strain_count: float class taikoBeatmapDifficultyAttributes(BeatmapDifficultyAttributes): mono_stamina_factor: float class BeatmapExtended(Beatmap): accuracy: float ar: float beatmapset_id: int bpm: float | None = None convert: bool count_circles: int count_sliders: int count_spinners: int cs: float deleted_at: datetime | None = None drain: float hit_length: int is_scoreable: bool last_updated: datetime mode_int: int passcount: int playcount: int ranked: int url: str class BeatmapOwner(BaseModel): id: int username: str class UserCompletionData(BaseModel): beatmapset_ids: list[int] completed: bool class BeatmapPack(BaseModel): author: str date: datetime name: str no_diff_reduction: bool ruleset_id: int | None tag: str url: str class BeatmapPlaycount(BaseModel): beatmap_id: int beatmap: 'Beatmap | None' = None beatmapset: 'Beatmapset | None' = None count: int class BeatmapScores(BaseModel): scores: list['Score'] userScore: 'BeatmapUserScore | None' = None class BeatmapUserScore(BaseModel): position: int score: 'Score' class Beatmapset(BaseModel): artist: str artist_unicode: str covers: 'Covers' creator: str favourite_count: int id: int nsfw: bool offset: int play_count: int preview_url: str source: str status: str spotlight: bool title: str title_unicode: str user_id: int video: bool class Covers(BaseModel): cover: str cover_2x: str = Field(alias='cover@2x') card: str card_2x: str = Field(alias='card@2x') list: str list_2x: str = Field(alias='list@2x') slimcover: str slimcover_2x: str = Field(alias='slimcover@2x') class BeatmapsetDiscussion(BaseModel): beatmap: 'Beatmap | None' = None beatmap_id: int | None = None beatmapset: 'Beatmapset | None' = None beatmapset_id: int can_be_resolved: bool can_grant_kudosu: bool created_at: datetime current_user_attributes: 'CurrentUserAttributes' deleted_at: datetime | None = None deleted_by_id: int | None = None id: int kudosu_denied: bool last_post_at: datetime message_type: Literal[ 'hype', 'mapper_note', 'praise', 'problem', 'review', 'suggestion' ] parent_id: int | None = None posts: list['BeatmapsetDiscussionPost'] timestamp: int | None = None updated_at: datetime | None = None user_id: int class BeatmapsetDiscussionPost(BaseModel): beatmapset_discussion_id: int created_at: datetime deleted_at: datetime | None = None deleted_by_id: int | None = None id: int last_editor_id: int | None = None message: str system: bool updated_at: datetime | None = None user_id: int class BeatmapsetDiscussionVote(BaseModel): beatmapset_discussion_id: int created_at: datetime id: int score: int updated_at: datetime user_id: int class BeatmapsetAvailability(BaseModel): download_disabled: bool more_information: str | None = None class BeatmapsetHype(BaseModel): current: int required: int class BeatmapsetNominationsSummary(BaseModel): current: int required: int class BeatmapsetExtended(Beatmapset): availability: BeatmapsetAvailability bpm: float can_be_hyped: float deleted_at: datetime | None = None discussion_enabled: bool discussion_locked: bool hype: BeatmapsetHype is_scoreable: bool last_updated: datetime legacy_thread_url: str | None = None nominations_summary: BeatmapsetNominationsSummary ranked: int ranked_date: datetime | None = None rating: float source: str storyboard: bool submitted_date: datetime | None = None tags: str class Build(BaseModel): created_at: datetime display_version: str id: int update_stream: 'UpdateStream | None' = None users: int version: str | None = None youtube_id: str | None = None class Versions(BaseModel): next: Build | None = None previous: Build | None = None class ChangelogEntry(BaseModel): category: str created_at: datetime github_pull_request_id: int | None = None github_url: str | None = None id: int | None = None major: bool repository_url: str | None = None title: str | None = None entry_type: str = Field(alias='type') url: str | None = None class ChatChannel(BaseModel): channel_id: int name: str description: str | None = None icon: str | None = None channel_type: Literal[ 'PUBLIC', 'PRIVATE', 'MULTIPLAYER', 'SPECTATOR', 'TEMPORARY', 'PM', 'GROUP', 'ANNOUNCE', ] = Field(alias='type') message_length_limit: int moderated: bool uuid: str | None = None class ChatMessage(BaseModel): channel_id: int content: str is_action: bool message_id: int sender_id: int timestamp: datetime message_type: str = Field(alias='type') uuid: str | None = None class Comment(BaseModel): pass class CommentBundle(BaseModel): pass class CommentSort(BaseModel): pass class CommentableMeta(BaseModel): pass class CurrentUserAttributes(BaseModel): pass class Event(BaseModel): pass class Forum(BaseModel): pass class ForumPost(BaseModel): pass class ForumTopic(BaseModel): pass class GithubUser(BaseModel): pass class Group(BaseModel): pass class KudosuHistory(BaseModel): pass class Match(BaseModel): pass class MatchEvent(BaseModel): pass class MatchGame(BaseModel): pass class MultiplayerScores(BaseModel): pass class MultiplayerScoresAroundUser(BaseModel): pass class MultiplayerScoresCursor(BaseModel): pass class MultiplayerScoresSort(BaseModel): pass class NewsPost(BaseModel): pass class Nomination(BaseModel): pass class Notification(BaseModel): pass class RankingType(BaseModel): pass class Rankings(BaseModel): pass class Score(BaseModel): accuracy: float beatmap_id: int | None = None best_id: int | None = None build_id: int | None = None classic_total_score: int | None = None ended_at: datetime | None = None has_replay: bool | None = None id: int is_perfect_combo: bool | None = None legacy_perfect: bool | None = None legacy_score_id: int | None = None legacy_total_score: int | None = None max_combo: int maximum_statistics: 'ScoreStatistics | None' = None mods: list[str] passed: bool playlist_item_id: int | None = None pp: float | None = None preserve: bool | None = None processed: bool | None = None rank: str ranked: bool | None = None room_id: int | None = None ruleset_id: int | None = None started_at: datetime | None = None statistics: 'ScoreStatistics' total_score: int | None = None type: str user_id: int class ScoreStatistics(BaseModel): pass class Spotlight(BaseModel): pass class Spotlights(BaseModel): spotlights: list[Spotlight] class UpdateStream(BaseModel): pass class UserAccountHistory(BaseModel): description: str | None = None id: int length: int permanent: bool timestamp: datetime type: Literal['note', 'restriction', 'silence'] class ProfileBanner(BaseModel): id: int tournament_id: int image: str | None = None image_2x: str | None = Field(alias='image@2x') class UserBadge(BaseModel): awarded_at: datetime description: str image_2x_url: str = Field(alias='image@2x_url') image_url: str url: str class UserKudosu(BaseModel): available: int total: int class UserRankHighest(BaseModel): rank: int updated_at: datetime class UserMonthlyPlaycount(BaseModel): start_date: datetime count: int class User(BaseModel): avatar_url: str | None = None country_code: str default_group: str | None = None id: int is_active: bool is_bot: bool is_deleted: bool is_online: bool is_supporter: bool last_visit: datetime | None = None pm_friends_only: bool profile_colour: str | None = None username: str class UserExtended(User): discord: str | None = None has_supported: bool interests: str | None = None join_date: datetime location: str | None = None max_blocks: int max_friends: int occupation: str | None = None playmode: Literal['osu', 'taiko', 'fruits', 'mania'] playstyle: list[str] post_count: int profile_hue: int | None = None profile_order: list[str] title: str | None = None title_url: str | None = None twitter: str | None = None website: str | None = None class UserGroup(BaseModel): pass class UserSilence(BaseModel): pass class UserStatisticsGradeCounts(BaseModel): a: int s: int sh: int ss: int ssh: int class UserStatisticsLevel(BaseModel): current: int progress: float class UserStatistics(BaseModel): count_100: int count_300: int count_50: int count_miss: int country_rank: int | None = None grade_counts: UserStatisticsGradeCounts hit_accuracy: float is_ranked: bool level: UserStatisticsLevel maximum_combo: int play_count: int play_time: int pp: float global_rank: int | None = None global_rank_exp: int | None = None ranked_score: int replays_watched_by_others: int total_hits: int total_score: int class WikiPage(BaseModel): pass class FavoriteBeatmaps(BaseModel): beatmapset_ids: list[int] class BeatmapPacks(BaseModel): beatmap_packs: list[BeatmapPack] class UserBeatmapScores(BaseModel): scores: list['Score'] class GetUserSchema(UserExtended): account_history: list[UserAccountHistory] active_tournament_banners: list[ProfileBanner] badges: list[UserBadge] beatmap_playcounts_count: int country: Country # cover favourite_beatmapset_count: int follow_user_mapping: list[int] follower_count: int graveyard_beatmapset_count: int groups: list[UserGroup] guest_beatmapset_count: int is_restricted: bool | None = None kudosu: UserKudosu loved_beatmapset_count: int mapping_follower_count: int monthly_playcounts: list[UserMonthlyPlaycount] nominated_beatmapset_count: int # page pending_beatmapset_count: int previous_usernames: list[str] rank_highest: UserRankHighest | None = None # rank_history ranked_beatmapset_count: int # replays_watched_counts scores_best_count: int scores_first_count: int scores_recent_count: int session_verified: bool statistics: UserStatistics support_level: int # user_achievements