This commit is contained in:
2026-01-11 14:46:41 -08:00
parent 1f3de7db1c
commit 275f18cb31
19 changed files with 2741 additions and 394 deletions

View File

@@ -2499,7 +2499,7 @@ def resolve_tidal_manifest_path(item: Any) -> Optional[str]:
raw_manifest = metadata.get("manifest")
if not raw_manifest:
# When piping directly from the HIFI search table, we may only have a track id.
# When piping directly from the Tidal search table, we may only have a track id.
# Fetch track details from the proxy so downstream stages can decode the manifest.
try:
already = bool(metadata.get("_tidal_track_details_fetched"))
@@ -2518,7 +2518,7 @@ def resolve_tidal_manifest_path(item: Any) -> Optional[str]:
if candidate_path:
m = re.search(
r"hifi:(?://)?track[\\/](\d+)",
r"tidal:(?://)?track[\\/](\d+)",
str(candidate_path),
flags=re.IGNORECASE,
)
@@ -2626,7 +2626,7 @@ def resolve_tidal_manifest_path(item: Any) -> Optional[str]:
except Exception:
pass
log(
f"[hifi] JSON manifest for track {metadata.get('trackId') or metadata.get('id')} had no playable urls",
f"[tidal] JSON manifest for track {metadata.get('trackId') or metadata.get('id')} had no playable urls",
file=sys.stderr,
)
except Exception as exc:
@@ -2637,7 +2637,7 @@ def resolve_tidal_manifest_path(item: Any) -> Optional[str]:
except Exception:
pass
log(
f"[hifi] Failed to parse JSON manifest for track {metadata.get('trackId') or metadata.get('id')}: {exc}",
f"[tidal] Failed to parse JSON manifest for track {metadata.get('trackId') or metadata.get('id')}: {exc}",
file=sys.stderr,
)
return None
@@ -2658,7 +2658,7 @@ def resolve_tidal_manifest_path(item: Any) -> Optional[str]:
pass
try:
log(
f"[hifi] Decoded manifest is not an MPD XML for track {metadata.get('trackId') or metadata.get('id')} (mime {manifest_mime or 'unknown'})",
f"[tidal] Decoded manifest is not an MPD XML for track {metadata.get('trackId') or metadata.get('id')} (mime {manifest_mime or 'unknown'})",
file=sys.stderr,
)
except Exception:
@@ -2681,13 +2681,13 @@ def resolve_tidal_manifest_path(item: Any) -> Optional[str]:
# Persist as .mpd for DASH manifests.
ext = "mpd"
manifest_dir = Path(tempfile.gettempdir()) / "medeia" / "hifi"
manifest_dir = Path(tempfile.gettempdir()) / "medeia" / "tidal"
try:
manifest_dir.mkdir(parents=True, exist_ok=True)
except Exception:
pass
filename = f"hifi-{track_safe}-{identifier_safe[:24]}.{ext}"
filename = f"tidal-{track_safe}-{identifier_safe[:24]}.{ext}"
target_path = manifest_dir / filename
try:
with open(target_path, "wb") as fh:

View File

@@ -1050,7 +1050,7 @@ class Add_File(Cmdlet):
"https://",
"magnet:",
"torrent:",
"hifi:",
"tidal:",
"hydrus:")):
log(
"add-file ingests local files only. Use download-file first.",
@@ -1067,7 +1067,7 @@ class Add_File(Cmdlet):
"https://",
"magnet:",
"torrent:",
"hifi:",
"tidal:",
"hydrus:")):
log(
"add-file ingests local files only. Use download-file first.",
@@ -1088,7 +1088,7 @@ class Add_File(Cmdlet):
"https://",
"magnet:",
"torrent:",
"hifi:",
"tidal:",
"hydrus:")):
log(
"add-file ingests local files only. Use download-file first.",
@@ -1214,7 +1214,7 @@ class Add_File(Cmdlet):
"https://",
"magnet:",
"torrent:",
"hifi:",
"tidal:",
"hydrus:")):
log("add-file ingests local files only.", file=sys.stderr)
return False

View File

