update
This commit is contained in:
100
cmdnat/pipe.py
100
cmdnat/pipe.py
@@ -844,7 +844,6 @@ def _tail_text_file(path: str,
|
||||
return []
|
||||
except Exception:
|
||||
return []
|
||||
|
||||
try:
|
||||
with open(p, "rb") as f:
|
||||
try:
|
||||
@@ -864,6 +863,64 @@ def _tail_text_file(path: str,
|
||||
return []
|
||||
|
||||
|
||||
def _extract_tidal_stream_fallback_url(item: Any) -> Optional[str]:
|
||||
"""Best-effort HTTP streaming fallback for unresolved tidal:// placeholders."""
|
||||
|
||||
def _http_candidate(value: Any) -> Optional[str]:
|
||||
if isinstance(value, list):
|
||||
for entry in value:
|
||||
candidate = _http_candidate(entry)
|
||||
if candidate:
|
||||
return candidate
|
||||
return None
|
||||
text = str(value or "").strip()
|
||||
if not text:
|
||||
return None
|
||||
if text.lower().startswith(("http://", "https://")):
|
||||
return text
|
||||
return None
|
||||
|
||||
metadata: Optional[Dict[str, Any]] = None
|
||||
|
||||
if isinstance(item, dict):
|
||||
metadata = item.get("full_metadata") or item.get("metadata")
|
||||
for key in ("url", "source_url", "target"):
|
||||
candidate = _http_candidate(item.get(key))
|
||||
if candidate:
|
||||
return candidate
|
||||
else:
|
||||
try:
|
||||
metadata = getattr(item, "full_metadata", None) or getattr(item, "metadata", None)
|
||||
except Exception:
|
||||
metadata = None
|
||||
for key in ("url", "source_url", "target"):
|
||||
try:
|
||||
candidate = _http_candidate(getattr(item, key, None))
|
||||
except Exception:
|
||||
candidate = None
|
||||
if candidate:
|
||||
return candidate
|
||||
|
||||
if not isinstance(metadata, dict):
|
||||
return None
|
||||
|
||||
for key in (
|
||||
"_tidal_manifest_url",
|
||||
"streamUrl",
|
||||
"audioUrl",
|
||||
"assetUrl",
|
||||
"playbackUrl",
|
||||
"manifestUrl",
|
||||
"manifestURL",
|
||||
"url",
|
||||
):
|
||||
candidate = _http_candidate(metadata.get(key))
|
||||
if candidate:
|
||||
return candidate
|
||||
|
||||
return None
|
||||
|
||||
|
||||
def _get_playable_path(
|
||||
item: Any,
|
||||
file_storage: Optional[Any],
|
||||
@@ -950,21 +1007,38 @@ def _get_playable_path(
|
||||
if manifest_path:
|
||||
path = manifest_path
|
||||
else:
|
||||
# If this is a tidal:// placeholder and we couldn't resolve a manifest, do not fall back.
|
||||
# If this is a tidal:// placeholder and we couldn't resolve a manifest, do not fall back —
|
||||
# UNLESS the item has already been stored in a backend (store+hash present), in which case
|
||||
# we clear the tidal:// path so the store-resolution logic below can build a playable URL.
|
||||
try:
|
||||
if isinstance(path, str) and path.strip().lower().startswith("tidal:"):
|
||||
try:
|
||||
meta = None
|
||||
if isinstance(item, dict):
|
||||
meta = item.get("full_metadata") or item.get("metadata")
|
||||
if store and file_hash and str(file_hash).strip().lower() not in ("", "unknown"):
|
||||
# Item is stored in a backend — clear the tidal:// placeholder and let
|
||||
# the hash+store resolution further below build the real playable URL.
|
||||
path = None
|
||||
else:
|
||||
fallback_stream_url = _extract_tidal_stream_fallback_url(item)
|
||||
if fallback_stream_url:
|
||||
path = fallback_stream_url
|
||||
try:
|
||||
debug(
|
||||
f"_get_playable_path: using fallback Tidal stream URL {fallback_stream_url}"
|
||||
)
|
||||
except Exception:
|
||||
pass
|
||||
else:
|
||||
meta = getattr(item, "full_metadata", None) or getattr(item, "metadata", None)
|
||||
if isinstance(meta, dict) and meta.get("_tidal_manifest_error"):
|
||||
print(str(meta.get("_tidal_manifest_error")), file=sys.stderr)
|
||||
except Exception:
|
||||
pass
|
||||
print("Tidal selection has no playable DASH MPD manifest.", file=sys.stderr)
|
||||
return None
|
||||
try:
|
||||
meta = None
|
||||
if isinstance(item, dict):
|
||||
meta = item.get("full_metadata") or item.get("metadata")
|
||||
else:
|
||||
meta = getattr(item, "full_metadata", None) or getattr(item, "metadata", None)
|
||||
if isinstance(meta, dict) and meta.get("_tidal_manifest_error"):
|
||||
print(str(meta.get("_tidal_manifest_error")), file=sys.stderr)
|
||||
except Exception:
|
||||
pass
|
||||
print("Tidal selection has no playable DASH MPD manifest.", file=sys.stderr)
|
||||
return None
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
|
||||
Reference in New Issue
Block a user