Phase 7 — strawcore wrapper now bridges to Sulkta-Coop/strawcore-core

Replaces the rustypipe-backed extraction with calls into the new
NPE-port crate. The UniFFI surface Kotlin sees is unchanged:

  suspend fun search(query: String): List<SearchItem>
  suspend fun streamInfo(input: String): StreamInfo
  suspend fun channelInfo(input: String): ChannelInfo
  fun initLogging()  // also wires the strawcore-core Downloader
  fun helloFromRust(name: String): String

rust/strawcore/
  * Cargo.toml      — dropped rustypipe + rquickjs-sys direct dep;
                      added strawcore-core path dep (../../../strawcore)
  * src/error.rs    — From<strawcore_core::ExtractionError>, mapping
                      ContentUnavailable variants to typed
                      StrawcoreError cases (AgeRestricted, GeoRestricted,
                      Private, RequiresLogin) instead of bucketing all
                      to Extractor
  * src/runtime.rs  — Once-guarded ReqwestDownloader init via
                      NewPipe::init_full
  * src/search.rs   — search() spawn_blocks core search_extractor::search
                      against SearchFilter::Videos
  * src/stream.rs   — stream_info() resolves URL → video_id via
                      strawcore_core::linkhandler::stream, then
                      spawn_blocks core stream_extractor::stream_info,
                      then maps StreamInfo → wrapper DTOs (combined/
                      video_only/audio_only/dash/hls)
  * src/channel.rs  — channel_info() parses input via
                      strawcore_core::linkhandler::channel (handle /
                      custom-url / legacy-user resolution lives in
                      core), then spawn_blocks core channel::channel_info

Build verified: wrapper compiles linking strawcore-core, uniffi-bindgen
generates Kotlin bindings with the same suspend fun + data class
surface Kotlin already consumes. Android NDK cross-compile + APK + on-
device smoke pending (needs crafting-table container).

This commits onto rollback/vc18-back-to-NPE — the existing Kotlin code
still calls NewPipeExtractor directly. Switching the Kotlin side to
consume the rust wrapper is a separate cutover.
This commit is contained in:
Kayos 2026-05-24 17:29:23 -07:00
parent 07e3163e62
commit 467a5f10fa
7 changed files with 250 additions and 309 deletions

View file

@ -1,21 +1,29 @@
// Tokio runtime singleton — rustypipe is async-first, so every exported
// function that touches the network needs to drive a runtime. Building one
// per call is wasteful; we build one shared multi-thread runtime at first
// use and `block_on` against it.
// Runtime bootstrap. Called once from Kotlin's StrawApp.onCreate via
// init_logging(). Wires the strawcore-core Downloader + Localization
// singleton so the extractor calls have an HTTP client to use.
use once_cell::sync::Lazy;
use tokio::runtime::Runtime;
use std::sync::{Arc, Once};
static RT: Lazy<Runtime> = Lazy::new(|| {
tokio::runtime::Builder::new_multi_thread()
.worker_threads(2) // Mobile — we don't need many. Most blocks are I/O.
.enable_all()
.thread_name("strawcore-tokio")
.build()
.expect("strawcore: failed to build tokio runtime")
});
use strawcore_core::downloader::ReqwestDownloader;
use strawcore_core::localization::{ContentCountry, Localization};
use strawcore_core::newpipe::NewPipe;
#[allow(dead_code)]
pub fn block_on<F: std::future::Future>(fut: F) -> F::Output {
RT.block_on(fut)
static INIT: Once = Once::new();
pub fn ensure_initialized() {
INIT.call_once(|| {
match ReqwestDownloader::new() {
Ok(dl) => {
NewPipe::init_full(
Arc::new(dl),
Localization::default(),
ContentCountry::default(),
);
log::info!("strawcore-core: downloader + localization initialized");
}
Err(e) => {
log::error!("strawcore-core: failed to build downloader: {e}");
}
}
});
}