604 lines
12 KiB
Python
604 lines
12 KiB
Python
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
|