Skip to content

feat: Browser cookie authentication, YouTube Profile menu with personalized content - #239

Open
ihorman wants to merge 26 commits into
trizen:mainfrom
ihorman:feat/cookies-from-browser
Open

feat: Browser cookie authentication, YouTube Profile menu with personalized content#239
ihorman wants to merge 26 commits into
trizen:mainfrom
ihorman:feat/cookies-from-browser

Conversation

@ihorman

@ihorman ihorman commented Jul 9, 2026

Copy link
Copy Markdown

Summary

Adds browser cookie extraction for YouTube authentication, enabling personalized content (subscriptions, history, playlists, trending) in both CLI and GTK interfaces.

Features Added

Core: Browser Cookie Authentication (--cookies-from-browser)

  • Extracts cookies directly from Chromium-based browsers (chromium, chrome, brave, edge, opera, vivaldi) using GNOME Keyring decryption
  • Python helper script (utils/extract-browser-cookies.py) for fast cookie extraction (~0.25s)
  • Handles YouTube's new __Secure-3P* cookie format — creates legacy SAPISID/SID aliases for API compatibility
  • Profile verification checks for auth cookies on both .google.com and .youtube.com domains
  • Cookies are cached and reused; force re-extraction via --cookies-from-browser flag
  • Fallback to yt-dlp if Python helper fails

GTK UI: Profile Menu

New Profile submenu in the Menu dropdown with:

  • Login with Browser (Ctrl+L) — browser selection dialog, auto-launches browser if not running, opens YouTube login page, extracts cookies, shows success/error feedback
  • Subscriptions (Ctrl+N) — YouTube subscription feed from logged-in account
  • History (Ctrl+H) — YouTube watch history
  • Playlists (Ctrl+P) — user's YouTube playlists (Liked videos, Watch later, custom playlists)
  • Trending (Ctrl+T) — YouTube trending videos
  • Shorts — YouTube Shorts with auto-play and keyboard navigation (↑/↓ to navigate, Escape to cancel)

GTK UI: Error Handling

  • When not logged in: shows dialog with "Login Now" button
  • When session expired: shows "YouTube session expired" dialog with clear instructions to re-login
  • When browser not found: shows error with manual instructions
  • All error dialogs use format_secondary_text for proper line breaks

GTK UI: Shorts Auto-play

  • Auto-plays next Short when current finishes (3s countdown)
  • ↑/↓ arrow keys navigate between Shorts
  • Escape cancels auto-play
  • Space pauses auto-play
  • Keyboard hints shown when entering Shorts mode

YouTube Data Parsing

  • Added lockupViewModel parser for YouTube's new video card format (used in trending, etc.)
  • Added reelShelfRenderer/shortsLockupViewModel parser for Shorts in subscription feed
  • Added compactVideoRenderer parser for watch history
  • Fixed critical eval/return Perl bug: return inside eval{} returns from the enclosing sub, not the eval block — replaced with do{} blocks

CLI

  • Added --yt-subs flag for subscription feed
  • Fixed --trending with empty category argument
  • Fixed format_time "Argument NA" warning

Files Changed

File Changes
bin/gtk-pipe-viewer Profile menu, Login dialog, Shorts auto-play, error handling
bin/pipe-viewer --yt-subs flag, trending fix
lib/WWW/PipeViewer.pm Cookie extraction, profile verification, eager loading
lib/WWW/PipeViewer/InitialData.pm YouTube data parsers, yt-dlp integration for playlists/shorts
lib/WWW/PipeViewer/Videos.pm New API methods (subscription_feed, youtube_history, youtube_playlists, youtube_shorts)
lib/WWW/PipeViewer/Utils.pm format_time NA fix
share/gtk-pipe-viewer.glade Profile submenu with all menu items
utils/extract-browser-cookies.py Cookie extraction with legacy alias creation

Testing

All features tested with real YouTube account:

  • Cookie extraction: 670+ cookies extracted, profile verified
  • Trending: returns real trending videos
  • Shorts: returns actual Shorts (under 60s)
  • Search: returns personalized results
  • Error handling: clear dialogs for all failure modes

