Files
musicseerr/backend/api/v1/routes/home.py
T
2026-04-03 15:53:00 +01:00

145 lines
5.3 KiB
Python

import logging
from typing import Literal
from fastapi import APIRouter, Depends, Query, HTTPException
from api.v1.schemas.home import (
HomeResponse,
HomeIntegrationStatus,
GenreDetailResponse,
GenreArtistResponse,
GenreArtistsBatchResponse,
TrendingArtistsResponse,
TrendingArtistsRangeResponse,
PopularAlbumsResponse,
PopularAlbumsRangeResponse,
)
from core.dependencies import get_home_service, get_home_charts_service
from infrastructure.degradation import try_get_degradation_context
from infrastructure.msgspec_fastapi import MsgSpecRoute
import msgspec.structs
from services.home_service import HomeService
from services.home_charts_service import HomeChartsService
logger = logging.getLogger(__name__)
router = APIRouter(route_class=MsgSpecRoute, prefix="/home", tags=["home"])
@router.get("", response_model=HomeResponse)
async def get_home_data(
source: Literal["listenbrainz", "lastfm"] | None = Query(default=None, description="Data source: listenbrainz or lastfm"),
home_service: HomeService = Depends(get_home_service),
):
result = await home_service.get_home_data(source=source)
ctx = try_get_degradation_context()
if ctx is not None and ctx.has_degradation():
result = msgspec.structs.replace(result, service_status=ctx.degraded_summary())
return result
@router.get("/integration-status", response_model=HomeIntegrationStatus)
async def get_integration_status(
home_service: HomeService = Depends(get_home_service)
):
return home_service.get_integration_status()
@router.get("/genre/{genre_name}", response_model=GenreDetailResponse)
async def get_genre_detail(
genre_name: str,
limit: int = Query(default=50, ge=1, le=200),
artist_offset: int = Query(default=0, ge=0),
album_offset: int = Query(default=0, ge=0),
charts_service: HomeChartsService = Depends(get_home_charts_service)
):
return await charts_service.get_genre_artists(
genre=genre_name,
limit=limit,
artist_offset=artist_offset,
album_offset=album_offset,
)
@router.get("/trending/artists", response_model=TrendingArtistsResponse)
async def get_trending_artists(
limit: int = Query(default=10, ge=1, le=25),
source: Literal["listenbrainz", "lastfm"] | None = Query(default=None),
charts_service: HomeChartsService = Depends(get_home_charts_service)
):
return await charts_service.get_trending_artists(limit=limit, source=source)
@router.get("/trending/artists/{range_key}", response_model=TrendingArtistsRangeResponse)
async def get_trending_artists_by_range(
range_key: str,
limit: int = Query(default=25, ge=1, le=100),
offset: int = Query(default=0, ge=0),
source: Literal["listenbrainz", "lastfm"] | None = Query(default=None),
charts_service: HomeChartsService = Depends(get_home_charts_service)
):
return await charts_service.get_trending_artists_by_range(
range_key=range_key, limit=limit, offset=offset, source=source
)
@router.get("/popular/albums", response_model=PopularAlbumsResponse)
async def get_popular_albums(
limit: int = Query(default=10, ge=1, le=25),
source: Literal["listenbrainz", "lastfm"] | None = Query(default=None),
charts_service: HomeChartsService = Depends(get_home_charts_service)
):
return await charts_service.get_popular_albums(limit=limit, source=source)
@router.get("/popular/albums/{range_key}", response_model=PopularAlbumsRangeResponse)
async def get_popular_albums_by_range(
range_key: str,
limit: int = Query(default=25, ge=1, le=100),
offset: int = Query(default=0, ge=0),
source: Literal["listenbrainz", "lastfm"] | None = Query(default=None),
charts_service: HomeChartsService = Depends(get_home_charts_service)
):
return await charts_service.get_popular_albums_by_range(
range_key=range_key, limit=limit, offset=offset, source=source
)
@router.get("/your-top/albums", response_model=PopularAlbumsResponse)
async def get_your_top_albums(
limit: int = Query(default=10, ge=1, le=25),
source: Literal["listenbrainz", "lastfm"] | None = Query(default=None),
charts_service: HomeChartsService = Depends(get_home_charts_service)
):
return await charts_service.get_your_top_albums(limit=limit, source=source)
@router.get("/your-top/albums/{range_key}", response_model=PopularAlbumsRangeResponse)
async def get_your_top_albums_by_range(
range_key: str,
limit: int = Query(default=25, ge=1, le=100),
offset: int = Query(default=0, ge=0),
source: Literal["listenbrainz", "lastfm"] | None = Query(default=None),
charts_service: HomeChartsService = Depends(get_home_charts_service)
):
return await charts_service.get_your_top_albums_by_range(
range_key=range_key, limit=limit, offset=offset, source=source
)
@router.get("/genre-artist/{genre_name}", response_model=GenreArtistResponse)
async def get_genre_artist(
genre_name: str,
home_service: HomeService = Depends(get_home_service)
):
artist_mbid = await home_service.get_genre_artist(genre_name)
return GenreArtistResponse(artist_mbid=artist_mbid)
@router.post("/genre-artists", response_model=GenreArtistsBatchResponse)
async def get_genre_artists_batch(
genres: list[str],
home_service: HomeService = Depends(get_home_service)
):
results = await home_service.get_genre_artists_batch(genres)
return GenreArtistsBatchResponse(genre_artists=results)