Files
bancho.py/app/api/v2/players.py
2025-04-04 21:30:31 +09:00

138 lines
3.8 KiB
Python

"""bancho.py's v2 apis for interacting with players"""
from __future__ import annotations
from fastapi import APIRouter
from fastapi import status
from fastapi.param_functions import Query
import app.state.sessions
from app.api.v2.common import responses
from app.api.v2.common.responses import Failure
from app.api.v2.common.responses import Success
from app.api.v2.models.players import Player
from app.api.v2.models.players import PlayerStats
from app.api.v2.models.players import PlayerStatus
from app.repositories import stats as stats_repo
from app.repositories import users as users_repo
router = APIRouter()
@router.get("/players")
async def get_players(
priv: int | None = None,
country: str | None = None,
clan_id: int | None = None,
clan_priv: int | None = None,
preferred_mode: int | None = None,
play_style: int | None = None,
page: int = Query(1, ge=1),
page_size: int = Query(50, ge=1, le=100),
) -> Success[list[Player]] | Failure:
players = await users_repo.fetch_many(
priv=priv,
country=country,
clan_id=clan_id,
clan_priv=clan_priv,
preferred_mode=preferred_mode,
play_style=play_style,
page=page,
page_size=page_size,
)
total_players = await users_repo.fetch_count(
priv=priv,
country=country,
clan_id=clan_id,
clan_priv=clan_priv,
preferred_mode=preferred_mode,
play_style=play_style,
)
response = [Player.from_mapping(rec) for rec in players]
return responses.success(
content=response,
meta={
"total": total_players,
"page": page,
"page_size": page_size,
},
)
@router.get("/players/{player_id}")
async def get_player(player_id: int) -> Success[Player] | Failure:
data = await users_repo.fetch_one(id=player_id)
if data is None:
return responses.failure(
message="Player not found.",
status_code=status.HTTP_404_NOT_FOUND,
)
response = Player.from_mapping(data)
return responses.success(response)
@router.get("/players/{player_id}/status")
async def get_player_status(player_id: int) -> Success[PlayerStatus] | Failure:
player = app.state.sessions.players.get(id=player_id)
if not player:
return responses.failure(
message="Player status not found.",
status_code=status.HTTP_404_NOT_FOUND,
)
response = PlayerStatus(
login_time=int(player.login_time),
action=int(player.status.action),
info_text=player.status.info_text,
mode=int(player.status.mode),
mods=int(player.status.mods),
beatmap_id=player.status.map_id,
)
return responses.success(response)
@router.get("/players/{player_id}/stats/{mode}")
async def get_player_mode_stats(
player_id: int,
mode: int,
) -> Success[PlayerStats] | Failure:
data = await stats_repo.fetch_one(player_id, mode)
if data is None:
return responses.failure(
message="Player stats not found.",
status_code=status.HTTP_404_NOT_FOUND,
)
response = PlayerStats.from_mapping(data)
return responses.success(response)
@router.get("/players/{player_id}/stats")
async def get_player_stats(
player_id: int,
page: int = Query(1, ge=1),
page_size: int = Query(50, ge=1, le=100),
) -> Success[list[PlayerStats]] | Failure:
data = await stats_repo.fetch_many(
player_id=player_id,
page=page,
page_size=page_size,
)
total_stats = await stats_repo.fetch_count(
player_id=player_id,
)
response = [PlayerStats.from_mapping(rec) for rec in data]
return responses.success(
response,
meta={
"total": total_stats,
"page": page,
"page_size": page_size,
},
)