Рефактор

This commit is contained in:
2025-11-26 11:59:35 +03:00
parent c3b4602ed1
commit 5510f85d94
4 changed files with 279 additions and 759 deletions

View File

@ -12,278 +12,34 @@ class osuAPIClient(AioHTTPXClient):
redis_url: str,
client_id: str,
client_secret: str,
callback_url: str,
redirect_uri: str,
):
self.base_uri = 'https://osu.ppy.sh/api/v2'
self.client_id = client_id
self.client_secret = client_secret
self.callback_url = callback_url
self.redirect_uri = redirect_uri
super().__init__(
base_url=self.base_uri,
redis_url=redis_url,
key='osu',
limit=10,
limit=1200,
logger='osu! API',
)
async def get_beatmap_favorites(
self, access_token: str, cache_time: int | None = None
):
req = await self.get(
'/me/beatmapset-favourites',
headers=self.clean_dict(
{
'Authorization': f'Bearer {access_token}',
'X-Cache-TTL': cache_time,
}
),
)
match req.status_code:
case st.OK:
return s.FavoriteBeatmaps.model_validate(req.json())
case st.UNAUTHORIZED:
raise s.Error(req.status_code, 'Unauthorized')
case _:
self.logger.error(req.text)
raise s.Error(500, 'Internal Server Error')
async def get_beatmap_packs(
self,
access_token: str,
packs_type: Literal[
'standard',
'featured',
'tournament',
'loved',
'chart',
'theme',
'artist',
] = 'standard',
cursor_string: str | None = None,
cache_time: int | None = None,
):
req = await self.get(
'/beatmaps/packs',
params=self.clean_dict(
{'type': packs_type, 'cursor_string': cursor_string}
),
headers=self.clean_dict(
{
'Authorization': f'Bearer {access_token}',
'X-Cache-TTL': cache_time,
}
),
)
match req.status_code:
case st.OK:
return s.BeatmapPacks.model_validate(req.json())
case st.UNAUTHORIZED:
raise s.Error(req.status_code, 'Unauthorized')
case _:
self.logger.error(req.text)
raise s.Error(500, 'Internal Server Error')
async def get_beatmap_pack(
self,
access_token: str,
pack: str,
legacy_only: int = 0,
cache_time: int | None = None,
):
req = await self.get(
f'/beatmaps/packs/{pack}',
params=self.clean_dict({'legacy_only': legacy_only}),
headers=self.clean_dict(
{
'Authorization': f'Bearer {access_token}',
'X-Cache-TTL': cache_time,
}
),
)
match req.status_code:
case st.OK:
return s.BeatmapPack.model_validate(req.json())
case st.UNAUTHORIZED:
raise s.Error(req.status_code, 'Unauthorized')
case st.NOT_FOUND:
raise s.Error(req.status_code, 'Not Found')
case _:
self.logger.error(req.text)
raise s.Error(500, 'Internal Server Error')
async def lookup_beatmap(
self,
access_token: str,
checksum: str | None = None,
filename: str | None = None,
beatmap_id: int | None = None,
cache_time: int | None = None,
):
req = await self.get(
'/beatmaps/lookup',
params=self.clean_dict(
{
'checksum': checksum,
'filename': filename,
'beatmap_id': beatmap_id,
}
),
headers=self.clean_dict(
{
'Authorization': f'Bearer {access_token}',
'X-Cache-TTL': cache_time,
}
),
)
match req.status_code:
case st.OK:
return s.BeatmapExtended.model_validate(req.json())
case st.UNAUTHORIZED:
raise s.Error(req.status_code, 'Unauthorized')
case st.NOT_FOUND:
raise s.Error(req.status_code, 'Not Found')
case _:
self.logger.error(req.text)
raise s.Error(500, 'Internal Server Error')
async def get_user_beatmap_score(
self,
access_token: str,
beatmap: int,
user: int,
cache_time: int | None = None,
):
req = await self.get(
f'/beatmaps/{beatmap}/scores/users/{user}',
headers=self.clean_dict(
{
'Authorization': f'Bearer {access_token}',
'X-Cache-TTL': cache_time,
}
),
)
match req.status_code:
case st.OK:
return s.BeatmapUserScore.model_validate(req.json())
case st.UNAUTHORIZED:
raise s.Error(req.status_code, 'Unauthorized')
case st.NOT_FOUND:
raise s.Error(req.status_code, 'Not Found')
case _:
self.logger.error(req.text)
raise s.Error(500, 'Internal Server Error')
async def get_user_beatmap_scores(
self,
access_token: str,
beatmap: int,
user: int,
legacy_only: int = 0,
ruleset: Literal['fruits', 'mania', 'osu', 'taiko'] | None = None,
cache_time: int | None = None,
):
req = await self.get(
f'/beatmaps/{beatmap}/scores/users/{user}/all',
params=self.clean_dict(
{'legacy_only': legacy_only, 'ruleset': ruleset}
),
headers=self.clean_dict(
{
'Authorization': f'Bearer {access_token}',
'X-Cache-TTL': cache_time,
}
),
)
match req.status_code:
case st.OK:
return s.UserBeatmapScores.model_validate(req.json())
case st.UNAUTHORIZED:
raise s.Error(req.status_code, 'Unauthorized')
case st.NOT_FOUND:
raise s.Error(req.status_code, 'Not Found')
case _:
self.logger.error(req.text)
raise s.Error(500, 'Internal Server Error')
async def get_beatmap_scores(
self,
access_token: str,
beatmap: int,
legacy_only: int = 0,
mode: Literal['fruits', 'mania', 'osu', 'taiko'] | None = None,
mods: str | None = None,
ranking_type: str | None = None,
cache_time: int | None = None,
):
req = await self.get(
f'/beatmaps/{beatmap}/scores',
params=self.clean_dict(
{
'legacy_only': legacy_only,
'mode': mode,
'mods': mods,
'ranking_type': ranking_type,
}
),
headers=self.clean_dict(
{
'Authorization': f'Bearer {access_token}',
'X-Cache-TTL': cache_time,
}
),
)
match req.status_code:
case st.OK:
return s.BeatmapScores.model_validate(req.json())
case st.UNAUTHORIZED:
raise s.Error(req.status_code, 'Unauthorized')
case _:
self.logger.error(req.text)
raise s.Error(500, 'Internal Server Error')
# TODO: implement endpoints
# https://osu.ppy.sh/docs/index.html#get-beatmaps
async def get_user_scores(
self,
access_token: str,
user: int,
score_type: Literal['best', 'firsts', 'recent'],
legacy_only: int = 0,
include_fails: int = 0,
user_id: int,
score_type: Literal['best', 'recent', 'firsts'],
legacy_only: Literal[0, 1] = 0,
include_fails: Literal[0, 1] = 0,
mode: Literal['fruits', 'mania', 'osu', 'taiko'] | None = None,
limit: int | None = None,
offset: int | None = None,
cache_time: int | None = None,
offset: str | None = None,
):
req = await self.get(
f'/users/{user}/scores/{score_type}',
f'/users/{user_id}/scores/{score_type}',
params=self.clean_dict(
{
'legacy_only': legacy_only,
@ -296,7 +52,6 @@ class osuAPIClient(AioHTTPXClient):
headers=self.clean_dict(
{
'Authorization': f'Bearer {access_token}',
'X-Cache-TTL': cache_time,
}
),
)
@ -315,9 +70,6 @@ class osuAPIClient(AioHTTPXClient):
self.logger.error(req.text)
raise s.Error(500, 'Internal Server Error')
# TODO: implement other endpoints
# https://osu.ppy.sh/docs/index.html#get-user-beatmaps
async def get_user(
self,
access_token: str,
@ -342,7 +94,7 @@ class osuAPIClient(AioHTTPXClient):
match req.status_code:
case st.OK:
return s.GetUserSchema.model_validate(req.json())
return s.GetUser.model_validate(req.json())
case st.NOT_FOUND:
raise s.Error(req.status_code, 'Not Found')