78007461e1
Pluggable fetch source: ytmusicapi search + yt-dlp download (cookies-file guard), DownloadJob entity/repo + DownloadService, download_task worker with exponential-backoff retries, and wired /search, /sources/{source}/search, and /downloads endpoints. Adds youtube_enabled/cookies config, yt-dlp+ytmusicapi deps, and the download_jobs.track_id migration. Snapshot also bundles in-progress storage/tracks/acoustid edits.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
36 lines
994 B
Python
36 lines
994 B
Python
"""Schemas for searching external (fetch) sources — the §A4 discover screen."""
|
|
|
|
from pydantic import BaseModel
|
|
|
|
from app.domain.sources import SearchResult
|
|
|
|
|
|
class ExternalSearchResultOut(BaseModel):
|
|
source: str
|
|
source_id: str
|
|
title: str
|
|
artist: str | None
|
|
album: str | None
|
|
duration_seconds: int | None
|
|
thumbnail_url: str | None
|
|
|
|
@classmethod
|
|
def from_entity(cls, r: SearchResult) -> ExternalSearchResultOut:
|
|
return cls(
|
|
source=r.source,
|
|
source_id=r.source_id,
|
|
title=r.title,
|
|
artist=r.artist,
|
|
album=r.album,
|
|
duration_seconds=r.duration_seconds,
|
|
thumbnail_url=r.thumbnail_url,
|
|
)
|
|
|
|
|
|
class ExternalSearchResponse(BaseModel):
|
|
"""Flat list of hits across one or more searchable sources, plus the names of
|
|
sources that were unavailable (so the UI can show a soft warning)."""
|
|
|
|
results: list[ExternalSearchResultOut]
|
|
searched_sources: list[str]
|