Requirements

  • Chromium-based browser with YouTube login
  • pycryptodome Python package (for cookie decryption)
  • secretstorage Python package (for GNOME Keyring access)
  • yt-dlp (for playlists and shorts extraction)

ihorman added 26 commits July 8, 2026 18:29
Add the ability to automatically extract cookies from an installed
browser (Chromium, Firefox, Chrome, Brave, Edge, Opera, Vivaldi)
using yt-dlp's browser cookie extraction.

This allows pipe-viewer to access:
- Logged-in YouTube content
- Age-restricted videos
- Personalized search results and recommendations
- Members-only content

Usage:
  pipe-viewer --cookies-from-browser=chromium

Config file:
  cookies_from_browser => "chromium",

Changes:
- lib/WWW/PipeViewer.pm: Add cookies_from_browser option and
  _extract_browser_cookies() method. Cookies are extracted via
  yt-dlp and cached for 1 hour to avoid repeated extraction.
- bin/pipe-viewer: Add --cookies-from-browser CLI flag and POD docs.
- bin/gtk-pipe-viewer: Add cookies_from_browser config pass-through.
Major changes:
- Add Login with Browser menu item (Ctrl+L) with browser selection dialog
- Support browsers: chromium, chrome, firefox, brave, edge, opera, vivaldi
- Add profile verification after cookie extraction (checks for auth cookies)
- Add startup notification showing profile status
- Bundle Python helper for fast native cookie extraction (0.25s vs 10s)
- Add raw JSON ytInitialData parsing for desktop YouTube pages
- Add reload_cookies_from_browser() method for runtime re-login
- Add get_profile_loaded() and get_profile_username() accessors

The Login dialog:
1. User clicks Menu > Login with Browser (or Ctrl+L)
2. Selects browser from dropdown (chromium default)
3. Clicks OK to extract cookies
4. Shows success/failure notification in progress bar
5. On failure, shows dialog with troubleshooting tips
…ing empty category

- Pass cookies_from_browser to main thread yv_obj constructor
- Add YouTube History menu item (Ctrl+H)
- Add YouTube Trending menu item (Ctrl+T)
- Add display_youtube_history, display_youtube_trending, display_youtube_subscriptions handlers
- Add yt_youtube_history, _parse_video_renderer, _extract_videos_from_richGrid to InitialData.pm
- Add subscription_feed, youtube_history methods to Videos.pm
- Fix trending empty category crash
When cookies_from_browser is set, eagerly call set_lwp_useragent()
in the constructor so that profile_loaded is available immediately.
This fixes the startup notification and menu items that depend on
knowing the profile status.
- Add yt_youtube_trending() - scrapes m.youtube.com/feed/trending
- Add yt_youtube_history() - scrapes m.youtube.com/feed/history
- Add _parse_compact_video_renderer() for history format
- Handle richSectionRenderer in trending (category shelves)
- trending_videos_from_category() now tries YouTube scraping first
- All three features tested and working with cookies
- Add YouTube Shorts menu item (searches for short videos)
- Add shorts_autoplay config option (default: 1)
- When a Short finishes playing, auto-plays next after 2s countdown
- Progress bar shows 'Playing next Short in Ns...' countdown
- Press Escape to cancel auto-play at any time
- Auto-play cancels when navigating away (search, other menus)
- Uses mpv IPC socket to detect video end
- Clean state management for shorts mode
When cookies_from_browser or cookie_file is set, the Subscription
videos menu item now fetches from YouTube's subscription feed instead
of requiring a local subscribed_channels.txt file.
When not logged in, clicking Subscription videos now shows:
'Not logged in. Use Menu > Login with Browser to see your subscriptions.'
instead of crashing with 'No subscribed channels' error.
When user clicks Login with Browser and selects a browser that
is not running, the app now:
1. Launches the browser automatically
2. Waits up to 10s for it to start
3. Shows progress bar updates while waiting
4. Gives browser 3s to initialize after startup
5. Shows error dialog if browser can't be launched

