porn4fans fix

This commit is contained in:
Simon
2026-03-13 12:53:33 +00:00
parent 6a62582c09
commit 0137313c6e
4 changed files with 115 additions and 192 deletions

View File

@@ -1,6 +1,5 @@
use ntex::web;
use crate::proxies::porn4fans::Porn4fansProxy;
use crate::proxies::spankbang::SpankbangProxy;
use crate::{proxies::sxyprn::SxyprnProxy, util::requester::Requester};
@@ -8,13 +7,11 @@ pub mod hanimecdn;
pub mod hqpornerthumb;
pub mod javtiful;
pub mod noodlemagazine;
pub mod porn4fans;
pub mod spankbang;
pub mod sxyprn;
#[derive(Debug, Clone)]
pub enum AnyProxy {
Porn4fans(Porn4fansProxy),
Sxyprn(SxyprnProxy),
Javtiful(javtiful::JavtifulProxy),
Spankbang(SpankbangProxy),
@@ -27,7 +24,6 @@ pub trait Proxy {
impl Proxy for AnyProxy {
async fn get_video_url(&self, url: String, requester: web::types::State<Requester>) -> String {
match self {
AnyProxy::Porn4fans(p) => p.get_video_url(url, requester).await,
AnyProxy::Sxyprn(p) => p.get_video_url(url, requester).await,
AnyProxy::Javtiful(p) => p.get_video_url(url, requester).await,
AnyProxy::Spankbang(p) => p.get_video_url(url, requester).await,

View File

@@ -1,146 +0,0 @@
use ntex::web;
use regex::Regex;
use crate::util::requester::Requester;
#[derive(Debug, Clone)]
pub struct Porn4fansProxy {}
impl Porn4fansProxy {
pub fn new() -> Self {
Porn4fansProxy {}
}
fn request_headers() -> Vec<(String, String)> {
vec![(
"Referer".to_string(),
"https://www.porn4fans.com/".to_string(),
)]
}
fn normalize_page_url(url: &str) -> String {
if url.starts_with("http://") || url.starts_with("https://") {
return url.to_string();
}
let trimmed = url.trim_start_matches('/');
if trimmed.starts_with("www.porn4fans.com/") || trimmed.starts_with("porn4fans.com/") {
return format!("https://{trimmed}");
}
format!("https://www.porn4fans.com/{trimmed}")
}
fn decode_escaped_text(text: &str) -> String {
text.replace("\\/", "/").replace("&amp;", "&")
}
fn extract_preferred_video_url(text: &str) -> Option<String> {
let decoded = Self::decode_escaped_text(text);
let video_url_re = Regex::new(
r#"(?is)(?:^|[{\s,])["']?video_url["']?\s*[:=]\s*["'](?P<url>https?://[^"'<>]+?\.mp4/?(?:\?[^"'<>]*)?)["']"#,
)
.ok()?;
if let Some(url) = video_url_re
.captures(&decoded)
.and_then(|captures| captures.name("url"))
.map(|value| value.as_str().to_string())
{
return Some(url);
}
let generic_mp4_re = Regex::new(
r#"(?is)(?P<url>https?://[^"'<>\s]+/get_file/[^"'<>\s]+?\.mp4/?(?:\?[^"'<>]*)?)"#,
)
.ok()?;
generic_mp4_re
.captures(&decoded)
.and_then(|captures| captures.name("url"))
.map(|value| value.as_str().to_string())
}
fn extract_rnd(text: &str) -> Option<String> {
let decoded = Self::decode_escaped_text(text);
let rnd_re =
Regex::new(r#"(?is)(?:^|[{\s,])["']?rnd["']?\s*[:=]\s*["']?(?P<rnd>\d{8,})"#).ok()?;
rnd_re
.captures(&decoded)
.and_then(|captures| captures.name("rnd"))
.map(|value| value.as_str().to_string())
}
fn attach_rnd(url: String, rnd: Option<String>) -> String {
if url.is_empty() || url.contains("rnd=") {
return url;
}
let Some(rnd) = rnd else {
return url;
};
let separator = if url.contains('?') { '&' } else { '?' };
format!("{url}{separator}rnd={rnd}")
}
pub async fn get_video_url(
&self,
url: String,
requester: web::types::State<Requester>,
) -> String {
let mut requester = requester.get_ref().clone();
let page_url = Self::normalize_page_url(&url);
let text = requester
.get_with_headers(&page_url, Self::request_headers(), None)
.await
.unwrap_or_default();
if text.is_empty() {
return String::new();
}
let Some(video_url) = Self::extract_preferred_video_url(&text) else {
return String::new();
};
Self::attach_rnd(video_url, Self::extract_rnd(&text))
}
}
#[cfg(test)]
mod tests {
use super::Porn4fansProxy;
#[test]
fn extracts_video_url_and_appends_rnd() {
let html = r#"
<script>
var flashvars = {
video_url: 'https:\/\/www.porn4fans.com\/get_file\/3\/9df8de1fc2da5dfcbf9a4ad512dc8f306c4997e60f\/10000\/10951\/10951.mp4\/',
video_alt_url: 'https:\/\/www.porn4fans.com\/get_file\/3\/9df8de1fc2da5dfcbf9a4ad512dc8f306c4997e60f\/10000\/10951\/10951_720p.mp4\/',
rnd: '1773402926076'
};
</script>
"#;
let video_url = Porn4fansProxy::extract_preferred_video_url(html).unwrap();
assert_eq!(
Porn4fansProxy::attach_rnd(video_url, Porn4fansProxy::extract_rnd(html)),
"https://www.porn4fans.com/get_file/3/9df8de1fc2da5dfcbf9a4ad512dc8f306c4997e60f/10000/10951/10951.mp4/?rnd=1773402926076"
);
}
#[test]
fn normalizes_relative_proxy_target() {
assert_eq!(
Porn4fansProxy::normalize_page_url("video/10951/example/"),
"https://www.porn4fans.com/video/10951/example/"
);
assert_eq!(
Porn4fansProxy::normalize_page_url("www.porn4fans.com/video/10951/example/"),
"https://www.porn4fans.com/video/10951/example/"
);
}
}