@@ -931,7 +931,8 @@ class Download_File(Cmdlet):
pass
transfer_label = label
if str(table or "").lower() == "hifi":
table_type = str(table or "").lower()
if table_type == "tidal" or table_type.startswith("tidal."):
try:
progress.begin_transfer(label=transfer_label, total=None)
except Exception:
@@ -943,7 +944,9 @@ class Download_File(Cmdlet):
provider_sr = None
provider_obj = None
if table and get_search_provider and SearchResult:
provider_obj = get_search_provider(str(table), config)
# Strip sub-table suffix (e.g. tidal.track -> tidal) to find the provider key
provider_key = str(table).split(".")[0]
provider_obj = get_search_provider(provider_key, config)
if provider_obj is not None:
attempted_provider_download = True
sr = SearchResult(
@@ -1160,14 +1163,7 @@ class Download_File(Cmdlet):
pass
# Allow providers to add/enrich tags and metadata during download.
if str(table or "").lower() == "libgen" and provider_sr is not None:
try:
sr_tags = getattr(provider_sr, "tag", None)
if tags_list is None and isinstance(sr_tags, set) and sr_tags:
tags_list = sorted([str(t) for t in sr_tags if t])
except Exception:
pass
if provider_sr is not None:
try:
sr_md = getattr(provider_sr, "full_metadata", None)
if isinstance(sr_md, dict) and sr_md:
@@ -1183,6 +1179,15 @@ class Download_File(Cmdlet):
except Exception:
pass
# Prefer tags from the search result object if the provider mutated them during download.
try:
sr_tags = getattr(provider_sr, "tag", None)
if isinstance(sr_tags, (set, list)) and sr_tags:
# Re-sync tags_list with the potentially enriched provider_sr.tag
tags_list = sorted([str(t) for t in sr_tags if t])
except Exception:
pass
self._emit_local_file(
downloaded_path=downloaded_path,
source=str(target) if target else None,
@@ -1201,7 +1206,8 @@ class Download_File(Cmdlet):
except Exception as e:
log(f"Error downloading item: {e}", file=sys.stderr)
finally:
if str(table or "").lower() == "hifi":
table_type = str(table or "").lower()
if table_type == "tidal" or table_type.startswith("tidal."):
try:
progress.finish_transfer(label=transfer_label)
except Exception:

View File

@@ -66,8 +66,8 @@ class search_file(Cmdlet):
CmdletArg(
"provider",
type="string",
description=
"External provider name: bandcamp, libgen, soulseek, youtube, alldebrid, loc, internetarchive, hifi",
description="External provider name (e.g., tidal, youtube, soulseek, etc)",
choices=["bandcamp", "libgen", "soulseek", "youtube", "alldebrid", "loc", "internetarchive", "tidal", "tidal"],
),
CmdletArg(
"open",
@@ -116,7 +116,7 @@ class search_file(Cmdlet):
return ext[:5]
@staticmethod
def _get_hifi_view_from_query(query: str) -> str:
def _get_tidal_view_from_query(query: str) -> str:
text = str(query or "").strip()
if not text:
return "track"
@@ -303,10 +303,10 @@ class search_file(Cmdlet):
preserve_order = provider_lower in {"youtube", "openlibrary", "loc", "torrent"}
table_type = provider_name
table_meta: Dict[str, Any] = {"provider": provider_name}
if provider_lower == "hifi":
view = self._get_hifi_view_from_query(query)
if provider_lower == "tidal":
view = self._get_tidal_view_from_query(query)
table_meta["view"] = view
table_type = f"hifi.{view}"
table_type = f"tidal.{view}"
elif provider_lower == "internetarchive":
# Internet Archive search results are effectively folders (items); selecting @N
# should open a list of downloadable files for the chosen item.
@@ -339,10 +339,10 @@ class search_file(Cmdlet):
results = provider.search(query, limit=limit, filters=search_filters or None)
debug(f"[search-file] {provider_name} -> {len(results or [])} result(s)")
# HIFI artist UX: if there is exactly one artist match, auto-expand
# Tidal artist UX: if there is exactly one artist match, auto-expand
# directly to albums without requiring an explicit @1 selection.
if (
provider_lower == "hifi"
provider_lower == "tidal"
and table_meta.get("view") == "artist"
and isinstance(results, list)
and len(results) == 1
@@ -372,7 +372,7 @@ class search_file(Cmdlet):
if album_results:
results = album_results
table_type = "hifi.album"
table_type = "tidal.album"
table.set_table(table_type)
table_meta["view"] = "album"
try: