porn4fans fix
This commit is contained in:
@@ -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,
|
||||
|
||||
@@ -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("&", "&")
|
||||
}
|
||||
|
||||
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/"
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user