diff --git a/src/api.rs b/src/api.rs index 186df41..eca44d4 100644 --- a/src/api.rs +++ b/src/api.rs @@ -1,3 +1,5 @@ +use std::cmp::Ordering; +use htmlentity::types::Byte; use ntex::http::header; use ntex::web; use ntex::web::HttpRequest; @@ -8,6 +10,80 @@ use crate::providers::spankbang::SpankbangProvider; use crate::util::cache::VideoCache; use crate::{providers::*, status::*, videos::*, DbPool}; +#[derive(Debug)] +struct ClientVersion{ + version: u32, + subversion: u32, + name: String, +} + + +impl ClientVersion { + + pub fn new(version: u32, subversion: u32, name: String) -> ClientVersion{ + ClientVersion{ + version, + subversion, + name + } + } + + pub fn parse(input: &str) -> Option { + // Example input: "Hot%20Tub/22c CFNetwork/1494.0.7 Darwin/23.4.0 0.002478" + let parts: Vec<&str> = input.split_whitespace().collect(); + if let Some(first) = parts.first() { + let name_version: Vec<&str> = first.split('/').collect(); + let name = name_version[1]; + + // Extract version and optional subversion + let (version, subversion) = if let Some((v, c)) = name.split_at(name.len().saturating_sub(1)).into() { + match v.parse::() { + Ok(ver) => (ver, c.chars().next().map(|ch| ch as u32).unwrap_or(0)), + Err(_) => { + // Try parsing whole string if no subversion exists + match name.parse::() { + Ok(ver) => (ver, 0), + Err(_) => return None, + } + } + } + } else { + return None; + }; + + return Some(ClientVersion { + version: version, + subversion: subversion, + name: name.to_string(), + }); + } + None + } +} + +// Implement comparisons +impl PartialEq for ClientVersion { + fn eq(&self, other: &Self) -> bool { + self.name == other.name + } +} + +impl Eq for ClientVersion {} + +impl PartialOrd for ClientVersion { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} + +impl Ord for ClientVersion { + fn cmp(&self, other: &Self) -> Ordering { + self.version + .cmp(&other.version) + .then_with(|| self.subversion.cmp(&other.subversion)) + } +} + pub fn config(cfg: &mut web::ServiceConfig) { cfg.service( web::resource("/status") @@ -22,6 +98,16 @@ pub fn config(cfg: &mut web::ServiceConfig) { } async fn status(req: HttpRequest) -> Result { + + let clientversion: ClientVersion = match req.headers().get("User-Agent"){ + Some(v) => match v.to_str(){ + Ok(useragent) => ClientVersion::parse(useragent).unwrap_or_else(|| ClientVersion::new(999, 0, "999".to_string())), + Err(_) => ClientVersion::new(999, 0, "999".to_string()) + }, + _=> ClientVersion::new(999, 0, "999".to_string()) + }; + + let host = req .headers() .get(header::HOST) @@ -29,72 +115,76 @@ async fn status(req: HttpRequest) -> Result { .unwrap_or_default() .to_string(); let mut status = Status::new(); - status.add_channel(Channel { - id: "perverzija".to_string(), - name: "Perverzija".to_string(), - description: "Free videos from Perverzija".to_string(), - premium: false, - favicon: "https://www.google.com/s2/favicons?sz=64&domain=tube.perverzija.com".to_string(), - status: "active".to_string(), - categories: vec![], - options: vec![ - // ChannelOption { - // id: "sort".to_string(), - // title: "Sort".to_string(), - // description: "Sort the Videos".to_string(), //"Sort the videos by Date or Name.".to_string(), - // systemImage: "list.number".to_string(), - // colorName: "blue".to_string(), - // options: vec![ - // FilterOption { - // id: "date".to_string(), - // title: "Date".to_string(), - // }, - // FilterOption { - // id: "name".to_string(), - // title: "Name".to_string(), - // }, - // ], - // multiSelect: false, - // }, - ChannelOption { - id: "featured".to_string(), - title: "Featured".to_string(), - description: "Filter Featured Videos.".to_string(), - systemImage: "star".to_string(), - colorName: "red".to_string(), - options: vec![ - FilterOption { - id: "all".to_string(), - title: "No".to_string(), - }, - FilterOption { - id: "featured".to_string(), - title: "Yes".to_string(), - }, - ], - multiSelect: false, - }, - // ChannelOption { - // id: "duration".to_string(), - // title: "Duration".to_string(), - // description: "Filter the videos by duration.".to_string(), - // systemImage: "timer".to_string(), - // colorName: "green".to_string(), - // options: vec![ - // FilterOption { - // id: "short".to_string(), - // title: "< 1h".to_string(), - // }, - // FilterOption { - // id: "long".to_string(), - // title: "> 1h".to_string(), - // }, - // ], - // multiSelect: true, - // }, - ], - nsfw: true, - }); + + if clientversion >= ClientVersion::new(22,97,"22a".to_string()){ + //add perverzija + status.add_channel(Channel { + id: "perverzija".to_string(), + name: "Perverzija".to_string(), + description: "Free videos from Perverzija".to_string(), + premium: false, + favicon: "https://www.google.com/s2/favicons?sz=64&domain=tube.perverzija.com".to_string(), + status: "active".to_string(), + categories: vec![], + options: vec![ + // ChannelOption { + // id: "sort".to_string(), + // title: "Sort".to_string(), + // description: "Sort the Videos".to_string(), //"Sort the videos by Date or Name.".to_string(), + // systemImage: "list.number".to_string(), + // colorName: "blue".to_string(), + // options: vec![ + // FilterOption { + // id: "date".to_string(), + // title: "Date".to_string(), + // }, + // FilterOption { + // id: "name".to_string(), + // title: "Name".to_string(), + // }, + // ], + // multiSelect: false, + // }, + ChannelOption { + id: "featured".to_string(), + title: "Featured".to_string(), + description: "Filter Featured Videos.".to_string(), + systemImage: "star".to_string(), + colorName: "red".to_string(), + options: vec![ + FilterOption { + id: "all".to_string(), + title: "No".to_string(), + }, + FilterOption { + id: "featured".to_string(), + title: "Yes".to_string(), + }, + ], + multiSelect: false, + }, + // ChannelOption { + // id: "duration".to_string(), + // title: "Duration".to_string(), + // description: "Filter the videos by duration.".to_string(), + // systemImage: "timer".to_string(), + // colorName: "green".to_string(), + // options: vec![ + // FilterOption { + // id: "short".to_string(), + // title: "< 1h".to_string(), + // }, + // FilterOption { + // id: "long".to_string(), + // title: "> 1h".to_string(), + // }, + // ], + // multiSelect: true, + // }, + ], + nsfw: true, + }); + } status.add_channel(Channel { id: "hanime".to_string(), name: "Hanime".to_string(),