Implement Bandcamp search service with autocomplete API and HTML scraping fallback. Add /api/bandcamp/search and /api/bandcamp/embed endpoints. Create Listening Room page with search, embedded player, and queue management. Add navigation entry and Bandcamp link on recommendation cards.
59 lines
1.6 KiB
Python
59 lines
1.6 KiB
Python
from fastapi import APIRouter, Depends, HTTPException, Query
|
|
from pydantic import BaseModel
|
|
|
|
from app.core.security import get_current_user
|
|
from app.models.user import User
|
|
from app.services.bandcamp import search_bandcamp, get_embed_data
|
|
|
|
router = APIRouter(prefix="/bandcamp", tags=["bandcamp"])
|
|
|
|
|
|
class BandcampResult(BaseModel):
|
|
title: str
|
|
artist: str
|
|
art_url: str | None = None
|
|
bandcamp_url: str
|
|
item_type: str
|
|
|
|
|
|
class BandcampEmbedResponse(BaseModel):
|
|
embed_url: str
|
|
title: str
|
|
artist: str
|
|
art_url: str | None = None
|
|
|
|
|
|
@router.get("/search", response_model=list[BandcampResult])
|
|
async def bandcamp_search(
|
|
q: str = Query(..., min_length=1),
|
|
type: str = Query("t", pattern="^[tab]$"),
|
|
user: User = Depends(get_current_user),
|
|
):
|
|
"""Search Bandcamp for tracks, albums, or artists."""
|
|
results = await search_bandcamp(q.strip(), item_type=type)
|
|
return [BandcampResult(**r) for r in results]
|
|
|
|
|
|
@router.get("/embed", response_model=BandcampEmbedResponse)
|
|
async def bandcamp_embed(
|
|
url: str = Query(..., min_length=1),
|
|
user: User = Depends(get_current_user),
|
|
):
|
|
"""Get embed data for a Bandcamp URL."""
|
|
if "bandcamp.com" not in url:
|
|
raise HTTPException(status_code=400, detail="Not a valid Bandcamp URL")
|
|
|
|
data = await get_embed_data(url.strip())
|
|
if not data:
|
|
raise HTTPException(
|
|
status_code=404,
|
|
detail="Could not extract embed data from this Bandcamp page",
|
|
)
|
|
|
|
return BandcampEmbedResponse(
|
|
embed_url=data["embed_url"],
|
|
title=data["title"],
|
|
artist=data["artist"],
|
|
art_url=data.get("art_url"),
|
|
)
|