diff --git a/src/providers/pimpbunny.rs b/src/providers/pimpbunny.rs index fc669ca..f5a9b3d 100644 --- a/src/providers/pimpbunny.rs +++ b/src/providers/pimpbunny.rs @@ -40,6 +40,11 @@ pub struct PimpbunnyProvider { } impl PimpbunnyProvider { + const FIREFOX_USER_AGENT: &'static str = + "Mozilla/5.0 (X11; Linux x86_64; rv:147.0) Gecko/20100101 Firefox/147.0"; + const HTML_ACCEPT: &'static str = + "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8"; + pub fn new() -> Self { let provider = Self { url: "https://pimpbunny.com".to_string(), @@ -194,11 +199,37 @@ impl PimpbunnyProvider { ) } + fn root_referer(&self) -> String { + format!("{}/", self.url.trim_end_matches('/')) + } + + fn root_headers(&self) -> Vec<(String, String)> { + vec![ + ("Referer".to_string(), self.root_referer()), + ( + "User-Agent".to_string(), + Self::FIREFOX_USER_AGENT.to_string(), + ), + ("Accept".to_string(), Self::HTML_ACCEPT.to_string()), + ("Accept-Language".to_string(), "en-US,en;q=0.9".to_string()), + ] + } + async fn load_stars(base: &str, stars: Arc>>) -> Result<()> { let mut requester = Requester::new(); + let headers = vec![ + ("Referer".to_string(), format!("{}/", base.trim_end_matches('/'))), + ( + "User-Agent".to_string(), + Self::FIREFOX_USER_AGENT.to_string(), + ), + ("Accept".to_string(), Self::HTML_ACCEPT.to_string()), + ("Accept-Language".to_string(), "en-US,en;q=0.9".to_string()), + ]; let text = requester - .get( + .get_with_headers( &format!("{base}/onlyfans-models/?models_per_page=20"), + headers, Some(Version::HTTP_2), ) .await @@ -240,9 +271,19 @@ impl PimpbunnyProvider { async fn load_categories(base: &str, cats: Arc>>) -> Result<()> { let mut requester = Requester::new(); + let headers = vec![ + ("Referer".to_string(), format!("{}/", base.trim_end_matches('/'))), + ( + "User-Agent".to_string(), + Self::FIREFOX_USER_AGENT.to_string(), + ), + ("Accept".to_string(), Self::HTML_ACCEPT.to_string()), + ("Accept-Language".to_string(), "en-US,en;q=0.9".to_string()), + ]; let text = requester - .get( + .get_with_headers( &format!("{base}/categories/?items_per_page=120"), + headers, Some(Version::HTTP_2), ) .await @@ -306,7 +347,10 @@ impl PimpbunnyProvider { }; let mut requester = crate::providers::requester_or_default(&options, module_path!(), "missing_requester"); - let text = match requester.get(&video_url, Some(Version::HTTP_11)).await { + let text = match requester + .get_with_headers(&video_url, self.root_headers(), Some(Version::HTTP_11)) + .await + { Ok(text) => text, Err(e) => { crate::providers::report_provider_error( @@ -403,7 +447,10 @@ impl PimpbunnyProvider { let mut requester = crate::providers::requester_or_default(&options, module_path!(), "missing_requester"); println!("Fetching URL: {}", video_url); - let text = match requester.get(&video_url, Some(Version::HTTP_2)).await { + let text = match requester + .get_with_headers(&video_url, self.root_headers(), Some(Version::HTTP_2)) + .await + { Ok(text) => text, Err(e) => { crate::providers::report_provider_error( @@ -531,7 +578,7 @@ impl PimpbunnyProvider { requester: &mut Requester, ) -> Result<(Vec, Vec, u32, u32)> { let text = requester - .get(url, Some(Version::HTTP_2)) + .get_with_headers(url, self.root_headers(), Some(Version::HTTP_2)) .await .map_err(|e| Error::from(format!("{}", e)))?; @@ -565,7 +612,12 @@ impl PimpbunnyProvider { Ok(( vec![], - vec![VideoFormat::new(video_url, quality, "video/mp4".into())], + vec![VideoFormat::new(video_url, quality, "video/mp4".into()) + .http_header("Referer".to_string(), url.to_string()) + .http_header( + "User-Agent".to_string(), + Self::FIREFOX_USER_AGENT.to_string(), + )], views, duration, )) diff --git a/src/proxies/pimpbunnythumb.rs b/src/proxies/pimpbunnythumb.rs index dfac189..9b94a19 100644 --- a/src/proxies/pimpbunnythumb.rs +++ b/src/proxies/pimpbunnythumb.rs @@ -4,9 +4,15 @@ use ntex::{ web::{self, HttpRequest, error}, }; use url::Url; +use wreq::Version; use crate::util::requester::Requester; +const FIREFOX_USER_AGENT: &str = + "Mozilla/5.0 (X11; Linux x86_64; rv:147.0) Gecko/20100101 Firefox/147.0"; +const IMAGE_ACCEPT: &str = + "image/avif,image/webp,image/png,image/svg+xml,image/*;q=0.8,*/*;q=0.5"; + fn is_allowed_thumb_url(url: &str) -> bool { let Some(url) = Url::parse(url).ok() else { return false; @@ -37,17 +43,66 @@ pub async fn get_image( return Ok(web::HttpResponse::BadRequest().finish()); } - let upstream = match requester - .get_ref() - .clone() - .get_raw_with_headers( - image_url.as_str(), - vec![("Referer".to_string(), "https://pimpbunny.com/".to_string())], - ) + let headers = vec![ + ("Referer".to_string(), "https://pimpbunny.com/".to_string()), + ("User-Agent".to_string(), FIREFOX_USER_AGENT.to_string()), + ("Accept".to_string(), IMAGE_ACCEPT.to_string()), + ("Accept-Language".to_string(), "en-US,en;q=0.9".to_string()), + ]; + let mut requester = requester.get_ref().clone(); + + let mut upstream = requester + .get_raw_with_headers(image_url.as_str(), headers.clone()) .await - { - Ok(response) if response.status().is_success() => response, - _ => return Ok(web::HttpResponse::NotFound().finish()), + .ok(); + + let needs_warmup = upstream + .as_ref() + .map(|response| !response.status().is_success()) + .unwrap_or(true); + + if needs_warmup { + let _ = requester + .get_with_headers( + "https://pimpbunny.com/", + vec![ + ("Referer".to_string(), "https://pimpbunny.com/".to_string()), + ("User-Agent".to_string(), FIREFOX_USER_AGENT.to_string()), + ( + "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.9".to_string()), + ], + Some(Version::HTTP_11), + ) + .await; + + upstream = requester + .get_raw_with_headers(image_url.as_str(), headers.clone()) + .await + .ok(); + } + + let needs_image_specific_warmup = upstream + .as_ref() + .map(|response| !response.status().is_success()) + .unwrap_or(true); + + if needs_image_specific_warmup { + let _ = requester + .get_with_headers(image_url.as_str(), headers.clone(), Some(Version::HTTP_11)) + .await; + + upstream = requester + .get_raw_with_headers(image_url.as_str(), headers) + .await + .ok(); + } + + let Some(upstream) = upstream.filter(|response| response.status().is_success()) else { + return Ok(web::HttpResponse::NotFound().finish()); }; let status = upstream.status();