sxyprn fix?
This commit is contained in:
@@ -21,7 +21,7 @@ fn boo(sum1: u32, sum2: u32) -> String {
|
||||
}
|
||||
|
||||
/// Extracts all CDN path values from the data-vnfo JSON attribute.
|
||||
fn extract_all_cdn_paths(html: &str) -> Vec<String> {
|
||||
pub(crate) fn extract_all_cdn_paths(html: &str) -> Vec<String> {
|
||||
let json_str = match html.split("data-vnfo='").nth(1) {
|
||||
Some(s) => s.split('\'').next().unwrap_or(""),
|
||||
None => return vec![],
|
||||
@@ -53,7 +53,7 @@ fn extract_all_cdn_paths(html: &str) -> Vec<String> {
|
||||
}
|
||||
|
||||
/// Applies the sxyprn segment transformation to produce the pre-redirect CDN URL.
|
||||
fn transform_cdn_path(path: &str) -> Option<String> {
|
||||
pub(crate) fn transform_cdn_path(path: &str) -> Option<String> {
|
||||
let mut tmp: Vec<String> = path.split('/').map(|s| s.to_string()).collect();
|
||||
if tmp.len() < 8 {
|
||||
return None;
|
||||
@@ -101,6 +101,68 @@ async fn race_cdn_urls(candidate_urls: Vec<String>) -> String {
|
||||
.unwrap_or_default()
|
||||
}
|
||||
|
||||
/// Resolves all candidate CDN mirror URLs concurrently, collecting every
|
||||
/// mirror that redirects successfully within the timeout window. Unlike
|
||||
/// `race_cdn_urls`, this does not stop at the first success -- the mirrors
|
||||
/// are redundant copies of the same stream, and callers that want to serve
|
||||
/// directly-playable format URLs need as many working ones as possible.
|
||||
pub(crate) async fn resolve_all_cdn_urls(candidate_urls: Vec<String>) -> Vec<String> {
|
||||
if candidate_urls.is_empty() {
|
||||
return vec![];
|
||||
}
|
||||
|
||||
let handles: Vec<_> = candidate_urls
|
||||
.into_iter()
|
||||
.map(|cdn_url| {
|
||||
tokio::spawn(async move {
|
||||
tokio::task::spawn_blocking(move || {
|
||||
crate::util::get_redirect_location(&cdn_url)
|
||||
.ok()
|
||||
.flatten()
|
||||
.map(|loc| format!("https:{}", loc))
|
||||
})
|
||||
.await
|
||||
.ok()
|
||||
.flatten()
|
||||
})
|
||||
})
|
||||
.collect();
|
||||
|
||||
let deadline = tokio::time::Instant::now() + Duration::from_secs(15);
|
||||
let mut resolved = Vec::new();
|
||||
for handle in handles {
|
||||
if let Ok(Ok(Some(url))) = tokio::time::timeout_at(deadline, handle).await {
|
||||
if !resolved.contains(&url) {
|
||||
resolved.push(url);
|
||||
}
|
||||
}
|
||||
}
|
||||
resolved
|
||||
}
|
||||
|
||||
/// Fetches the sxyprn detail page for `slug` and resolves every mirror CDN
|
||||
/// URL it advertises. Used by the provider to eagerly populate `formats`
|
||||
/// for app clients, instead of the lazy single-mirror `/proxy/sxyprn/...`
|
||||
/// redirect used by other clients.
|
||||
pub(crate) async fn resolve_all_media_urls(
|
||||
requester: &mut Requester,
|
||||
base_url: &str,
|
||||
slug: &str,
|
||||
) -> Vec<String> {
|
||||
let full_url = format!("{}/post/{}", base_url, slug);
|
||||
let text = requester.get(&full_url, None).await.unwrap_or_default();
|
||||
if text.is_empty() {
|
||||
return vec![];
|
||||
}
|
||||
|
||||
let candidate_urls: Vec<String> = extract_all_cdn_paths(&text)
|
||||
.iter()
|
||||
.filter_map(|p| transform_cdn_path(p))
|
||||
.collect();
|
||||
|
||||
resolve_all_cdn_urls(candidate_urls).await
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct SxyprnProxy {}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user