Релиз 0.1
This commit is contained in:
319
src/osuclient/api.py
Normal file
319
src/osuclient/api.py
Normal file
@ -0,0 +1,319 @@
|
||||
from typing import Literal
|
||||
|
||||
from aiohttpx import status as st
|
||||
from aiohttpx.client import AioHTTPXClient
|
||||
|
||||
from . import schema as s
|
||||
|
||||
|
||||
class osuAPIClient(AioHTTPXClient):
|
||||
def __init__(
|
||||
self,
|
||||
redis_url: str,
|
||||
client_id: str,
|
||||
client_secret: str,
|
||||
callback_url: 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
|
||||
|
||||
super().__init__(
|
||||
base_url=self.base_uri,
|
||||
redis_url=redis_url,
|
||||
key='osu',
|
||||
limit=10,
|
||||
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,
|
||||
mode: Literal['fruits', 'mania', 'osu', 'taiko'] | None = None,
|
||||
limit: int | None = None,
|
||||
offset: int | None = None,
|
||||
cache_time: int | None = None,
|
||||
):
|
||||
req = await self.get(
|
||||
f'/users/{user}/scores/{score_type}',
|
||||
params=self.clean_dict(
|
||||
{
|
||||
'legacy_only': legacy_only,
|
||||
'include_fails': include_fails,
|
||||
'mode': mode,
|
||||
'limit': limit,
|
||||
'offset': offset,
|
||||
}
|
||||
),
|
||||
headers=self.clean_dict(
|
||||
{
|
||||
'Authorization': f'Bearer {access_token}',
|
||||
'X-Cache-TTL': cache_time,
|
||||
}
|
||||
),
|
||||
)
|
||||
|
||||
match req.status_code:
|
||||
case st.OK:
|
||||
return [s.Score.model_validate(score) for score in req.json()]
|
||||
|
||||
case st.NOT_FOUND:
|
||||
raise s.Error(req.status_code, 'Not Found')
|
||||
|
||||
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 other endpoints
|
||||
# https://osu.ppy.sh/docs/index.html#get-user-beatmaps
|
||||
Reference in New Issue
Block a user