Rust port of NewPipeExtractor (YT-only). Plugs into Straw via UniFFI.
Find a file
Kayos b4286b8236 Phase 5 — PoTokenProvider trait + stream_extractor wiring
Mirrors NPE PoTokenProvider.java + PoTokenResult.java; defines the
host-injection surface for BotGuard attestation. The Rust crate stays
out of the BotGuard business — embedders (Straw on Android, future
Sulkta CLI via Browserless, etc.) supply their own impl.

src/youtube/potoken/mod.rs
  * PoTokenResult { player_request_po_token, streaming_data_po_token,
                    visitor_data }  + ::new + ::single constructors
  * PoTokenError (Unavailable, MintFailed) — FIX vs NPE: split 'declined'
    (Ok(None)) from 'errored' (Err) so callers can react differently
  * trait PoTokenProvider with 4 client-scoped methods; default impl
    returns Ok(None) so embedders can override just what they support
  * set_po_token_provider / clear_po_token_provider / po_token_provider
    static registration via RwLock<Option<Arc<dyn PoTokenProvider>>>

src/youtube/potoken/noop.rs
  * NoopPoTokenProvider — safe default

src/youtube/stream_extractor.rs
  * resolve_po_token via options-first-then-provider helper
    (options_or_provider)
  * Android branch: pulls player_request_po_token + visitor_data into
    /player body, streams streaming_data_po_token through to URL &pot=
  * iOS branch: same shape, gated on fetch_ios_client AND non-empty
    provider result

Kotlin side (PoTokenWebView lift into Straw via UniFFI's foreign-trait
bridge) is separate work — strawcore just owns the contract.

Tests: 77 lib unit pass (+4 since Phase 4) + 7 Phase 2 offline + 7
Phase 4 offline = 91 green.
2026-05-24 17:10:13 -07:00
src Phase 5 — PoTokenProvider trait + stream_extractor wiring 2026-05-24 17:10:13 -07:00
tests Phase 4 (complete) — stream_extractor orchestrator 2026-05-24 17:08:04 -07:00
.gitignore Initial commit 2026-05-24 16:26:57 -07:00
Cargo.lock Phase 2 — JS deobfuscator (rquickjs + ress) 2026-05-24 16:53:19 -07:00
Cargo.toml Phase 2 — JS deobfuscator (rquickjs + ress) 2026-05-24 16:53:19 -07:00
LICENSE Initial commit 2026-05-24 16:26:57 -07:00
README.md Phase 1 — Foundation 2026-05-24 16:32:36 -07:00

strawcore

Rust port of NewPipeExtractor (v0.26.2), YouTube-only. Plugs into Straw via UniFFI.

Why this exists

rustypipe regex-parses YouTube's player.js and reimplements the signature deobfuscator in Rust. Every YT player rotation breaks it. NPE embeds Mozilla Rhino and executes the JS function live — resilient by design, and that's the architecture we're mirroring.

The rustypipe-backed Straw build (vc=15..17) also routed playback through iOS-progressive URLs, which hit a server-side ~917 KiB end-byte cap. NPE uses the Android client + po_token → DASH manifest path, which doesn't see the cap. Same fix, different layer.

See memory/npe-audit-2026-05-24/SPEC.md in the workspace repo for the full plan.

Status

Phase Subsystem Status
1 Foundation (downloader + service spine) in progress
2 JS engine (rquickjs + ress) pending
3 InnerTube + itag table pending
4 Stream extractor + DASH pending
5 PoTokenProvider trait + Android JNI bridge pending
6 Search + Channel + Playlist + Kiosks pending
7 UniFFI surface swap pending
8 Delete rustypipe everywhere pending

Build + test

cargo build
cargo test --lib                          # offline unit tests
cargo test --features online-tests        # full smoke incl. live httpbin.org

License

GPL-3.0-or-later. NPE is GPL-3.0; this port inherits.