From 57eb2d7063cb73e131c6246c237163ab98696235 Mon Sep 17 00:00:00 2001 From: Simon Date: Thu, 9 Apr 2026 07:19:33 +0000 Subject: [PATCH] upgrades --- Cargo.toml | 2 +- src/providers/hqporner.rs | 252 ++++---------------------------------- src/providers/mod.rs | 82 ++----------- src/providers/pornhub.rs | 49 +------- src/status.rs | 14 +++ src/videos.rs | 2 - 6 files changed, 49 insertions(+), 352 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 5883d05..98f6cb3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -39,7 +39,7 @@ chrono = "0.4.44" md5 = "0.8.0" [lints.rust] -warnings = "deny" +warnings = "warn" unexpected_cfgs = "allow" # Or keep it as a warning but whitelist the cfg: # unexpected_cfgs = { level = "warn", check-cfg = ['cfg(has_error_description_deprecated)'] } diff --git a/src/providers/hqporner.rs b/src/providers/hqporner.rs index fc0cca4..a2e985d 100644 --- a/src/providers/hqporner.rs +++ b/src/providers/hqporner.rs @@ -6,10 +6,9 @@ use crate::util::cache::VideoCache; use crate::util::discord::{format_error_chain, send_discord_error_report}; use crate::util::requester::Requester; use crate::util::time::parse_time_to_seconds; -use crate::videos::{ServerOptions, VideoFormat, VideoItem}; +use crate::videos::{ServerOptions, VideoItem}; use async_trait::async_trait; use error_chain::error_chain; -use futures::stream::{FuturesUnordered, StreamExt}; use htmlentity::entity::{ICodedDataTrait, decode}; use std::sync::{Arc, RwLock}; use std::{thread, vec}; @@ -194,9 +193,7 @@ impl HqpornerProvider { .await .map_err(|e| Error::from(format!("Request failed: {}", e)))?; - let video_items = self - .get_video_items_from_html(text, &mut requester, &options) - .await; + let video_items = self.get_video_items_from_html(text, &options).await; if !video_items.is_empty() { cache.insert(video_url, video_items.clone()); } @@ -242,9 +239,7 @@ impl HqpornerProvider { .await .map_err(|e| Error::from(format!("Request failed: {}", e)))?; - let video_items = self - .get_video_items_from_html(text, &mut requester, &options) - .await; + let video_items = self.get_video_items_from_html(text, &options).await; if !video_items.is_empty() { cache.insert(video_url, video_items.clone()); } @@ -254,7 +249,6 @@ impl HqpornerProvider { async fn get_video_items_from_html( &self, html: String, - requester: &mut Requester, options: &ServerOptions, ) -> Vec { if html.is_empty() || html.contains("404 Not Found") { @@ -273,63 +267,14 @@ impl HqpornerProvider { }) .unwrap_or_default(); - // Limit concurrent detail-page requests to reduce transient connect errors. - let mut in_flight = FuturesUnordered::new(); - let mut iter = raw_videos.into_iter(); - let mut items = Vec::new(); - const MAX_IN_FLIGHT: usize = 6; - - loop { - while in_flight.len() < MAX_IN_FLIGHT { - let Some(seg) = iter.next() else { - break; - }; - in_flight.push(self.get_video_item(seg, requester.clone(), options)); - } - - let Some(result) = in_flight.next().await else { - break; - }; - match result { - Ok(item) - if item - .formats - .as_ref() - .map(|formats| !formats.is_empty()) - .unwrap_or(false) => - { - items.push(item); - } - Ok(_) => {} - Err(e) => { - let msg = e.to_string(); - let chain = format_error_chain(&e); - tokio::spawn(async move { - let _ = send_discord_error_report( - msg, - Some(chain), - Some("Hqporner Provider"), - None, - file!(), - line!(), - module_path!(), - ) - .await; - }); - } - } - } - - items + raw_videos + .into_iter() + .filter_map(|seg| self.get_video_item(seg, options).ok()) + .collect() } - async fn get_video_item( - &self, - seg: String, - mut requester: Requester, - options: &ServerOptions, - ) -> Result { - let video_url = format!( + fn get_video_item(&self, seg: String, options: &ServerOptions) -> Result { + let detail_url = format!( "{}{}", self.url, seg.split(" Result<(Vec, Vec)> { - let mut formats = vec![]; - let mut tags = vec![]; - let headers = vec![("Referer".to_string(), "https://hqporner.com/".into())]; - let mut text = match self - .fetch_text_with_retries(requester, url, &headers, 3) - .await - { - Ok(text) => text, - Err(primary_err) => { - if url.contains("://hqporner.com/") { - let fallback_url = url.replace("://hqporner.com/", "://www.hqporner.com/"); - self.fetch_text_with_retries(requester, &fallback_url, &headers, 3) - .await - .map_err(|fallback_err| { - Error::from(format!( - "Request failed: primary={primary_err}; fallback={fallback_err}" - )) - })? - } else { - return Err(Error::from(format!("Request failed: {}", primary_err))); - } - } - }; - - if text.is_empty() && url.contains("://hqporner.com/") { - let fallback_url = url.replace("://hqporner.com/", "://www.hqporner.com/"); - text = self - .fetch_text_with_retries(requester, &fallback_url, &headers, 3) - .await - .unwrap_or_default(); - } - - if text.contains("Why do I see it?") { - return Ok((tags, formats)); - } - - // Extract Stars & Tags - if let Some(stars_block) = text - .split("icon fa-star-o") - .nth(1) - .and_then(|s| s.split("").next()) - { - for star_el in stars_block.split("href=\"/actress/").skip(1) { - let id = star_el.split('"').next().unwrap_or("").to_string(); - let name = star_el - .split("\">") - .nth(1) - .and_then(|s| s.split('<').next()) - .unwrap_or("") - .to_string(); - if !name.is_empty() { - tags.push(name.clone()); - Self::push_unique(&self.stars, FilterOption { id, title: name }); - } - } - } - - // Player / Video Extraction - let player_url = format!( - "https:{}", - text.split("url: '/blocks/altplayer.php?i=") - .nth(1) - .and_then(|s| s.split('\'').next()) - .ok_or("No player link")? + let proxied_url = crate::providers::build_proxy_url( + options, + "hqporner", + &crate::providers::strip_url_scheme(&detail_url), ); - let response_text = match self - .fetch_text_with_retries(requester, &player_url, &headers, 2) - .await - { - Ok(text) => text, - Err(e) => { - let err = format!("altplayer request failed: {e}"); - send_discord_error_report( - err.clone(), - None, - Some("Hqporner Provider"), - Some(&player_url), - file!(), - line!(), - module_path!(), - ) - .await; - return Ok((tags, formats)); - } - }; - let text2 = response_text; - // Check for error response - if text2.starts_with("ERR:") { - return Ok((tags, formats)); - } - - let video_element = text2 - .split("