"""Schemas for searching external (fetch) sources — the §A4 discover screen.""" import uuid from pydantic import BaseModel from app.domain.entities.track import Track 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 # Remote browse (plan: Model C) — set when this hit is already saved in the # library, so the UI can show "Play"/"Saved" instead of "Save to library". in_library: bool track_id: uuid.UUID | None availability: str | None @classmethod def from_entity( cls, r: SearchResult, *, existing: Track | None = None ) -> 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, in_library=existing is not None, track_id=existing.id if existing is not None else None, availability=existing.availability if existing is not None else None, ) 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]