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

176 lines
5.5 KiB
Python

import logging
from fastapi import APIRouter, Response
from api.v1.schemas.discover import YouTubeQuotaResponse
from api.v1.schemas.youtube import (
YouTubeLink,
YouTubeLinkGenerateRequest,
YouTubeLinkResponse,
YouTubeLinkUpdateRequest,
YouTubeManualLinkRequest,
YouTubeTrackLink,
YouTubeTrackLinkBatchGenerateRequest,
YouTubeTrackLinkBatchResponse,
YouTubeTrackLinkGenerateRequest,
YouTubeTrackLinkResponse,
)
from core.dependencies import YouTubeServiceDep
from infrastructure.msgspec_fastapi import MsgSpecBody, MsgSpecRoute
logger = logging.getLogger(__name__)
router = APIRouter(route_class=MsgSpecRoute, prefix="/youtube", tags=["YouTube"])
@router.post("/generate", response_model=YouTubeLinkResponse)
async def generate_link(
youtube_service: YouTubeServiceDep,
request: YouTubeLinkGenerateRequest = MsgSpecBody(YouTubeLinkGenerateRequest),
) -> YouTubeLinkResponse:
link = await youtube_service.generate_link(
artist_name=request.artist_name,
album_name=request.album_name,
album_id=request.album_id,
cover_url=request.cover_url,
)
quota = youtube_service.get_quota_status()
return YouTubeLinkResponse(
link=link,
quota=quota,
)
@router.get("/link/{album_id}", response_model=YouTubeLink | None)
async def get_link(
album_id: str,
youtube_service: YouTubeServiceDep,
) -> YouTubeLink | Response:
link = await youtube_service.get_link(album_id)
if link is None:
return Response(status_code=204)
return link
@router.get("/links", response_model=list[YouTubeLink])
async def get_all_links(
youtube_service: YouTubeServiceDep,
) -> list[YouTubeLink]:
return await youtube_service.get_all_links()
@router.delete("/link/{album_id}", status_code=204)
async def delete_link(
album_id: str,
youtube_service: YouTubeServiceDep,
) -> None:
await youtube_service.delete_link(album_id)
@router.put("/link/{album_id}", response_model=YouTubeLink)
async def update_link(
album_id: str,
youtube_service: YouTubeServiceDep,
request: YouTubeLinkUpdateRequest = MsgSpecBody(YouTubeLinkUpdateRequest),
) -> YouTubeLink:
return await youtube_service.update_link(
album_id=album_id,
youtube_url=request.youtube_url,
album_name=request.album_name,
artist_name=request.artist_name,
cover_url=request.cover_url,
)
@router.post("/manual", response_model=YouTubeLink)
async def save_manual_link(
youtube_service: YouTubeServiceDep,
request: YouTubeManualLinkRequest = MsgSpecBody(YouTubeManualLinkRequest),
) -> YouTubeLink:
return await youtube_service.save_manual_link(
album_name=request.album_name,
artist_name=request.artist_name,
youtube_url=request.youtube_url,
cover_url=request.cover_url,
album_id=request.album_id,
)
@router.post("/generate-track", response_model=YouTubeTrackLinkResponse)
async def generate_track_link(
youtube_service: YouTubeServiceDep,
request: YouTubeTrackLinkGenerateRequest = MsgSpecBody(YouTubeTrackLinkGenerateRequest),
) -> YouTubeTrackLinkResponse:
track_link = await youtube_service.generate_track_link(
album_id=request.album_id,
album_name=request.album_name,
artist_name=request.artist_name,
track_name=request.track_name,
track_number=request.track_number,
disc_number=request.disc_number,
cover_url=request.cover_url,
)
quota = youtube_service.get_quota_status()
return YouTubeTrackLinkResponse(
track_link=track_link,
quota=quota,
)
@router.post("/generate-tracks", response_model=YouTubeTrackLinkBatchResponse)
async def generate_track_links_batch(
youtube_service: YouTubeServiceDep,
request: YouTubeTrackLinkBatchGenerateRequest = MsgSpecBody(YouTubeTrackLinkBatchGenerateRequest),
) -> YouTubeTrackLinkBatchResponse:
tracks = [
{"track_name": t.track_name, "track_number": t.track_number, "disc_number": t.disc_number}
for t in request.tracks
]
generated, failed = await youtube_service.generate_track_links_batch(
album_id=request.album_id,
album_name=request.album_name,
artist_name=request.artist_name,
tracks=tracks,
cover_url=request.cover_url,
)
quota = youtube_service.get_quota_status()
return YouTubeTrackLinkBatchResponse(
track_links=generated,
failed=failed,
quota=quota,
)
@router.get("/track-links/{album_id}", response_model=list[YouTubeTrackLink])
async def get_track_links(
album_id: str,
youtube_service: YouTubeServiceDep,
) -> list[YouTubeTrackLink]:
return await youtube_service.get_track_links(album_id)
@router.delete("/track-link/{album_id}/{track_number}", status_code=204, deprecated=True)
async def delete_track_link_legacy(
album_id: str,
track_number: int,
youtube_service: YouTubeServiceDep,
) -> None:
await youtube_service.delete_track_link(album_id, 1, track_number)
@router.delete("/track-link/{album_id}/{disc_number}/{track_number}", status_code=204)
async def delete_track_link(
album_id: str,
disc_number: int,
track_number: int,
youtube_service: YouTubeServiceDep,
) -> None:
await youtube_service.delete_track_link(album_id, disc_number, track_number)
@router.get("/quota", response_model=YouTubeQuotaResponse)
async def get_quota(
youtube_service: YouTubeServiceDep,
) -> YouTubeQuotaResponse:
return youtube_service.get_quota_status()