Fix broken-playback providers (wowxxx, porndish, noodlemagazine) and a shared 429 retry bug
- wowxxx: site migrated wow.xxx -> wowxxx.to; update BASE_URL and stop pinning Version::HTTP_11, which mismatched the TLS handshake's h2 ALPN and got scored as a bot (same root cause already fixed for jable.tv) - porndish: recognize playmogo.com iframes as the same Doodstream-clone embed protocol as myvidplay.com (confirmed live) instead of falling through to a naive branch that pointed formats[0] at the unresolved, Cloudflare-protected iframe URL; kept in sync in both providers/porndish.rs and proxies/porndish.rs since single-provider builds can't share code across that boundary - noodlemagazine: entity-decode the thumb URL pulled from a raw data-original="..." attribute - undecoded `&` in the query string was getting the CDN to 400 the request - requester.rs: cap the previously-unbounded HTTP 429 retry loop at 3 attempts before falling through to the existing Jina/FlareSolverr fallback, instead of retrying forever with no bound Also fixes check.py: the thumbnail check never consulted the CF-protected-host allowlist (only the page-url check did), and adds missav.ws/surrit.com, tik.porn/image-cdn.tik.porn, vrporn.com, and www.wowxxx.to/img.wowxxx.to to that allowlist - all four providers already work fine through the app's real client; the checker's plain probes (and its yt-dlp invocation, which never applies a channel's declared ytdlpCommand impersonation flag) just can't replicate that. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QTqf6orbHZ9rFFpVpcgzcR
This commit is contained in:
@@ -528,6 +528,13 @@ impl NoodlemagazineProvider {
|
||||
.filter_map(|captures| captures.name("url").map(|value| value.as_str().to_string()))
|
||||
.find(|candidate| !candidate.starts_with("data:image/"))
|
||||
})
|
||||
.map(|thumb| {
|
||||
// HTML attributes encode `&` as `&`; the raw regex match
|
||||
// above needs decoding or a query string like `...&idx=0&type=39`
|
||||
// survives as the literal text `...&idx=0&type=39`,
|
||||
// which the CDN rejects with HTTP 400.
|
||||
decode(thumb.as_bytes()).to_string().unwrap_or(thumb)
|
||||
})
|
||||
.unwrap_or_default();
|
||||
|
||||
let raw_duration = video_segment
|
||||
@@ -699,6 +706,34 @@ mod tests {
|
||||
assert!(items[1].thumb.is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn decodes_html_entities_in_thumb_query_string() {
|
||||
// Real markup HTML-encodes `&` as `&` in attribute values; the
|
||||
// raw-HTML parsing path used to pass that straight through, leaving
|
||||
// a literal `&` in the thumb URL that the CDN rejected (HTTP 400).
|
||||
let provider = NoodlemagazineProvider::new();
|
||||
let options = options();
|
||||
let html = r#"
|
||||
<div class="list_videos" id="list_videos">
|
||||
<div class="item">
|
||||
<a href="/watch/-111_222">
|
||||
<img data-src="https://img.pvvstream.pro/preview/abc/-111_222/240/iv.okcdn.ru/getVideoPreview?id=1&idx=0&type=39&tkn=xyz" />
|
||||
</a>
|
||||
<div class="title">sample</div>
|
||||
<svg><use></use></svg>#clock-o"></use></svg>12:34<
|
||||
<svg><use></use></svg>#eye"></use></svg>1.2K<
|
||||
</div>
|
||||
>Show more</div>
|
||||
"#;
|
||||
|
||||
let items = provider.get_video_items_from_html(html.to_string(), &options);
|
||||
assert_eq!(items.len(), 1);
|
||||
assert_eq!(
|
||||
items[0].thumb,
|
||||
"https://example.com/proxy/noodlemagazine-thumb/img.pvvstream.pro/preview/abc/-111_222/240/iv.okcdn.ru/getVideoPreview?id=1&idx=0&type=39&tkn=xyz"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn keeps_preview_urls_without_file_extension() {
|
||||
let provider = NoodlemagazineProvider::new();
|
||||
|
||||
Reference in New Issue
Block a user