strawcore/src/youtube
Sulkta 60dfbac6f2 channel: second-browse to Videos tab + parse lockupViewModel
Found via emulator smoke that channelInfo was returning empty
recent_videos list, breaking the subscriptions feed.

Two root causes:
1. First browse of a channel by browseId lands on the HOME tab in
   2026 YT, not Videos. Home uses sectionListRenderer, not the
   richGridRenderer my parser expected. The Videos tab in the
   response carries an empty content block (you need a SECOND
   browse with the params token to populate it).
2. Channel video items on the Videos tab migrated from
   videoRenderer to lockupViewModel (YT made the switch ~2024).
   My old parser only handled videoRenderer.

Fix:
* fetch_channel_browse now does TWO browses — first for Home
  (header + metadata), second with params='EgZ2aWRlb3PyBgQKAjoA'
  for the Videos tab. Same magic constant NPE uses (audit Track
  A §2.4).
* parse_videos_tab handles BOTH videoRenderer (legacy/fallback)
  AND lockupViewModel (current). lockupViewModel parse extracts:
    - contentId → video ID
    - metadata.lockupMetadataViewModel.title.content → title
    - metadataRows[].metadataParts[].text.content → view-count
      ('1.1m views') + relative-age ('2 years ago') + uploader
    - contentImage.thumbnailViewModel.overlays[]
      .thumbnailBottomOverlayViewModel.badges[]
      .thumbnailBadgeViewModel.text → duration ('3:14:08')
    - contentImage.thumbnailViewModel.image.sources[] → thumbnails
* parse_videos_continuation pulls the continuation token from the
  Videos tab grid for pagination.

Second browse is best-effort: if it fails, recent_videos stays
empty and the channel header still populates from the first.

Verified the YT response shape by probing live channel
UCwwtUfy0-CqN50HfaFDzL0w (NCS Spektrem) — got 30+ lockup-style
video items with the expected fields.
2026-05-24 20:06:43 -07:00
..
js Phase 2 — JS deobfuscator (rquickjs + ress) 2026-05-24 16:53:19 -07:00
linkhandler Phase 6 — Search + Channel + Playlist + LinkHandler 2026-05-24 17:16:14 -07:00
potoken Phase 5 — PoTokenProvider trait + stream_extractor wiring 2026-05-24 17:10:13 -07:00
channel.rs channel: second-browse to Videos tab + parse lockupViewModel 2026-05-24 20:06:43 -07:00
client_request.rs Phase 3 — InnerTube + itag 2026-05-24 16:57:47 -07:00
constants.rs Phase 3 — InnerTube + itag 2026-05-24 16:57:47 -07:00
itag.rs Phase 3 — InnerTube + itag 2026-05-24 16:57:47 -07:00
mod.rs Phase 6 — Search + Channel + Playlist + LinkHandler 2026-05-24 17:16:14 -07:00
parsing.rs Phase 4 (partial) — stream value types + InnerTube /player helpers 2026-05-24 17:01:03 -07:00
playlist_extractor.rs Phase 6 — Search + Channel + Playlist + LinkHandler 2026-05-24 17:16:14 -07:00
search_extractor.rs Phase 6 — Search + Channel + Playlist + LinkHandler 2026-05-24 17:16:14 -07:00
stream_extractor.rs Phase 5 — PoTokenProvider trait + stream_extractor wiring 2026-05-24 17:10:13 -07:00
stream_helper.rs Phase 4 (complete) — stream_extractor orchestrator 2026-05-24 17:08:04 -07:00
suggestion_extractor.rs Phase 6 — Search + Channel + Playlist + LinkHandler 2026-05-24 17:16:14 -07:00