strawcore/src/youtube/linkhandler/mod.rs
Sulkta 12b8865929 Cleanup: drop playlist + suggestion + dead client constants + suppress_unused stubs
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.
2026-05-26 22:16:11 -07:00

69 lines
2 KiB
Rust

// LinkHandler factories — URL parsing + URL building for YouTube
// resource categories. Mirrors NPE
// services/youtube/linkHandler/Youtube*LinkHandlerFactory.java.
//
// PORT SCOPE (per SPEC §6.6): we keep youtube.com / youtube-nocookie.com
// / youtu.be / m.youtube.com / music.youtube.com. The 27-host Invidious
// mirror list in NPE is dropped — Sulkta isn't an Invidious mirror.
pub mod channel;
pub mod search;
pub mod stream;
use thiserror::Error;
#[derive(Debug, Error)]
pub enum LinkError {
#[error("invalid url: {0}")]
InvalidUrl(String),
#[error("unsupported host: {0}")]
UnsupportedHost(String),
#[error("missing id in url: {0}")]
MissingId(String),
#[error("malformed id: {0}")]
MalformedId(String),
}
/// The acceptable hosts for first-party YT links. Audit Track D §6.
pub const ACCEPTED_HOSTS: &[&str] = &[
"youtube.com",
"www.youtube.com",
"m.youtube.com",
"music.youtube.com",
"youtu.be",
"www.youtube-nocookie.com",
];
pub fn host_is_youtube(host: &str) -> bool {
let h = host.to_ascii_lowercase();
let h = h.strip_prefix("www.").unwrap_or(&h);
ACCEPTED_HOSTS
.iter()
.any(|allowed| {
let allowed = allowed.strip_prefix("www.").unwrap_or(allowed);
allowed == h
})
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn accepts_first_party_hosts() {
assert!(host_is_youtube("www.youtube.com"));
assert!(host_is_youtube("youtube.com"));
assert!(host_is_youtube("m.youtube.com"));
assert!(host_is_youtube("music.youtube.com"));
assert!(host_is_youtube("youtu.be"));
assert!(host_is_youtube("WWW.YouTube.COM")); // case-insensitive
}
#[test]
fn rejects_invidious_and_random() {
assert!(!host_is_youtube("invidious.io"));
assert!(!host_is_youtube("yewtu.be"));
assert!(!host_is_youtube("piped.video"));
assert!(!host_is_youtube("evil.com"));
}
}