k
This commit is contained in:
@@ -11,6 +11,15 @@ import subprocess
|
||||
|
||||
from API.HTTP import HTTPClient
|
||||
from ProviderCore.base import SearchResult
|
||||
try:
|
||||
from Provider.HIFI import HIFI
|
||||
except ImportError: # pragma: no cover - optional
|
||||
HIFI = None
|
||||
from Provider.tidal_shared import (
|
||||
build_track_tags,
|
||||
extract_artists,
|
||||
stringify,
|
||||
)
|
||||
try: # Optional dependency for IMDb scraping
|
||||
from imdbinfo.services import search_title # type: ignore
|
||||
except ImportError: # pragma: no cover - optional
|
||||
@@ -1416,6 +1425,95 @@ except Exception:
|
||||
|
||||
# Registry ---------------------------------------------------------------
|
||||
|
||||
class TidalMetadataProvider(MetadataProvider):
|
||||
"""Metadata provider that reuses the HIFI search provider for tidal info."""
|
||||
|
||||
@property
|
||||
def name(self) -> str: # type: ignore[override]
|
||||
return "tidal"
|
||||
|
||||
def __init__(self, config: Optional[Dict[str, Any]] = None) -> None:
|
||||
if HIFI is None:
|
||||
raise RuntimeError("HIFI provider unavailable for tidal metadata")
|
||||
super().__init__(config)
|
||||
self._provider = HIFI(self.config)
|
||||
|
||||
def search(self, query: str, limit: int = 10) -> List[Dict[str, Any]]:
|
||||
normalized = str(query or "").strip()
|
||||
if not normalized:
|
||||
return []
|
||||
|
||||
try:
|
||||
results = self._provider.search(normalized, limit=limit)
|
||||
except Exception as exc:
|
||||
debug(f"[tidal-meta] search failed for '{normalized}': {exc}")
|
||||
return []
|
||||
|
||||
items: List[Dict[str, Any]] = []
|
||||
for result in results:
|
||||
metadata = getattr(result, "full_metadata", {}) or {}
|
||||
if not isinstance(metadata, dict):
|
||||
metadata = {}
|
||||
|
||||
title = stringify(metadata.get("title") or result.title)
|
||||
if not title:
|
||||
continue
|
||||
|
||||
artists = extract_artists(metadata)
|
||||
artist_display = ", ".join(artists) if artists else stringify(metadata.get("artist"))
|
||||
|
||||
album_obj = metadata.get("album")
|
||||
album = ""
|
||||
if isinstance(album_obj, dict):
|
||||
album = stringify(album_obj.get("title"))
|
||||
else:
|
||||
album = stringify(metadata.get("album"))
|
||||
|
||||
year = stringify(metadata.get("releaseDate") or metadata.get("year") or metadata.get("date"))
|
||||
|
||||
track_id = self._provider._parse_track_id(metadata.get("trackId") or metadata.get("id"))
|
||||
lyrics_data = None
|
||||
if track_id is not None:
|
||||
try:
|
||||
lyrics_data = self._provider._fetch_track_lyrics(track_id)
|
||||
except Exception as exc:
|
||||
debug(f"[tidal-meta] lyrics lookup failed for {track_id}: {exc}")
|
||||
|
||||
lyrics = None
|
||||
if isinstance(lyrics_data, dict):
|
||||
lyrics = stringify(lyrics_data.get("lyrics") or lyrics_data.get("text"))
|
||||
subtitles = stringify(lyrics_data.get("subtitles"))
|
||||
if subtitles:
|
||||
metadata.setdefault("_tidal_lyrics", {})["subtitles"] = subtitles
|
||||
|
||||
tags = sorted(build_track_tags(metadata))
|
||||
items.append({
|
||||
"title": title,
|
||||
"artist": artist_display,
|
||||
"album": album,
|
||||
"year": year,
|
||||
"lyrics": lyrics,
|
||||
"tags": tags,
|
||||
"provider": self.name,
|
||||
"path": getattr(result, "path", ""),
|
||||
"track_id": track_id,
|
||||
"full_metadata": metadata,
|
||||
})
|
||||
return items
|
||||
|
||||
def to_tags(self, item: Dict[str, Any]) -> List[str]:
|
||||
tags: List[str] = []
|
||||
for value in item.get("tags", []):
|
||||
value_text = stringify(value)
|
||||
if value_text:
|
||||
normalized = value_text.lower()
|
||||
if normalized in {"tidal", "lossless"}:
|
||||
continue
|
||||
if normalized.startswith("quality:lossless"):
|
||||
continue
|
||||
tags.append(value_text)
|
||||
return tags
|
||||
|
||||
_METADATA_PROVIDERS: Dict[str,
|
||||
Type[MetadataProvider]] = {
|
||||
"itunes": ITunesProvider,
|
||||
@@ -1426,6 +1524,7 @@ _METADATA_PROVIDERS: Dict[str,
|
||||
"musicbrainz": MusicBrainzMetadataProvider,
|
||||
"imdb": ImdbMetadataProvider,
|
||||
"ytdlp": YtdlpMetadataProvider,
|
||||
"tidal": TidalMetadataProvider,
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user