clapdat
This commit is contained in:
113
src/proxies/clapdat.rs
Normal file
113
src/proxies/clapdat.rs
Normal file
@@ -0,0 +1,113 @@
|
||||
use ntex::web;
|
||||
use regex::Regex;
|
||||
|
||||
use crate::util::requester::Requester;
|
||||
|
||||
const BASE_URL: &str = "https://www.clapdat.com";
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct ClapdatProxy {}
|
||||
|
||||
impl ClapdatProxy {
|
||||
pub fn new() -> Self {
|
||||
Self {}
|
||||
}
|
||||
|
||||
fn normalize_detail_url(endpoint: &str) -> Option<String> {
|
||||
let value = endpoint.trim().trim_start_matches('/');
|
||||
if value.is_empty() {
|
||||
return None;
|
||||
}
|
||||
|
||||
let detail_url = if value.starts_with("http://") || value.starts_with("https://") {
|
||||
value.to_string()
|
||||
} else {
|
||||
format!("https://{}", value)
|
||||
};
|
||||
|
||||
let detail_url = detail_url.replacen("http://", "https://", 1);
|
||||
let parsed = url::Url::parse(&detail_url).ok()?;
|
||||
let host = parsed.host_str()?;
|
||||
if !(host == "www.clapdat.com" || host == "clapdat.com") {
|
||||
return None;
|
||||
}
|
||||
if !parsed.path().starts_with("/video/") {
|
||||
return None;
|
||||
}
|
||||
|
||||
Some(detail_url)
|
||||
}
|
||||
|
||||
fn clapdat_decode(input: &str) -> Option<Vec<u8>> {
|
||||
let compact = if input.len() > 209 {
|
||||
format!("{}{}", &input[..19], &input[209..])
|
||||
} else {
|
||||
input.to_string()
|
||||
};
|
||||
|
||||
let cleaned: String = compact
|
||||
.chars()
|
||||
.filter(|c| c.is_ascii_alphanumeric() || *c == '+' || *c == '/')
|
||||
.collect();
|
||||
if cleaned.is_empty() {
|
||||
return None;
|
||||
}
|
||||
|
||||
let mut padded = cleaned;
|
||||
while padded.len() % 4 != 0 {
|
||||
padded.push('=');
|
||||
}
|
||||
|
||||
base64::Engine::decode(&base64::engine::general_purpose::STANDARD, padded.as_bytes()).ok()
|
||||
}
|
||||
|
||||
fn extract_media_url(html: &str) -> Option<String> {
|
||||
let domain_re = Regex::new(r#"file_domain:"([^"]+)""#).ok()?;
|
||||
let file_re = Regex::new(r#"file:"([^"]+)""#).ok()?;
|
||||
let domain = domain_re
|
||||
.captures(html)
|
||||
.and_then(|caps| caps.get(1).map(|m| m.as_str().trim().to_string()))?;
|
||||
let encoded = file_re
|
||||
.captures(html)
|
||||
.and_then(|caps| caps.get(1).map(|m| m.as_str().trim().to_string()))?;
|
||||
|
||||
let decoded = Self::clapdat_decode(&encoded)?;
|
||||
let path: String = decoded.into_iter().map(char::from).collect();
|
||||
if path.is_empty() {
|
||||
return None;
|
||||
}
|
||||
Some(format!("https://{}/{}", domain, path.trim_start_matches('/')))
|
||||
}
|
||||
}
|
||||
|
||||
impl crate::proxies::Proxy for ClapdatProxy {
|
||||
async fn get_video_url(&self, url: String, requester: web::types::State<Requester>) -> String {
|
||||
let Some(detail_url) = Self::normalize_detail_url(&url) else {
|
||||
return String::new();
|
||||
};
|
||||
|
||||
let mut requester = requester.get_ref().clone();
|
||||
let headers = vec![
|
||||
(
|
||||
"accept".to_string(),
|
||||
"text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8".to_string(),
|
||||
),
|
||||
("accept-language".to_string(), "en-US,en;q=0.8".to_string()),
|
||||
(
|
||||
"user-agent".to_string(),
|
||||
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36".to_string(),
|
||||
),
|
||||
("referer".to_string(), BASE_URL.to_string()),
|
||||
];
|
||||
|
||||
let html = requester
|
||||
.get_with_headers(&detail_url, headers, Some(wreq::Version::HTTP_11))
|
||||
.await
|
||||
.unwrap_or_default();
|
||||
if html.is_empty() {
|
||||
return String::new();
|
||||
}
|
||||
|
||||
Self::extract_media_url(&html).unwrap_or_default()
|
||||
}
|
||||
}
|
||||
@@ -61,23 +61,29 @@ impl LulustreamProxy {
|
||||
) -> String {
|
||||
let mut requester = requester.get_ref().clone();
|
||||
let Some((detail_url, video_id)) = Self::normalize_detail_request(&url) else {
|
||||
println!("LulustreamProxy: Invalid detail URL: {url}");
|
||||
return String::new();
|
||||
};
|
||||
let mut text = requester.get(&detail_url, None).await.unwrap_or_default();
|
||||
println!("LulustreamProxy: Normalized detail URL: {:?}", format!("https://luluvid.com/e/{video_id}"));
|
||||
let mut text = requester.get(format!("https://luluvid.com/e/{video_id}").as_str(), None).await.unwrap_or_default();
|
||||
if !text.contains("[{file:\"") {
|
||||
let packedtext = text.split("<script type='text/javascript'>").nth(1).and_then(|t| t.split("</script>").next()).unwrap_or_default();
|
||||
println!("LulustreamProxy: Found packed text: {packedtext}");
|
||||
text = dean_edwards::unpack(&packedtext).unwrap_or_default();
|
||||
println!("LulustreamProxy: Unpacked text: {text}");
|
||||
}
|
||||
let video_url = text.split("[{file:\"")
|
||||
.nth(1)
|
||||
.and_then(|s| s.split('"').next())
|
||||
.unwrap_or_default()
|
||||
.to_string();
|
||||
println!("LulustreamProxy: Extracted video URL: {video_url}");
|
||||
println!("LulustreamProxy: Extracted video URL: {}", video_url);
|
||||
let test_request = requester.get_raw_with_headers(video_url.as_str(), vec![
|
||||
("Accept-Language".to_string(), "en-US,en;q=0.9".to_string()),
|
||||
("Referer".to_string(), detail_url.clone()),
|
||||
("User-Agent".to_string(), "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36".to_string())
|
||||
]).await.unwrap();
|
||||
println!("LulustreamProxy: Test request status: {}", test_request.status());
|
||||
|
||||
video_url
|
||||
// return "https://cdn1004.cdn-tnmr.org/hls2/01/03256/cssckmym0ibf_h/master.m3u8?t=Y2jXSIPERwSec0L6RSAOIPFAW53dQ0UgslngqGnF0go&s=1778507711&e=28800&f=16283923&i=0.3&sp=0".to_string();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
use crate::proxies::archivebate::ArchivebateProxy;
|
||||
use crate::proxies::clapdat::ClapdatProxy;
|
||||
use crate::proxies::doodstream::DoodstreamProxy;
|
||||
use crate::proxies::heavyfetish::HeavyfetishProxy;
|
||||
use crate::proxies::hqporner::HqpornerProxy;
|
||||
@@ -15,6 +16,7 @@ use crate::proxies::vidara::VidaraProxy;
|
||||
use crate::proxies::lulustream::LulustreamProxy;
|
||||
|
||||
pub mod archivebate;
|
||||
pub mod clapdat;
|
||||
pub mod doodstream;
|
||||
pub mod hanimecdn;
|
||||
pub mod heavyfetish;
|
||||
@@ -50,6 +52,7 @@ pub enum AnyProxy {
|
||||
Heavyfetish(HeavyfetishProxy),
|
||||
Vjav(VjavProxy),
|
||||
Vidara(VidaraProxy),
|
||||
Clapdat(ClapdatProxy),
|
||||
}
|
||||
|
||||
pub trait Proxy {
|
||||
@@ -73,6 +76,7 @@ impl Proxy for AnyProxy {
|
||||
AnyProxy::Heavyfetish(p) => p.get_video_url(url, requester).await,
|
||||
AnyProxy::Vjav(p) => p.get_video_url(url, requester).await,
|
||||
AnyProxy::Vidara(p) => p.get_video_url(url, requester).await,
|
||||
AnyProxy::Clapdat(p) => p.get_video_url(url, requester).await,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user