From 7c73601954d752e542e650a40f81af54498913fd Mon Sep 17 00:00:00 2001 From: Simon Date: Sat, 4 Oct 2025 17:40:03 +0000 Subject: [PATCH] now supports sites --- src/providers/omgxxx.rs | 95 +++++++++++++++++++++++++++-------------- src/util/requester.rs | 2 +- 2 files changed, 65 insertions(+), 32 deletions(-) diff --git a/src/providers/omgxxx.rs b/src/providers/omgxxx.rs index 68bda0a..0f64c60 100644 --- a/src/providers/omgxxx.rs +++ b/src/providers/omgxxx.rs @@ -10,8 +10,8 @@ use async_trait::async_trait; use error_chain::error_chain; use htmlentity::entity::{ICodedDataTrait, decode}; use std::sync::{Arc, RwLock}; -use std::thread; use std::vec; +use std::{env, thread}; error_chain! { foreign_links { @@ -30,8 +30,14 @@ impl OmgxxxProvider { pub fn new() -> Self { let provider = OmgxxxProvider { url: "https://www.omg.xxx".to_string(), - sites: Arc::new(RwLock::new(vec![])), - networks: Arc::new(RwLock::new(vec![FilterOption{id:"all".to_string(),title:"All".to_string()}])), + sites: Arc::new(RwLock::new(vec![FilterOption { + id: "all".to_string(), + title: "All".to_string(), + }])), + networks: Arc::new(RwLock::new(vec![FilterOption { + id: "all".to_string(), + title: "All".to_string(), + }])), }; // Kick off the background load but return immediately @@ -41,7 +47,7 @@ impl OmgxxxProvider { fn spawn_initial_load(&self) { let url = self.url.clone(); - // let sites = Arc::clone(&self.sites); + let sites = Arc::clone(&self.sites); let networks = Arc::clone(&self.networks); thread::spawn(move || { @@ -53,9 +59,9 @@ impl OmgxxxProvider { rt.block_on(async move { // If you have a streaming sites loader, call it here too - // if let Err(e) = Self::load_sites_into(&url, sites).await { - // eprintln!("load_sites_into failed: {e}"); - // } + if let Err(e) = Self::load_sites(&url, sites).await { + eprintln!("load_sites_into failed: {e}"); + } if let Err(e) = Self::load_networks(&url, networks).await { eprintln!("load_networks failed: {e}"); @@ -64,23 +70,44 @@ impl OmgxxxProvider { }); } - /// === separate, self-contained logic === - /// Replace the bodies with your real fetching/parsing code. - // async fn load_sites(base_url: &str) -> Result> { - // // Example stub: - // // let html = reqwest::blocking::get(format!("{}/sites/", base_url))?.text()?; - // // Ok(parse_sites_from_html(&html)) - // Ok(vec![ - // FilterOption { - // id: "site-a".into(), - // title: "Site A".into(), - // }, - // FilterOption { - // id: "site-b".into(), - // title: "Site B".into(), - // }, - // ]) - // } + async fn load_sites(base_url: &str, networks: Arc>>) -> Result<()> { + let mut requester = util::requester::Requester::new(); + requester.set_proxy(env::var("PROXY").unwrap_or("0".to_string()) != "0".to_string()); + let mut page = 0; + loop { + page += 1; + let text = requester + .get(format!("{}/sites/{}/", &base_url, page).as_str()) + .await + .unwrap(); + if text.contains("404 Not Found") || text.is_empty() { + break; + } + let sites_div = text + .split("id=\"list_content_sources_sponsors_list_items\"").collect::>()[1] + .split("class=\"pagination\"").collect::>()[0]; + for sites_element in + sites_div.split("class=\"headline\"").collect::>()[1..].to_vec() + { + let site_url = sites_element.split("href=\"").collect::>()[1] + .split("\"") + .collect::>()[0]; + let site_id = site_url.split("/").collect::>()[4].to_string(); + let site_name = sites_element.split("

").collect::>()[1] + .split("<") + .collect::>()[0] + .to_string(); + Self::push_unique( + &networks, + FilterOption { + id: site_id, + title: site_name, + }, + ); + } + } + return Ok(()); + } async fn load_networks(base_url: &str, networks: Arc>>) -> Result<()> { let mut requester = util::requester::Requester::new(); @@ -88,8 +115,12 @@ impl OmgxxxProvider { let networks_div = text.split("class=\"sites__list\"").collect::>()[1] .split("") .collect::>()[0]; - for network_element in networks_div.split("sites__item").collect::>()[1..].to_vec() { - if network_element.contains("sites__all"){continue;} + for network_element in + networks_div.split("sites__item").collect::>()[1..].to_vec() + { + if network_element.contains("sites__all") { + continue; + } let network_url = network_element.split("href=\"").collect::>()[1] .split("\"") .collect::>()[0]; @@ -137,7 +168,7 @@ impl OmgxxxProvider { Channel { id: "omgxxx".to_string(), name: "OMG XXX".to_string(), - description: "Free Porn Site".to_string(), + description: "OMG look at that Collection!".to_string(), premium: false, favicon: "https://www.google.com/s2/favicons?sz=64&domain=www.omg.xxx".to_string(), status: "active".to_string(), @@ -196,13 +227,16 @@ impl OmgxxxProvider { sort: &str, options: ServerOptions, ) -> Result> { - let mut sort_string:String = match sort { + let mut sort_string: String = match sort { "top-rated" => "top-rated".to_string(), "most-popular" => "most-popular".to_string(), _ => "latest-updates".to_string(), }; - if options.network.is_some() && !options.network.as_ref().unwrap().is_empty() && options.network.as_ref().unwrap() != "all" { - sort_string = format!("networks/{}",options.network.as_ref().unwrap()); + if options.network.is_some() + && !options.network.as_ref().unwrap().is_empty() + && options.network.as_ref().unwrap() != "all" + { + sort_string = format!("networks/{}", options.network.as_ref().unwrap()); } let video_url = format!("{}/{}/{}/", self.url, sort_string, page); let old_items = match cache.get(&video_url) { @@ -219,7 +253,6 @@ impl OmgxxxProvider { } }; - let mut requester = options.requester.clone().unwrap(); let text = requester.get(&video_url).await.unwrap(); let video_items: Vec = self.get_video_items_from_html(text.clone()); diff --git a/src/util/requester.rs b/src/util/requester.rs index 796b592..1f8756c 100644 --- a/src/util/requester.rs +++ b/src/util/requester.rs @@ -118,7 +118,7 @@ impl Requester { let response = request.send().await?; - if response.status().is_success() { + if response.status().is_success() || response.status().as_u16() == 404 { return Ok(response.text().await?); }