Supported browsers: chromium, chrome, firefox, brave, edge, opera, vivaldi
- Add YouTube Playlists menu item (Ctrl+P)
- Uses yt-dlp to extract playlists (page loads dynamically)
- Shows: Liked videos, Watch later, and all user playlists
- Updated cookie extractor to copy google.com auth cookies to youtube.com
  (fixes API authentication for playlists, history, etc.)
- Added _find_cookie_file helper to locate cookies in multiple paths
- Added _parse_grid_playlist_renderer helper (unused but available)

Cookie extractor fix: SAPISID and other auth cookies from .google.com
are now duplicated to .youtube.com domain, enabling YouTube API access.
- Use yt-dlp with Shorts filter (sp=EgIYAQ%3D%3D) to fetch real Shorts
- Only includes videos under 60 seconds (actual Shorts format)
- Uses dedicated yt_youtube_shorts() method
- Searches for 'shorts' with the YouTube Shorts filter applied
- Handle richSectionRenderer with reelShelfRenderer in subscription feed
- Extract Shorts from shortsLockupViewModel with proper title parsing
- Remove view count from Shorts titles (e.g., ', 1,1 тысячи просмотров')
- Support Unicode quotes (U+201C/U+201D) in accessibility text
- Subscription feed now shows 4 items (3 videos + 1 Short)
Menu structure now:
  Menu > Saved channels
         Watched videos
         YouTube > Login with Browser
                   ---
                   Subscriptions
                   History
                   Playlists
                   ---
                   Trending
                   Shorts
         CLI Pipe Viewer
         Preferences
- Up/Down arrow keys navigate between Shorts in Shorts mode
- Space toggles auto-play pause
- Escape cancels auto-play
- Shows keyboard hints when entering Shorts mode
  'Shorts mode: ↑/↓ navigate, Enter play, Esc exit'
- play_next_short() uses play_adjacent_short() for consistency
- Shorts mode auto-selects first item for immediate navigation
…Model support

Critical fixes:
- Renamed 'YouTube' submenu to 'Profile'
- Fixed Perl eval/return bug in yt_youtube_trending, yt_subscription_feed,
  yt_youtube_history: 'return' inside eval{} returns from the enclosing
  sub, not the eval block. Replaced with do{} blocks using 'last' for
  early exit.
- Added lockupViewModel parser for YouTube's new video card format
  (_parse_lockup_view_model) — YouTube now uses lockupViewModel instead
  of videoWithContextRenderer in trending and other feeds
- Fixed stale '}' // [] leftover after history eval fix
- All 25 feature tests pass
- Login with Browser now opens YouTube login page when launching browser
  (https://accounts.google.com/ServiceLogin?continue=...)
- If not logged in, shows dialog: 'Not logged in to YouTube' with
  instructions and 'Open YouTube Login' button
- Added require_login() helper for all Profile menu items
- Subscriptions, History, Playlists show login dialog if not logged in
- Login dialog offers 'Login Now' button that opens the login flow
- Trending works without login
- Error dialogs use format_secondary_text for proper line breaks
- Extractor creates SAPISID/SID/SIDCC legacy aliases from __Secure-3P*
  cookies (YouTube moved to new cookie format)
- _find_cookie_file falls back to any cookies_from_*.txt if browser not set
- Fixed 'Argument NA isn't numeric' warning in format_time
- Profile check recognizes __Secure-3PAPISID/__Secure-1PSID cookies

NOTE: Subscriptions/History/Playlists return 0 because the YouTube
session cookies have expired for API use. The user needs to re-login
in the browser to get fresh cookies.
When Subscriptions/History/Playlists return empty results with cookies
configured, instead of generic error shows:
- 'YouTube session expired' dialog
- Step-by-step instructions to re-login
- 'Open YouTube Login' button to open browser
- 'Re-extract Cookies' button to run Login with Browser flow

Also:
- send_search_request no longer dies on empty results (was crashing)
- Error shows in progress bar for non-auth features
When browser is running, still opens the YouTube login URL in it.
When browser is not running, launches it with the login URL.
@trizen

trizen commented Jul 10, 2026

Copy link
Copy Markdown
Owner

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants