advanced search for channel and models

This commit is contained in:
Simon
2025-07-19 14:37:11 +00:00
parent 6ef74955cf
commit 41374470b1

View File

@@ -6,6 +6,7 @@ use crate::util::flaresolverr::{FlareSolverrRequest, Flaresolverr};
use crate::util::time::parse_time_to_seconds; use crate::util::time::parse_time_to_seconds;
use crate::videos::{VideoItem}; use crate::videos::{VideoItem};
use error_chain::error_chain; use error_chain::error_chain;
use futures::stream::SplitSink;
use htmlentity::entity::{ICodedDataTrait, decode}; use htmlentity::entity::{ICodedDataTrait, decode};
use std::env; use std::env;
use std::vec; use std::vec;
@@ -53,12 +54,13 @@ impl PornhubProvider {
} }
}; };
let client = Client::builder().emulation(Emulation::Firefox136).build()?; let proxy = Proxy::all("http://192.168.0.103:8081").unwrap();
let client = Client::builder().cert_verification(false).emulation(Emulation::Firefox136).build()?;
let response = client.get(url.clone()).send().await?; let response = client.get(url.clone()).proxy(proxy).send().await?;
if response.status().is_success() { if response.status().is_success() {
let text = response.text().await?; let text = response.text().await?;
let video_items: Vec<VideoItem> = self.get_video_items_from_html(text.clone()); let video_items: Vec<VideoItem> = self.get_video_items_from_html(text.clone(),"<ul id=\"video");
if !video_items.is_empty() { if !video_items.is_empty() {
cache.remove(&url); cache.remove(&url);
cache.insert(url.clone(), video_items.clone()); cache.insert(url.clone(), video_items.clone());
@@ -79,7 +81,7 @@ impl PornhubProvider {
let video_items = match result { let video_items = match result {
Ok(res) => { Ok(res) => {
// println!("FlareSolverr response: {}", res); // println!("FlareSolverr response: {}", res);
self.get_video_items_from_html(res.solution.response) self.get_video_items_from_html(res.solution.response,"<ul id=\"video")
} }
Err(e) => { Err(e) => {
println!("Error solving FlareSolverr: {}", e); println!("Error solving FlareSolverr: {}", e);
@@ -101,12 +103,26 @@ impl PornhubProvider {
page: u8, page: u8,
query: &str, query: &str,
) -> Result<Vec<VideoItem>> { ) -> Result<Vec<VideoItem>> {
let mut split_string = "<ul id=\"video";
let search_string = query.to_lowercase().trim().replace(" ", "+"); let search_string = query.to_lowercase().trim().replace(" ", "+");
let mut url = format!("{}/video/search?search={}&page={}", self.url, search_string, page); let mut url = format!("{}/video/search?search={}&page={}", self.url, search_string, page);
if page == 1 { if page == 1 {
url = format!("{}/video/search?search={}", self.url, search_string); url = format!("{}/video/search?search={}", self.url, search_string);
} }
if query.starts_with("@"){
let url_parts = query[1..].split(":").collect::<Vec<&str>>();
url = [self.url.to_string(), url_parts[0].to_string(), url_parts[1].to_string(), "videos?page=".to_string()].join("/");
url += &page.to_string();
if query.contains("@model"){
split_string = "mostRecentVideosSection";
}
if query.contains("@channels"){
split_string = "dropdownHottestVideos";
}
println!("Query URL: {}", url);
}
// Check our Video Cache. If the result is younger than 1 hour, we return it. // Check our Video Cache. If the result is younger than 1 hour, we return it.
let old_items = match cache.get(&url) { let old_items = match cache.get(&url) {
Some((time, items)) => { Some((time, items)) => {
@@ -128,7 +144,7 @@ impl PornhubProvider {
let response = client.get(url.clone()).proxy(proxy).send().await?; let response = client.get(url.clone()).proxy(proxy).send().await?;
if response.status().is_success() { if response.status().is_success() {
let text = response.text().await?; let text = response.text().await?;
let video_items: Vec<VideoItem> = self.get_video_items_from_html(text.clone()); let video_items: Vec<VideoItem> = self.get_video_items_from_html(text.clone(),split_string);
if !video_items.is_empty() { if !video_items.is_empty() {
cache.remove(&url); cache.remove(&url);
cache.insert(url.clone(), video_items.clone()); cache.insert(url.clone(), video_items.clone());
@@ -147,7 +163,7 @@ impl PornhubProvider {
}) })
.await; .await;
let video_items = match result { let video_items = match result {
Ok(res) => self.get_video_items_from_html(res.solution.response), Ok(res) => self.get_video_items_from_html(res.solution.response,split_string),
Err(e) => { Err(e) => {
println!("Error solving FlareSolverr: {}", e); println!("Error solving FlareSolverr: {}", e);
return Err("Failed to solve FlareSolverr".into()); return Err("Failed to solve FlareSolverr".into());
@@ -163,18 +179,20 @@ impl PornhubProvider {
} }
} }
fn get_video_items_from_html(&self, html: String) -> Vec<VideoItem> { fn get_video_items_from_html(&self, html: String, split_string: &str) -> Vec<VideoItem> {
if html.is_empty() { if html.is_empty() {
println!("HTML is empty"); println!("HTML is empty");
return vec![]; return vec![];
} }
let mut items: Vec<VideoItem> = Vec::new(); let mut items: Vec<VideoItem> = Vec::new();
println!("{}", html.contains("<ul id=\"video")); println!("split_string: {}", split_string);
let video_listing_content = html.split("<ul id=\"video").collect::<Vec<&str>>()[1]; let video_listing_content = html.split(split_string).collect::<Vec<&str>>()[1].split("Porn in German").collect::<Vec<&str>>()[0];
println!("Video listing content length: {}", video_listing_content.len());
let raw_videos = video_listing_content let raw_videos = video_listing_content
.split("class=\"pcVideoListItem ") .split("class=\"pcVideoListItem ")
.collect::<Vec<&str>>()[1..] .collect::<Vec<&str>>()[1..]
.to_vec(); .to_vec();
println!("Number of video segments found: {}", raw_videos.len());
for video_segment in &raw_videos { for video_segment in &raw_videos {
// let vid = video_segment.split("\n").collect::<Vec<&str>>(); // let vid = video_segment.split("\n").collect::<Vec<&str>>();
// for (index, line) in vid.iter().enumerate() { // for (index, line) in vid.iter().enumerate() {
@@ -211,7 +229,7 @@ impl PornhubProvider {
let view_part = match video_segment.split("iews\">").collect::<Vec<&str>>().len(){ let view_part = match video_segment.split("iews\">").collect::<Vec<&str>>().len(){
2 => video_segment.split("iews\">").collect::<Vec<&str>>()[1], 2 => video_segment.split("iews\">").collect::<Vec<&str>>()[1],
3 => video_segment.split("iews\">").collect::<Vec<&str>>()[2], 3 => video_segment.split("iews\">").collect::<Vec<&str>>()[2],
_ => continue, // Skip if the format is unexpected _ => "<var>0<", // Skip if the format is unexpected
}; };
let views = parse_abbreviated_number(view_part let views = parse_abbreviated_number(view_part
.split("<var>").collect::<Vec<&str>>()[1] .split("<var>").collect::<Vec<&str>>()[1]
@@ -222,7 +240,24 @@ impl PornhubProvider {
.split("\"") .split("\"")
.collect::<Vec<&str>>()[0] .collect::<Vec<&str>>()[0]
.to_string(); .to_string();
let video_item = VideoItem::new(
let mut uploaderBlock = String::new();
let mut uploader_href = vec![];
let mut tag = String::new();
if video_segment.contains("videoUploaderBlock") {
uploaderBlock = video_segment.split("videoUploaderBlock").collect::<Vec<&str>>()[1]
.to_string();
uploader_href = uploaderBlock.split("href=\"").collect::<Vec<&str>>()[1]
.split("\"")
.collect::<Vec<&str>>()[0]
.split("/").collect::<Vec<&str>>();
tag = format!("@{}:{}", uploader_href[1], uploader_href[2]);
}
let mut video_item = VideoItem::new(
id, id,
title, title,
url.to_string(), url.to_string(),
@@ -230,8 +265,14 @@ impl PornhubProvider {
thumb, thumb,
duration, duration,
) )
.views(views)
; ;
if views > 0 {
video_item = video_item.views(views);
}
if !tag.is_empty() {
video_item = video_item.tags(vec![tag])
.uploader(uploader_href[2].to_string());
}
items.push(video_item); items.push(video_item);
} }
return items; return items;