strawcore/src/youtube/constants.rs
Cobb 2452f1785d
Some checks failed
gitleaks / scan (push) Failing after 1s
npe-sync: visitorData + visionOS(101) + xtags audio typing (best-effort, additive)
Brings the port up to current NewPipe Extractor coverage:
- visitorData: fetched + attached to the anonymous reel/web/ios/visionos
  InnerTube contexts (upstream "always pass a valid visitorData"). Best-effort
  — a failure returns None and extraction proceeds exactly as before. Cached
  process-wide with a 15-min TTL, and invalidated when the primary android
  response is rejected (decoy/playability) so a bad session self-heals.
- visionOS client (101): a 4th /player fetch, ON by default, recovering >360p
  streams for SABR-only / made-for-kids videos where android/ios cap at 360p.
  Formats merged android-first (android wins itag ties); a failure changes
  nothing. HLS + DASH manifest branches now skip empty urls (an empty visionOS
  url no longer shadows a real ios/android one).
- xtags: derive audio track type (original/dubbed/descriptive/secondary) from
  the format xtags protobuf, falling back to the audioIsDefault heuristic when
  absent. Hand-rolled protobuf walker, fuzzed (4M inputs, no panic); 32-bit
  length guarded via try_from.

FFI surface unchanged (AudioStream gains an additive track_type the wrapper
may later surface). 155 lib + 7 integration tests, clippy -D clean.
2026-07-29 07:07:42 -07:00

57 lines
2.7 KiB
Rust

// InnerTube client constants. Active clients: WEB, WEB_EMBEDDED_PLAYER,
// ANDROID, IOS. WEB_REMIX (music) and WEB_MUSIC_ANALYTICS were ported
// but never wired through — dropped 2026-05-26 along with the music
// SearchFilter variants and the of_web_music_analytics_charts_client
// factory.
pub const DESKTOP_CLIENT_PLATFORM: &str = "DESKTOP";
pub const MOBILE_CLIENT_PLATFORM: &str = "MOBILE";
pub const WATCH_CLIENT_SCREEN: &str = "WATCH";
pub const EMBED_CLIENT_SCREEN: &str = "EMBED";
pub const WEB_CLIENT_ID: &str = "1";
pub const WEB_CLIENT_NAME: &str = "WEB";
pub const WEB_HARDCODED_CLIENT_VERSION: &str = "2.20260120.01.00";
pub const WEB_EMBEDDED_CLIENT_ID: &str = "56";
pub const WEB_EMBEDDED_CLIENT_NAME: &str = "WEB_EMBEDDED_PLAYER";
pub const WEB_EMBEDDED_CLIENT_VERSION: &str = "1.20260122.01.00";
// iPhone 15 Pro Max — chosen explicitly for 60fps tags per ItagItem.java:26
// note and the gist referenced in NPE source.
pub const IOS_CLIENT_ID: &str = "5";
pub const IOS_CLIENT_NAME: &str = "IOS";
pub const IOS_CLIENT_VERSION: &str = "21.03.2";
pub const IOS_DEVICE_MODEL: &str = "iPhone16,2";
pub const IOS_OS_VERSION: &str = "18.7.2.22H124";
pub const IOS_USER_AGENT_VERSION: &str = "18_7_2";
pub const ANDROID_CLIENT_ID: &str = "3";
pub const ANDROID_CLIENT_NAME: &str = "ANDROID";
pub const ANDROID_CLIENT_VERSION: &str = "21.03.36";
// NPE hard-codes androidSdkVersion=36 + osVersion=16 even though the
// User-Agent advertises Android 15. DroidGuard doesn't check the
// InnerTube context so this mismatch is intentional and not a bug.
pub const ANDROID_SDK_VERSION: u32 = 36;
pub const ANDROID_OS_VERSION: &str = "16";
// visionOS client (client 101). A best-effort 4th /player fetch that recovers
// >360p streams for SABR-only / "made for kids" videos where the ANDROID/IOS
// clients cap at a single 360p muxed stream. Values from NPE
// ClientsConstants.java (commit 82b7e410, "Workaround again SABR-only
// responses"). Carries NO poToken.
pub const VISIONOS_CLIENT_ID: &str = "101";
pub const VISIONOS_CLIENT_NAME: &str = "VISIONOS";
pub const VISIONOS_CLIENT_VERSION: &str = "1.02";
pub const VISIONOS_DEVICE_MODEL: &str = "RealityDevice14,1";
pub const VISIONOS_OS_VERSION: &str = "25.6.0.23O471";
pub const VISIONOS_USER_AGENT_VERSION: &str = "25_6_0";
// Base URLs (NPE YoutubeParsingHelper.java:91,96).
pub const YOUTUBEI_V1_URL: &str = "https://www.youtube.com/youtubei/v1/";
pub const YOUTUBEI_V1_GAPIS_URL: &str = "https://youtubei.googleapis.com/youtubei/v1/";
pub const YOUTUBE_MUSIC_INNERTUBE_URL: &str = "https://music.youtube.com/youtubei/v1/";
// All InnerTube calls carry this query suffix to shrink responses.
pub const DISABLE_PRETTY_PRINT_PARAM: &str = "?prettyPrint=false";