This commit is contained in:
2026-02-02 19:49:07 -08:00
parent 8d22ec5a81
commit 1e0000ae19
13 changed files with 297 additions and 988 deletions

View File

@@ -56,7 +56,7 @@ _LYRIC_VISIBLE_PROP = "user-data/medeia-lyric-visible"
# Optional overrides set by the playlist controller (.pipe/.mpv) so the lyric
# helper can resolve notes even when the local file path cannot be mapped back
# to a store via the store DB (common for Folder stores).
# to a store via the store DB.
_ITEM_STORE_PROP = "user-data/medeia-item-store"
_ITEM_HASH_PROP = "user-data/medeia-item-hash"
@@ -804,11 +804,7 @@ def _resolve_store_backend_for_target(
except Exception:
return None, None
# Prefer the inferred Folder store (fast), but still validate via get_file().
preferred = _infer_store_for_target(target=target, config=config)
if preferred and preferred in backend_names:
backend_names.remove(preferred)
backend_names.insert(0, preferred)
for name in backend_names:
try:
@@ -842,80 +838,9 @@ def _resolve_store_backend_for_target(
return name, backend
# Fallback for Folder stores:
# If the mpv target is inside a configured Folder store root and the filename
# is hash-named, accept the inferred store even if the store DB doesn't map
# hash->path (e.g. DB missing entry, external copy, etc.).
try:
inferred = _infer_store_for_target(target=target, config=config)
if inferred and inferred in backend_names:
backend = reg[inferred]
if type(backend).__name__ == "Folder":
p = Path(target)
stem = str(p.stem or "").strip().lower()
if stem and stem == str(file_hash or "").strip().lower():
return inferred, backend
except Exception:
pass
return None, None
def _infer_store_for_target(*, target: str, config: dict) -> Optional[str]:
"""Infer store name from the current mpv target (local path under a folder root).
Note: URLs/streams are intentionally not mapped to stores for lyrics.
"""
if isinstance(target, str) and _is_stream_target(target):
return None
try:
from Store import Store as StoreRegistry
reg = StoreRegistry(config, suppress_debug=True)
backends = [(name, reg[name]) for name in reg.list_backends()]
except Exception:
backends = []
# Local file path: choose the deepest Folder root that contains it.
try:
p = Path(target)
if not p.exists() or not p.is_file():
return None
p_str = str(p.resolve()).lower()
except Exception:
return None
best: Optional[str] = None
best_len = -1
for name, backend in backends:
if type(backend).__name__ != "Folder":
continue
root = None
try:
root = (
getattr(backend,
"_location",
None) or getattr(backend,
"location", lambda: None)()
)
except Exception:
root = None
if not root:
continue
try:
root_path = Path(str(root)).expanduser().resolve()
root_str = str(root_path).lower().rstrip("\\/")
except Exception:
continue
if p_str.startswith(root_str) and len(root_str) > best_len:
best = name
best_len = len(root_str)
return best
def _infer_hash_for_target(target: str) -> Optional[str]:
"""Infer SHA256 hash from Hydrus URL query, hash-named local files, or by hashing local file content."""
h = _extract_hash_from_target(target)

View File

@@ -64,6 +64,7 @@ if _ROOT not in sys.path:
from MPV.mpv_ipc import MPVIPCClient # noqa: E402
from SYS.config import load_config # noqa: E402
from SYS.logger import set_debug, debug, set_thread_stream # noqa: E402
from SYS.utils import format_bytes # noqa: E402
REQUEST_PROP = "user-data/medeia-pipeline-request"
RESPONSE_PROP = "user-data/medeia-pipeline-response"
@@ -395,20 +396,8 @@ def _run_op(op: str, data: Any) -> Dict[str, Any]:
ydl_opts["cookiefile"] = cookiefile
def _format_bytes(n: Any) -> str:
try:
v = float(n)
except Exception:
return ""
if v <= 0:
return ""
units = ["B", "KB", "MB", "GB", "TB"]
i = 0
while v >= 1024 and i < len(units) - 1:
v /= 1024.0
i += 1
if i == 0:
return f"{int(v)} {units[i]}"
return f"{v:.1f} {units[i]}"
"""Format bytes using centralized utility."""
return format_bytes(n)
with yt_dlp.YoutubeDL(ydl_opts) as ydl: # type: ignore[attr-defined]
info = ydl.extract_info(url, download=False)