145 lines
5.3 KiB
Python
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)
|