f
This commit is contained in:
@@ -1,5 +1,6 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import os
|
||||||
import sys
|
import sys
|
||||||
import subprocess
|
import subprocess
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
@@ -98,6 +99,7 @@ def ensure_zerotier_server_running() -> None:
|
|||||||
"--storage-path", str(storage_path),
|
"--storage-path", str(storage_path),
|
||||||
"--port", str(port),
|
"--port", str(port),
|
||||||
"--monitor"]
|
"--monitor"]
|
||||||
|
cmd += ["--parent-pid", str(os.getpid())]
|
||||||
if api_key:
|
if api_key:
|
||||||
cmd += ["--api-key", str(api_key)]
|
cmd += ["--api-key", str(api_key)]
|
||||||
|
|
||||||
|
|||||||
@@ -3828,10 +3828,43 @@ def check_url_exists_in_storage(
|
|||||||
except Exception:
|
except Exception:
|
||||||
cm = nullcontext()
|
cm = nullcontext()
|
||||||
|
|
||||||
|
auto_confirm_reason: Optional[str] = None
|
||||||
|
if in_pipeline and stage_ctx is not None:
|
||||||
|
try:
|
||||||
|
total_stages = int(getattr(stage_ctx, "total_stages", 0))
|
||||||
|
except Exception:
|
||||||
|
total_stages = 0
|
||||||
|
try:
|
||||||
|
is_last_stage = bool(getattr(stage_ctx, "is_last_stage", False))
|
||||||
|
except Exception:
|
||||||
|
is_last_stage = False
|
||||||
|
if total_stages > 1 and not is_last_stage:
|
||||||
|
auto_confirm_reason = "pipeline stage (pre-last)"
|
||||||
|
if auto_confirm_reason is None:
|
||||||
|
try:
|
||||||
|
stdin_interactive = bool(sys.stdin and sys.stdin.isatty())
|
||||||
|
except Exception:
|
||||||
|
stdin_interactive = False
|
||||||
|
if not stdin_interactive:
|
||||||
|
auto_confirm_reason = "non-interactive stdin"
|
||||||
|
|
||||||
|
answered_yes = True
|
||||||
with cm:
|
with cm:
|
||||||
get_stderr_console().print(table)
|
get_stderr_console().print(table)
|
||||||
setattr(table, "_rendered_by_cmdlet", True)
|
setattr(table, "_rendered_by_cmdlet", True)
|
||||||
|
if auto_confirm_reason is None:
|
||||||
answered_yes = bool(Confirm.ask("Continue anyway?", default=False, console=get_stderr_console()))
|
answered_yes = bool(Confirm.ask("Continue anyway?", default=False, console=get_stderr_console()))
|
||||||
|
else:
|
||||||
|
debug(
|
||||||
|
f"Bulk URL preflight auto-confirmed duplicates ({auto_confirm_reason}); continuing without user input."
|
||||||
|
)
|
||||||
|
try:
|
||||||
|
log(
|
||||||
|
f"Auto-confirmed duplicate URL warning ({auto_confirm_reason}). Continuing...",
|
||||||
|
file=sys.stderr,
|
||||||
|
)
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
|
||||||
if in_pipeline:
|
if in_pipeline:
|
||||||
try:
|
try:
|
||||||
|
|||||||
@@ -696,16 +696,22 @@ def main():
|
|||||||
action="store_true",
|
action="store_true",
|
||||||
help="Shut down if parent process dies"
|
help="Shut down if parent process dies"
|
||||||
)
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--parent-pid",
|
||||||
|
type=int,
|
||||||
|
default=None,
|
||||||
|
help="Explicit PID to monitor (defaults to the immediate parent process)",
|
||||||
|
)
|
||||||
|
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
# Start monitor thread if requested
|
# Start monitor thread if requested
|
||||||
if args.monitor:
|
if args.monitor:
|
||||||
ppid = os.getppid()
|
monitor_pid = args.parent_pid or os.getppid()
|
||||||
if ppid > 1:
|
if monitor_pid > 1:
|
||||||
monitor_thread = threading.Thread(
|
monitor_thread = threading.Thread(
|
||||||
target=monitor_parent,
|
target=monitor_parent,
|
||||||
args=(ppid, ),
|
args=(monitor_pid, ),
|
||||||
daemon=True
|
daemon=True
|
||||||
)
|
)
|
||||||
monitor_thread.start()
|
monitor_thread.start()
|
||||||
|
|||||||
@@ -165,6 +165,74 @@ def _parse_csv_list(value: Any) -> Optional[List[str]]:
|
|||||||
return parts or None
|
return parts or None
|
||||||
|
|
||||||
|
|
||||||
|
_BROWSER_COOKIES_AVAILABLE: Optional[bool] = None
|
||||||
|
_BROWSER_COOKIE_WARNING_EMITTED = False
|
||||||
|
|
||||||
|
|
||||||
|
def _browser_cookie_candidate_paths() -> List[Path]:
|
||||||
|
try:
|
||||||
|
home = Path.home()
|
||||||
|
except Exception:
|
||||||
|
home = Path.cwd()
|
||||||
|
|
||||||
|
candidates: List[Path] = []
|
||||||
|
if os.name == "nt":
|
||||||
|
for env_value in (os.getenv("LOCALAPPDATA"), os.getenv("APPDATA")):
|
||||||
|
if not env_value:
|
||||||
|
continue
|
||||||
|
base_path = Path(env_value)
|
||||||
|
if not base_path:
|
||||||
|
continue
|
||||||
|
candidates.extend([
|
||||||
|
base_path / "Google" / "Chrome" / "User Data" / "Default" / "Cookies",
|
||||||
|
base_path / "Chromium" / "User Data" / "Default" / "Cookies",
|
||||||
|
base_path / "BraveSoftware" / "Brave-Browser" / "User Data" / "Default" / "Cookies",
|
||||||
|
])
|
||||||
|
else:
|
||||||
|
candidates.extend([
|
||||||
|
home / ".config" / "google-chrome" / "Default" / "Cookies",
|
||||||
|
home / ".config" / "chromium" / "Default" / "Cookies",
|
||||||
|
home / ".config" / "BraveSoftware" / "Brave-Browser" / "Default" / "Cookies",
|
||||||
|
])
|
||||||
|
if sys.platform == "darwin":
|
||||||
|
candidates.extend([
|
||||||
|
home / "Library" / "Application Support" / "Google" / "Chrome" / "Default" / "Cookies",
|
||||||
|
home / "Library" / "Application Support" / "Chromium" / "Default" / "Cookies",
|
||||||
|
home / "Library" / "Application Support" / "BraveSoftware" / "Brave-Browser" / "Default" / "Cookies",
|
||||||
|
])
|
||||||
|
return candidates
|
||||||
|
|
||||||
|
|
||||||
|
def _has_browser_cookie_database() -> bool:
|
||||||
|
global _BROWSER_COOKIES_AVAILABLE
|
||||||
|
if _BROWSER_COOKIES_AVAILABLE is not None:
|
||||||
|
return _BROWSER_COOKIES_AVAILABLE
|
||||||
|
|
||||||
|
for path in _browser_cookie_candidate_paths():
|
||||||
|
try:
|
||||||
|
if path.is_file():
|
||||||
|
_BROWSER_COOKIES_AVAILABLE = True
|
||||||
|
return True
|
||||||
|
except Exception:
|
||||||
|
continue
|
||||||
|
|
||||||
|
_BROWSER_COOKIES_AVAILABLE = False
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def _add_browser_cookies_if_available(options: Dict[str, Any]) -> None:
|
||||||
|
global _BROWSER_COOKIE_WARNING_EMITTED
|
||||||
|
if _has_browser_cookie_database():
|
||||||
|
options["cookiesfrombrowser"] = ["chrome"]
|
||||||
|
return
|
||||||
|
if not _BROWSER_COOKIE_WARNING_EMITTED:
|
||||||
|
log(
|
||||||
|
"Browser cookie extraction skipped because no Chrome-compatible cookie database was found. "
|
||||||
|
"Provide a cookies file via config or --cookies if authentication is required."
|
||||||
|
)
|
||||||
|
_BROWSER_COOKIE_WARNING_EMITTED = True
|
||||||
|
|
||||||
|
|
||||||
def ensure_yt_dlp_ready() -> None:
|
def ensure_yt_dlp_ready() -> None:
|
||||||
"""Verify yt-dlp is importable, raising DownloadError if missing."""
|
"""Verify yt-dlp is importable, raising DownloadError if missing."""
|
||||||
|
|
||||||
@@ -272,7 +340,7 @@ def list_formats(
|
|||||||
ydl_opts["cookiefile"] = str(cookiefile)
|
ydl_opts["cookiefile"] = str(cookiefile)
|
||||||
else:
|
else:
|
||||||
# Best effort attempt to use browser cookies if no file is explicitly passed
|
# Best effort attempt to use browser cookies if no file is explicitly passed
|
||||||
ydl_opts["cookiesfrombrowser"] = ["chrome"]
|
_add_browser_cookies_if_available(ydl_opts)
|
||||||
|
|
||||||
if no_playlist:
|
if no_playlist:
|
||||||
ydl_opts["noplaylist"] = True
|
ydl_opts["noplaylist"] = True
|
||||||
@@ -365,7 +433,7 @@ def probe_url(
|
|||||||
ydl_opts["cookiefile"] = str(cookiefile)
|
ydl_opts["cookiefile"] = str(cookiefile)
|
||||||
else:
|
else:
|
||||||
# Best effort fallback
|
# Best effort fallback
|
||||||
ydl_opts["cookiesfrombrowser"] = ["chrome"]
|
_add_browser_cookies_if_available(ydl_opts)
|
||||||
|
|
||||||
if no_playlist:
|
if no_playlist:
|
||||||
ydl_opts["noplaylist"] = True
|
ydl_opts["noplaylist"] = True
|
||||||
@@ -708,7 +776,7 @@ class YtDlpTool:
|
|||||||
# Add browser cookies support "just in case" if no file found (best effort)
|
# Add browser cookies support "just in case" if no file found (best effort)
|
||||||
# This uses yt-dlp's support for extracting from common browsers.
|
# This uses yt-dlp's support for extracting from common browsers.
|
||||||
# Defaulting to 'chrome' as the most common path.
|
# Defaulting to 'chrome' as the most common path.
|
||||||
base_options["cookiesfrombrowser"] = ["chrome"]
|
_add_browser_cookies_if_available(base_options)
|
||||||
|
|
||||||
# Special handling for format keywords
|
# Special handling for format keywords
|
||||||
if opts.ytdl_format == "audio":
|
if opts.ytdl_format == "audio":
|
||||||
|
|||||||
Reference in New Issue
Block a user