Round-2 cruft audit punch list — mechanical deletes, no behavior change.
Whole modules deleted (no wrapper consumer):
* youtube/playlist_extractor.rs (297 LOC) — full playlist extraction
* youtube/linkhandler/playlist.rs (81 LOC) — playlist URL parser
* youtube/suggestion_extractor.rs (91 LOC) — search-as-you-type
* tests/stream_phase4_offline.rs (186 LOC) — tautological test
Dead pub fns + enum variants + constants:
* WEB_REMIX_* constants (3) + WEB_MUSIC_ANALYTICS_* constants (3)
* InnertubeClientRequestInfo::of_web_music_analytics_charts_client
factory + its charts_client_omits_platform_and_screen test
* SearchFilter::Music{Songs,Videos,Albums,Playlists,Artists} variants
(5 of 9 cases) + uses_music_endpoint helper + the search_extractor
'music search not implemented' reject branch
* Two #[allow(dead_code)] _suppress_unused stub fns and the imports
they were keeping alive (std::sync::Arc in js/extractor.rs,
NetworkError in stream_extractor.rs)
Renamed:
* search_extractor::test_helpers -> renderer_helpers. Mis-named:
it's production code called from channel.rs, not a test fixture.
potoken/ kept and documented as the designed Phase-5 extension point
for YouTube bot-detection — wrapper's Android side hasn't registered
a real provider yet, but the trait + global slot stay so when YT
forces po_token universally the integration is one Kotlin patch away,
not a Rust-side rewrite.
~580 LOC removed from production. Wrapper does not need to change.
67 lines
1.9 KiB
Rust
67 lines
1.9 KiB
Rust
// YoutubeSearchQueryHandlerFactory + search filters. Filter params are
|
|
// opaque base64 protobufs — NPE doesn't decode them, just sends the
|
|
// magic strings. We mirror that. See audit Track D §3.
|
|
//
|
|
// Music* filter variants were ported from NPE but never wired through
|
|
// (search_extractor rejected anything with `uses_music_endpoint()`).
|
|
// Dropped 2026-05-26 along with WEB_REMIX_* constants + the music
|
|
// charts client factory.
|
|
|
|
use url::form_urlencoded;
|
|
|
|
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
|
|
pub enum SearchFilter {
|
|
/// All result types — no params field sent.
|
|
All,
|
|
/// Videos only.
|
|
Videos,
|
|
/// Channels only.
|
|
Channels,
|
|
/// Playlists only.
|
|
Playlists,
|
|
}
|
|
|
|
impl SearchFilter {
|
|
/// Returns the InnerTube `params` base64 string. None means omit
|
|
/// the field entirely (== All).
|
|
pub fn params(&self) -> Option<&'static str> {
|
|
match self {
|
|
SearchFilter::All => None,
|
|
SearchFilter::Videos => Some("EgIQAfABAQ%3D%3D"),
|
|
SearchFilter::Channels => Some("EgIQAvABAQ%3D%3D"),
|
|
SearchFilter::Playlists => Some("EgIQA_ABAQ%3D%3D"),
|
|
}
|
|
}
|
|
}
|
|
|
|
pub fn search_url(query: &str) -> String {
|
|
let encoded: String = form_urlencoded::Serializer::new(String::new())
|
|
.append_pair("search_query", query)
|
|
.finish();
|
|
format!("https://www.youtube.com/results?{encoded}")
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
|
|
#[test]
|
|
fn all_filter_omits_params() {
|
|
assert!(SearchFilter::All.params().is_none());
|
|
}
|
|
|
|
#[test]
|
|
fn typed_filters_have_params() {
|
|
assert!(SearchFilter::Videos.params().is_some());
|
|
assert!(SearchFilter::Channels.params().is_some());
|
|
assert!(SearchFilter::Playlists.params().is_some());
|
|
}
|
|
|
|
#[test]
|
|
fn search_url_encodes_query() {
|
|
assert_eq!(
|
|
search_url("rust + ferris"),
|
|
"https://www.youtube.com/results?search_query=rust+%2B+ferris"
|
|
);
|
|
}
|
|
}
|