kl
This commit is contained in:
@@ -375,7 +375,7 @@
|
||||
"(filespace\\.com/[a-zA-Z0-9]{12})"
|
||||
],
|
||||
"regexp": "(filespace\\.com/fd/([a-zA-Z0-9]{12}))|((filespace\\.com/[a-zA-Z0-9]{12}))",
|
||||
"status": false
|
||||
"status": true
|
||||
},
|
||||
"filezip": {
|
||||
"name": "filezip",
|
||||
@@ -595,7 +595,7 @@
|
||||
"(simfileshare\\.net/download/[0-9]+/)"
|
||||
],
|
||||
"regexp": "(simfileshare\\.net/download/[0-9]+/)",
|
||||
"status": false
|
||||
"status": true
|
||||
},
|
||||
"streamtape": {
|
||||
"name": "streamtape",
|
||||
|
||||
246
MPV/LUA/main.lua
246
MPV/LUA/main.lua
@@ -1876,6 +1876,212 @@ local function _download_url_for_current_item(url)
|
||||
return base, true
|
||||
end
|
||||
|
||||
function M._extract_youtube_video_id(url)
|
||||
url = trim(tostring(url or ''))
|
||||
if url == '' then
|
||||
return nil
|
||||
end
|
||||
|
||||
local lower = url:lower()
|
||||
local video_id = nil
|
||||
if lower:match('youtu%.be/') then
|
||||
video_id = url:match('youtu%.be/([^%?&#/]+)')
|
||||
elseif lower:match('youtube%.com/watch') or lower:match('youtube%-nocookie%.com/watch') then
|
||||
video_id = _extract_query_param(url, 'v')
|
||||
elseif lower:match('youtube%.com/shorts/') or lower:match('youtube%-nocookie%.com/shorts/') then
|
||||
video_id = url:match('/shorts/([^%?&#/]+)')
|
||||
elseif lower:match('youtube%.com/live/') or lower:match('youtube%-nocookie%.com/live/') then
|
||||
video_id = url:match('/live/([^%?&#/]+)')
|
||||
elseif lower:match('youtube%.com/embed/') or lower:match('youtube%-nocookie%.com/embed/') then
|
||||
video_id = url:match('/embed/([^%?&#/]+)')
|
||||
end
|
||||
|
||||
video_id = trim(tostring(video_id or ''))
|
||||
if video_id == '' or not video_id:match('^[%w_-]+$') then
|
||||
return nil
|
||||
end
|
||||
return video_id
|
||||
end
|
||||
|
||||
function M._suspicious_ytdl_format_reason(fmt, url, raw)
|
||||
fmt = trim(tostring(fmt or ''))
|
||||
url = trim(tostring(url or ''))
|
||||
if fmt == '' then
|
||||
return nil
|
||||
end
|
||||
|
||||
local lower_fmt = fmt:lower()
|
||||
if lower_fmt:match('^https?://') or lower_fmt:match('^rtmp') or (url ~= '' and fmt == url) then
|
||||
return 'format string is a url'
|
||||
end
|
||||
|
||||
local youtube_id = M._extract_youtube_video_id(url)
|
||||
if youtube_id and fmt == youtube_id then
|
||||
return 'format matches current youtube video id'
|
||||
end
|
||||
|
||||
if type(raw) == 'table' and youtube_id then
|
||||
local raw_id = trim(tostring(raw.id or ''))
|
||||
if raw_id ~= '' and raw_id == youtube_id and fmt == raw_id then
|
||||
return 'format matches raw youtube video id'
|
||||
end
|
||||
end
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
function M._clear_suspicious_ytdl_format_for_url(url, reason)
|
||||
url = trim(tostring(url or ''))
|
||||
if url == '' then
|
||||
return false
|
||||
end
|
||||
|
||||
local raw = mp.get_property_native('ytdl-raw-info')
|
||||
local bad_props = {}
|
||||
local bad_value = nil
|
||||
local bad_reason = nil
|
||||
local checks = {
|
||||
{
|
||||
prop = 'ytdl-format',
|
||||
value = mp.get_property_native('ytdl-format'),
|
||||
},
|
||||
{
|
||||
prop = 'file-local-options/ytdl-format',
|
||||
value = mp.get_property('file-local-options/ytdl-format'),
|
||||
},
|
||||
{
|
||||
prop = 'options/ytdl-format',
|
||||
value = mp.get_property('options/ytdl-format'),
|
||||
},
|
||||
}
|
||||
|
||||
for _, item in ipairs(checks) do
|
||||
local candidate = trim(tostring(item.value or ''))
|
||||
local why = M._suspicious_ytdl_format_reason(candidate, url, raw)
|
||||
if why then
|
||||
if not bad_value then
|
||||
bad_value = candidate
|
||||
end
|
||||
if not bad_reason then
|
||||
bad_reason = why
|
||||
end
|
||||
bad_props[#bad_props + 1] = tostring(item.prop)
|
||||
end
|
||||
end
|
||||
|
||||
if #bad_props == 0 then
|
||||
return false
|
||||
end
|
||||
|
||||
pcall(mp.set_property, 'options/ytdl-format', '')
|
||||
pcall(mp.set_property, 'file-local-options/ytdl-format', '')
|
||||
pcall(mp.set_property, 'ytdl-format', '')
|
||||
_lua_log(
|
||||
'ytdl-format: cleared suspicious selector=' .. tostring(bad_value or '')
|
||||
.. ' props=' .. table.concat(bad_props, ',')
|
||||
.. ' reason=' .. tostring(bad_reason or reason or 'invalid')
|
||||
.. ' url=' .. tostring(url)
|
||||
)
|
||||
return true
|
||||
end
|
||||
|
||||
function M._prepare_ytdl_format_for_web_load(url, reason)
|
||||
url = trim(tostring(url or ''))
|
||||
if url == '' then
|
||||
return false
|
||||
end
|
||||
|
||||
if M._clear_suspicious_ytdl_format_for_url(url, reason) then
|
||||
return true
|
||||
end
|
||||
|
||||
local normalized_url = url:gsub('#.*$', '')
|
||||
local base, query = normalized_url:match('^([^?]+)%?(.*)$')
|
||||
if base then
|
||||
local kept = {}
|
||||
for pair in query:gmatch('[^&]+') do
|
||||
local raw_key = pair:match('^([^=]+)') or pair
|
||||
local key = tostring(_percent_decode(raw_key) or raw_key or ''):lower()
|
||||
local keep = true
|
||||
if key == 't' or key == 'start' or key == 'time_continue' or key == 'timestamp' or key == 'time' or key == 'begin' then
|
||||
keep = false
|
||||
elseif key:match('^utm_') then
|
||||
keep = false
|
||||
end
|
||||
if keep then
|
||||
kept[#kept + 1] = pair
|
||||
end
|
||||
end
|
||||
if #kept > 0 then
|
||||
normalized_url = base .. '?' .. table.concat(kept, '&')
|
||||
else
|
||||
normalized_url = base
|
||||
end
|
||||
end
|
||||
local explicit_reload_url = normalized_url
|
||||
explicit_reload_url = explicit_reload_url:gsub('^[%a][%w+%.%-]*://', '')
|
||||
explicit_reload_url = explicit_reload_url:gsub('^www%.', '')
|
||||
explicit_reload_url = explicit_reload_url:gsub('/+$', '')
|
||||
explicit_reload_url = explicit_reload_url:lower()
|
||||
|
||||
local is_explicit_reload = (
|
||||
explicit_reload_url ~= ''
|
||||
and _skip_next_store_check_url ~= ''
|
||||
and explicit_reload_url == _skip_next_store_check_url
|
||||
)
|
||||
|
||||
local active_props = {}
|
||||
local first_value = nil
|
||||
local checks = {
|
||||
{
|
||||
prop = 'ytdl-format',
|
||||
value = mp.get_property_native('ytdl-format'),
|
||||
},
|
||||
{
|
||||
prop = 'file-local-options/ytdl-format',
|
||||
value = mp.get_property('file-local-options/ytdl-format'),
|
||||
},
|
||||
{
|
||||
prop = 'options/ytdl-format',
|
||||
value = mp.get_property('options/ytdl-format'),
|
||||
},
|
||||
}
|
||||
|
||||
for _, item in ipairs(checks) do
|
||||
local candidate = trim(tostring(item.value or ''))
|
||||
if candidate ~= '' then
|
||||
if not first_value then
|
||||
first_value = candidate
|
||||
end
|
||||
active_props[#active_props + 1] = tostring(item.prop) .. '=' .. candidate
|
||||
end
|
||||
end
|
||||
|
||||
if #active_props == 0 then
|
||||
return false
|
||||
end
|
||||
|
||||
if is_explicit_reload then
|
||||
_lua_log(
|
||||
'ytdl-format: preserving explicit reload selector reason=' .. tostring(reason or 'on-load')
|
||||
.. ' url=' .. tostring(url)
|
||||
.. ' values=' .. table.concat(active_props, '; ')
|
||||
)
|
||||
return false
|
||||
end
|
||||
|
||||
pcall(mp.set_property, 'options/ytdl-format', '')
|
||||
pcall(mp.set_property, 'file-local-options/ytdl-format', '')
|
||||
pcall(mp.set_property, 'ytdl-format', '')
|
||||
_lua_log(
|
||||
'ytdl-format: cleared stale selector=' .. tostring(first_value or '')
|
||||
.. ' reason=' .. tostring(reason or 'on-load')
|
||||
.. ' url=' .. tostring(url)
|
||||
.. ' values=' .. table.concat(active_props, '; ')
|
||||
)
|
||||
return true
|
||||
end
|
||||
|
||||
local function _normalize_url_for_store_lookup(url)
|
||||
url = trim(tostring(url or ''))
|
||||
if url == '' then
|
||||
@@ -3742,6 +3948,8 @@ function M._apply_web_subtitle_load_defaults(reason)
|
||||
return false
|
||||
end
|
||||
|
||||
M._prepare_ytdl_format_for_web_load(target, reason or 'on-load')
|
||||
|
||||
local raw = M._build_web_ytdl_raw_options()
|
||||
if raw and raw ~= '' then
|
||||
pcall(mp.set_property, 'file-local-options/ytdl-raw-options', raw)
|
||||
@@ -4664,22 +4872,35 @@ _show_format_list_osd = function(items, max_items)
|
||||
end
|
||||
|
||||
local function _current_ytdl_format_string()
|
||||
local url = _current_url_for_web_actions() or _current_target() or ''
|
||||
local raw = mp.get_property_native('ytdl-raw-info')
|
||||
|
||||
-- Preferred: mpv exposes the active ytdl format string.
|
||||
local fmt = trim(tostring(mp.get_property_native('ytdl-format') or ''))
|
||||
if fmt ~= '' then
|
||||
local suspicious_reason = M._suspicious_ytdl_format_reason(fmt, url, raw)
|
||||
if fmt ~= '' and not suspicious_reason then
|
||||
return fmt
|
||||
elseif fmt ~= '' then
|
||||
_lua_log('ytdl-format: ignoring suspicious current format source=ytdl-format value=' .. tostring(fmt) .. ' reason=' .. tostring(suspicious_reason))
|
||||
end
|
||||
|
||||
-- Fallbacks: option value, or raw info if available.
|
||||
local opt = trim(tostring(mp.get_property('options/ytdl-format') or ''))
|
||||
if opt ~= '' then
|
||||
suspicious_reason = M._suspicious_ytdl_format_reason(opt, url, raw)
|
||||
if opt ~= '' and not suspicious_reason then
|
||||
return opt
|
||||
elseif opt ~= '' then
|
||||
_lua_log('ytdl-format: ignoring suspicious current format source=options/ytdl-format value=' .. tostring(opt) .. ' reason=' .. tostring(suspicious_reason))
|
||||
end
|
||||
|
||||
local raw = mp.get_property_native('ytdl-raw-info')
|
||||
if type(raw) == 'table' then
|
||||
if raw.format_id and tostring(raw.format_id) ~= '' then
|
||||
return tostring(raw.format_id)
|
||||
local raw_format_id = tostring(raw.format_id)
|
||||
suspicious_reason = M._suspicious_ytdl_format_reason(raw_format_id, url, raw)
|
||||
if not suspicious_reason then
|
||||
return raw_format_id
|
||||
end
|
||||
_lua_log('ytdl-format: ignoring suspicious current format source=ytdl-raw-info.format_id value=' .. tostring(raw_format_id) .. ' reason=' .. tostring(suspicious_reason))
|
||||
end
|
||||
local rf = raw.requested_formats
|
||||
if type(rf) == 'table' then
|
||||
@@ -4690,7 +4911,12 @@ local function _current_ytdl_format_string()
|
||||
end
|
||||
end
|
||||
if #parts >= 1 then
|
||||
return table.concat(parts, '+')
|
||||
local joined = table.concat(parts, '+')
|
||||
suspicious_reason = M._suspicious_ytdl_format_reason(joined, url, raw)
|
||||
if not suspicious_reason then
|
||||
return joined
|
||||
end
|
||||
_lua_log('ytdl-format: ignoring suspicious current format source=ytdl-raw-info.requested_formats value=' .. tostring(joined) .. ' reason=' .. tostring(suspicious_reason))
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -4957,6 +5183,16 @@ local function _apply_ytdl_format_and_reload(url, fmt)
|
||||
return
|
||||
end
|
||||
|
||||
local suspicious_reason = M._suspicious_ytdl_format_reason(fmt, url, mp.get_property_native('ytdl-raw-info'))
|
||||
if suspicious_reason then
|
||||
pcall(mp.set_property, 'options/ytdl-format', '')
|
||||
pcall(mp.set_property, 'file-local-options/ytdl-format', '')
|
||||
pcall(mp.set_property, 'ytdl-format', '')
|
||||
_lua_log('change-format: rejected suspicious format=' .. tostring(fmt) .. ' reason=' .. tostring(suspicious_reason) .. ' url=' .. tostring(url))
|
||||
mp.osd_message('Invalid format selection', 3)
|
||||
return
|
||||
end
|
||||
|
||||
local pos = mp.get_property_number('time-pos')
|
||||
local paused = mp.get_property_native('pause') and true or false
|
||||
local media_title = trim(tostring(mp.get_property('media-title') or ''))
|
||||
|
||||
@@ -1831,8 +1831,7 @@ def main(argv: Optional[list[str]] = None) -> int:
|
||||
try:
|
||||
if target_client.sock is None:
|
||||
if use_shared_ipc_client:
|
||||
if note_ipc_unavailable is not None:
|
||||
note_ipc_unavailable(f"helper-command-connect:{label or '?'}")
|
||||
_note_ipc_unavailable(f"helper-command-connect:{label or '?'}")
|
||||
return False
|
||||
if not target_client.connect():
|
||||
_append_helper_log(
|
||||
|
||||
@@ -4,6 +4,7 @@ import re
|
||||
import sys
|
||||
import tempfile
|
||||
import shutil
|
||||
from collections import deque
|
||||
from pathlib import Path
|
||||
from typing import Any, Dict, List, Literal, Optional, Sequence, Tuple
|
||||
|
||||
@@ -1094,78 +1095,13 @@ class HydrusNetwork(Store):
|
||||
return token.replace("*", "").replace("?", "")
|
||||
|
||||
# Fast-path: exact URL via /add_urls/get_url_files when a full URL is provided.
|
||||
exact_url_attempted = False
|
||||
try:
|
||||
if pattern.startswith("http://") or pattern.startswith(
|
||||
"https://"):
|
||||
from API.HydrusNetwork import HydrusRequestSpec
|
||||
|
||||
spec = HydrusRequestSpec(
|
||||
method="GET",
|
||||
endpoint="/add_urls/get_url_files",
|
||||
query={
|
||||
"url": pattern
|
||||
},
|
||||
)
|
||||
response = client._perform_request(
|
||||
spec
|
||||
) # type: ignore[attr-defined]
|
||||
hashes = []
|
||||
file_ids = []
|
||||
if isinstance(response, dict):
|
||||
raw_hashes = response.get("hashes") or response.get(
|
||||
"file_hashes"
|
||||
)
|
||||
if isinstance(raw_hashes, list):
|
||||
hashes = [
|
||||
str(h).strip() for h in raw_hashes
|
||||
if isinstance(h, str) and str(h).strip()
|
||||
]
|
||||
raw_ids = response.get("file_ids")
|
||||
if isinstance(raw_ids, list):
|
||||
for item in raw_ids:
|
||||
try:
|
||||
file_ids.append(int(item))
|
||||
except (TypeError, ValueError):
|
||||
continue
|
||||
|
||||
if file_ids:
|
||||
payload = client.fetch_file_metadata(
|
||||
file_ids=file_ids,
|
||||
include_file_url=True,
|
||||
include_service_keys_to_tags=not minimal,
|
||||
include_duration=not minimal,
|
||||
include_size=not minimal,
|
||||
include_mime=not minimal,
|
||||
)
|
||||
metas = (
|
||||
payload.get("metadata",
|
||||
[]) if isinstance(payload,
|
||||
dict) else []
|
||||
)
|
||||
if isinstance(metas, list):
|
||||
metadata_list = [
|
||||
m for m in metas if isinstance(m, dict)
|
||||
]
|
||||
elif hashes:
|
||||
payload = client.fetch_file_metadata(
|
||||
hashes=hashes,
|
||||
include_file_url=True,
|
||||
include_service_keys_to_tags=not minimal,
|
||||
include_duration=not minimal,
|
||||
include_size=not minimal,
|
||||
include_mime=not minimal,
|
||||
)
|
||||
metas = (
|
||||
payload.get("metadata",
|
||||
[]) if isinstance(payload,
|
||||
dict) else []
|
||||
)
|
||||
if isinstance(metas, list):
|
||||
metadata_list = [
|
||||
m for m in metas if isinstance(m, dict)
|
||||
]
|
||||
if pattern.startswith("http://") or pattern.startswith("https://"):
|
||||
exact_url_attempted = True
|
||||
metadata_list = self.lookup_url_metadata(pattern, minimal=minimal)
|
||||
except Exception:
|
||||
metadata_list = None
|
||||
metadata_list = [] if exact_url_attempted else None
|
||||
|
||||
# Fallback: substring scan
|
||||
if metadata_list is None:
|
||||
@@ -2108,6 +2044,115 @@ class HydrusNetwork(Store):
|
||||
debug(f"{self._log_prefix()} get_url failed: {exc}")
|
||||
return []
|
||||
|
||||
def lookup_url_metadata(self, url_value: str, *, minimal: bool = False) -> List[Dict[str, Any]]:
|
||||
"""Resolve an exact URL to Hydrus metadata using /add_urls/get_url_files variants."""
|
||||
candidate_url = str(url_value or "").strip()
|
||||
if not candidate_url:
|
||||
return []
|
||||
|
||||
client = self._client
|
||||
if client is None:
|
||||
return []
|
||||
|
||||
try:
|
||||
from API.HydrusNetwork import HydrusRequestSpec, _generate_hydrus_url_variants
|
||||
except Exception:
|
||||
return []
|
||||
|
||||
pending: deque[str] = deque(_generate_hydrus_url_variants(candidate_url) or [candidate_url])
|
||||
seen_urls: set[str] = set()
|
||||
file_ids: List[int] = []
|
||||
hashes: List[str] = []
|
||||
seen_ids: set[int] = set()
|
||||
seen_hashes: set[str] = set()
|
||||
|
||||
while pending:
|
||||
current = str(pending.popleft() or "").strip()
|
||||
if not current or current in seen_urls:
|
||||
continue
|
||||
seen_urls.add(current)
|
||||
|
||||
try:
|
||||
response = client._perform_request(
|
||||
HydrusRequestSpec(
|
||||
method="GET",
|
||||
endpoint="/add_urls/get_url_files",
|
||||
query={"url": current},
|
||||
)
|
||||
)
|
||||
except Exception:
|
||||
continue
|
||||
|
||||
if not isinstance(response, dict):
|
||||
continue
|
||||
|
||||
raw_hashes = response.get("hashes") or response.get("file_hashes")
|
||||
if isinstance(raw_hashes, list):
|
||||
for item in raw_hashes:
|
||||
try:
|
||||
file_hash = str(item or "").strip().lower()
|
||||
except Exception:
|
||||
continue
|
||||
if not file_hash or file_hash in seen_hashes:
|
||||
continue
|
||||
seen_hashes.add(file_hash)
|
||||
hashes.append(file_hash)
|
||||
|
||||
raw_ids = response.get("file_ids") or response.get("file_id")
|
||||
id_values = raw_ids if isinstance(raw_ids, list) else [raw_ids] if raw_ids is not None else []
|
||||
for item in id_values:
|
||||
try:
|
||||
file_id = int(item)
|
||||
except (TypeError, ValueError):
|
||||
continue
|
||||
if file_id in seen_ids:
|
||||
continue
|
||||
seen_ids.add(file_id)
|
||||
file_ids.append(file_id)
|
||||
|
||||
for key in ("normalized_url", "redirect_url", "url"):
|
||||
value = response.get(key)
|
||||
if isinstance(value, str):
|
||||
next_url = value.strip()
|
||||
if next_url and next_url not in seen_urls:
|
||||
pending.append(next_url)
|
||||
|
||||
if not file_ids and not hashes:
|
||||
return []
|
||||
|
||||
try:
|
||||
payload = client.fetch_file_metadata(
|
||||
file_ids=file_ids or None,
|
||||
hashes=hashes or None,
|
||||
include_file_url=True,
|
||||
include_service_keys_to_tags=not minimal,
|
||||
include_duration=not minimal,
|
||||
include_size=not minimal,
|
||||
include_mime=not minimal,
|
||||
)
|
||||
except Exception:
|
||||
return []
|
||||
|
||||
metadata = payload.get("metadata") if isinstance(payload, dict) else None
|
||||
if not isinstance(metadata, list):
|
||||
return []
|
||||
return [entry for entry in metadata if isinstance(entry, dict)]
|
||||
|
||||
def find_hashes_by_url(self, url_value: str) -> List[str]:
|
||||
hashes: List[str] = []
|
||||
seen: set[str] = set()
|
||||
for entry in self.lookup_url_metadata(url_value, minimal=True):
|
||||
raw_hash = entry.get("hash") or entry.get("hash_hex") or entry.get("file_hash")
|
||||
try:
|
||||
file_hash = str(raw_hash or "").strip().lower()
|
||||
except Exception:
|
||||
continue
|
||||
if len(file_hash) != 64 or file_hash in seen:
|
||||
continue
|
||||
seen.add(file_hash)
|
||||
hashes.append(file_hash)
|
||||
return hashes
|
||||
|
||||
def get_url_info(self, url: str, **kwargs: Any) -> dict[str, Any] | None:
|
||||
"""Return Hydrus URL info for a single URL (Hydrus-only helper).
|
||||
|
||||
|
||||
@@ -326,10 +326,8 @@ class Add_File(Cmdlet):
|
||||
is_storage_backend_location = False
|
||||
if location:
|
||||
try:
|
||||
# Check against the cached startup list of available backends
|
||||
from cmdlet._shared import SharedArgs
|
||||
available_backends = SharedArgs.get_store_choices(config)
|
||||
is_storage_backend_location = location in available_backends
|
||||
store_for_lookup = storage_registry or Store(config)
|
||||
is_storage_backend_location = Add_File._resolve_backend_by_name(store_for_lookup, str(location)) is not None
|
||||
except Exception:
|
||||
is_storage_backend_location = False
|
||||
|
||||
@@ -608,8 +606,8 @@ class Add_File(Cmdlet):
|
||||
if location:
|
||||
try:
|
||||
store = storage_registry or Store(config)
|
||||
backends = store.list_backends()
|
||||
if location in backends:
|
||||
resolved_backend = Add_File._resolve_backend_by_name(store, str(location))
|
||||
if resolved_backend is not None:
|
||||
code = self._handle_storage_backend(
|
||||
item,
|
||||
media_path,
|
||||
|
||||
@@ -2685,6 +2685,14 @@ class Download_File(Cmdlet):
|
||||
pass
|
||||
|
||||
try:
|
||||
if HydrusNetwork is not None and isinstance(backend, HydrusNetwork):
|
||||
hashes = backend.find_hashes_by_url(canonical_url) or []
|
||||
for existing_hash in hashes:
|
||||
normalized = sh.normalize_hash(existing_hash)
|
||||
if normalized:
|
||||
return normalized
|
||||
continue
|
||||
|
||||
hits = backend.search(f"url:{canonical_url}", limit=5) or []
|
||||
except Exception:
|
||||
hits = []
|
||||
|
||||
@@ -1000,22 +1000,15 @@ def _build_hydrus_header(config: Dict[str, Any]) -> Optional[str]:
|
||||
def _build_ytdl_options(config: Optional[Dict[str,
|
||||
Any]],
|
||||
hydrus_header: Optional[str]) -> Optional[str]:
|
||||
"""Compose ytdl-raw-options string including cookies and optional Hydrus header."""
|
||||
"""Compose mpv ytdl-raw-options for playback.
|
||||
|
||||
Keep this limited to options that are truly required for MPV playback.
|
||||
In particular, do not pass the repo cookiefile via `cookies=...` here:
|
||||
mpv's ytdl-hook can fail to resolve some YouTube/Shorts URLs when a global
|
||||
cookiefile is forced, even though the same URLs work with MPV defaults.
|
||||
"""
|
||||
opts: List[str] = []
|
||||
cookies_path = None
|
||||
try:
|
||||
from tool.ytdlp import YtDlpTool
|
||||
|
||||
cookiefile = YtDlpTool(config or {}).resolve_cookiefile()
|
||||
if cookiefile is not None:
|
||||
cookies_path = str(cookiefile)
|
||||
except Exception:
|
||||
cookies_path = None
|
||||
|
||||
if cookies_path:
|
||||
opts.append(f"cookies={cookies_path.replace('\\', '/')}")
|
||||
# Do not force chrome cookies if none are found; let yt-dlp use its defaults or fail gracefully.
|
||||
|
||||
if hydrus_header:
|
||||
opts.append(f"add-header={hydrus_header}")
|
||||
return ",".join(opts) if opts else None
|
||||
@@ -2584,19 +2577,10 @@ def _start_mpv(
|
||||
|
||||
_schedule_notes_prefetch(items[:1], config)
|
||||
|
||||
cookies_path = None
|
||||
try:
|
||||
from tool.ytdlp import YtDlpTool
|
||||
|
||||
cookiefile = YtDlpTool(config or {}).resolve_cookiefile()
|
||||
if cookiefile is not None:
|
||||
cookies_path = str(cookiefile)
|
||||
except Exception:
|
||||
cookies_path = None
|
||||
if cookies_path:
|
||||
debug(f"Starting MPV with cookies file: {cookies_path.replace('\\', '/')}")
|
||||
if ytdl_opts:
|
||||
debug(f"Starting MPV with ytdl raw options: {ytdl_opts}")
|
||||
else:
|
||||
debug("Starting MPV with browser cookies: chrome")
|
||||
debug("Starting MPV with default yt-dlp raw options")
|
||||
|
||||
try:
|
||||
extra_args: List[str] = [
|
||||
|
||||
Reference in New Issue
Block a user