10 Commits

Author SHA1 Message Date
Jaroslav Beneš 8dd8a3c1ad Add YtdlpClient: shared JSON invocation layer for yt-dlp
Every metadata call site previously built its own command list. The new
ytsage/core/ytsage_client.py centralizes binary resolution (managed,
verified binary only), cookie/proxy args from ConfigManager (with
session-state overrides), utf-8 output handling, process-group-safe
timeouts, and a short-TTL cache for flat/search results.

Provides fetch_video_info, fetch_flat_info, fetch_flat_entries (with
-I range pagination), search (ytsearchN:), and fetch_account_feed
(youtube.com/feed/subscriptions with cookies) plus a generic YtdlpWorker
QThread. AnalysisThread now delegates its subprocess execution to the
shared runner; its signal surface is unchanged.

Groundwork for the SageTube watch/search/browse/feed features.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-25 01:39:20 +02:00
Jaroslav Beneš ebb9422591 Harden yt-dlp binary resolution and analysis subprocess handling
- get_yt_dlp_path() no longer implicitly executes a bare "yt-dlp" from
  PATH (on Windows that lookup includes the CWD, so a planted binary
  in a writable directory could be run). A system yt-dlp is used only
  behind the explicit advanced.allow_system_ytdlp config opt-in, and
  then always as a which()-resolved absolute path. Analysis and
  download refuse to exec the not-installed sentinel.
- Analysis subprocesses now run in their own session and the whole
  process group is killed on timeout, so deno grandchildren no longer
  leak; partial stderr is preserved and logged, and output decoding is
  pinned to utf-8 with replacement (Windows locale codecs crashed on
  non-UTF8 titles).
- Flat-playlist entries are filtered for None (private/deleted first
  video no longer breaks analysis).
- update_yt_dlp() normalizes the sentinel to Path, unbreaking the pip
  fallback path that crashed on str.exists().

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-25 01:30:08 +02:00
oop7 0d5cbb2df1 Write auto-subs only if selected; show count
Downloader: add detection for "Auto-generated" subtitle selection and only append --write-auto-subs when an auto-generated subtitle is explicitly chosen (prevents always enabling the flag when any subtitles are requested). GUI: update subtitle label to display the number of selected subtitles when >0, falling back to the zero-selected message otherwise. Small UX and behavior fixes in DownloadThread and AnalysisMixin.
2026-05-01 16:49:58 +03:00
oop7 5bbecf1e1d Detect private/sign-in yt-dlp errors
Update AnalysisThread error handling to detect yt-dlp stderr containing "Private video" or "Sign in". For those cases, emit a localized errors.private_video message and log a specific private-video error; otherwise preserve the existing generic ytdlp_failed behavior. Playlist visibility signals and early return remain unchanged.
2026-04-28 13:29:26 +03:00
oop7 717e9b40ae Preselect default subtitles from config
Load user's default_subtitle_language from ConfigManager and preselect matching manual or auto-generated subtitles on analysis load. Handles comma-separated strings, checks against available_subtitles and available_automatic_subtitles, and updates the selected subtitles list. Attempts to update the UI label and button state (with style refresh) inside a try/except to avoid errors during initialization.
2026-04-25 10:32:20 +03:00
oop7 9afca46c5d Add generic-mode URL validation and UI
Introduce a "generic_mode" option to allow validating/downloading from non-YouTube sites and wire it through the UI, config, and validation logic. Key changes:

- Add generic_mode default to ConfigManager and persist setting from DownloadSettingsDialog (checkbox + help text).
- Extend validate_video_url to accept a generic_mode flag and allow any http/https URL with a domain when enabled; pass this flag from Analysis and Download flows.
- Update YTSageApp to load/save generic_mode, update URL placeholder and settings tooltip behavior, and refresh tooltip when settings change.
- Improve robustness in FormatTableMixin: handle None/incorrect types for format_note, abr, resolution, ext, and codec values to avoid type errors and ensure consistent display.
- Add localization entries for generic mode, placeholder, and related help text across multiple language files and update the in-app default localization strings.

These changes enable broader site support via yt-dlp while hardening UI format handling and keeping user settings persistent.
2026-03-12 11:10:10 +02:00
oop7 9f1381d27e Update format table directly from analysis
Stop storing result_data["all_formats"] on the mixin and instead call update_format_table(result_data["all_formats"]). Replaces the previous filter_formats() call so the format table is populated directly from the fresh analysis result, avoiding reliance on a separate self.all_formats attribute.
2026-02-07 19:01:37 +02:00
oop7 49dde84481 Add progress signals and fake progress timer
Emit progress updates during URL analysis and simulate gradual progress for long-running yt-dlp operations. Added QTimer import and a progress_update Signal on AnalysisThread, with emits at multiple analysis milestones (e.g. 15, 30, 60, 70, 85, 90, 92, 95, 100). In AnalysisMixin introduced _analysis_timer and _fake_progress, connected thread progress to _handle_analysis_progress, and implemented a _update_fake_progress timer that slowly advances the progress bar between real updates. Timers are stopped on real progress, completion or error and the UI progress is reset appropriately to improve UX during long extraction steps.
2026-02-03 19:17:30 +02:00
oop7 36eff02b18 Add widget shake animation for invalid input
Introduce a shake animation to visually indicate invalid inputs and wire it into validation/error flows. Changes: import QPoint; add animate_widget_shake(QWidget) implementation that uses QPropertyAnimation on widget.pos with keyframes; call the animation when URL/path/format validations fail and replace some direct status_label updates with set_status_message_animated. Updated files: ytsage/gui/ytsage_gui_main.py and ytsage/gui/ytsage_gui_analysis.py.
2026-02-01 12:36:00 +02:00
oop7 96dadd7e5b Refactor GUI package structure and update imports
Moved all files from src/gui/ to ytsage/gui/ and updated import statements to use relative imports within the new package structure. This improves modularity and prepares the codebase for distribution as a proper Python package.
2026-01-25 14:07:51 +02:00