diff --git a/Cargo.toml b/Cargo.toml index c62a8f4..b75801e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,6 +17,7 @@ chrono = "0.4.41" rss_content = { git = "https://code.gabe.rocks/gabriel/rss_content", version = "0.1.1" } bytes = "1.10.1" scraper = "0.23.1" +url = "2.5.4" [profile.dev] debug=true diff --git a/src/net.rs b/src/net.rs index 2e92892..458f3b4 100644 --- a/src/net.rs +++ b/src/net.rs @@ -1,86 +1,107 @@ use core::panic; use iced::widget::image::Handle; -use rss::{Channel}; use reqwest::{self, blocking::Client, header::USER_AGENT, Error, Proxy}; +use rss::Channel; use scraper::{Html, Selector}; +use url::Url; const DEFAULT_TOR_PROXY: &str = "socks5h://127.0.0.1:9050"; const DEFAULT_I2P_PROXY: &str = "socks5h://127.0.0.1:4447"; -enum Network{ +#[derive(PartialEq)] +enum Network { Clearnet, Tor, - I2P + I2P, + Unknown, } -fn get_client(network: Network) -> Result{ +fn url_network(url: &str) -> Network { + match Url::parse(url) { + Ok(u) => match u.host() { + Some(host) => { + let h = host.to_string(); + if h.find(".onion").is_some() { + return Network::Tor; + } else if h.find(".i2p").is_some() { + return Network::I2P; + } else { + return Network::Clearnet; + } + } + None => {return Network::Unknown;} + }, + Err(e) => { + return Network::Clearnet; + } + } + Network::Clearnet +} + +#[test] +fn network_testing(){ + assert!(url_network("http://gabe.onion/rss") == Network::Tor); + assert!(url_network("http://gabe.i2p/rss") == Network::I2P); + assert!(url_network("https://gabe.rocks/rss") == Network::Clearnet); +} + +fn get_client(network: Network) -> Result { //in the long run, support for fancy things like arti & user-configurable proxies will be important, nevermind other networks like reticulum! match network { Network::Clearnet => { return Ok(Client::new()); } Network::Tor => { - match Client::builder().proxy(Proxy::http(DEFAULT_TOR_PROXY).unwrap()).build() { - Ok(client) => {return Ok(client);} - Err(e) => {return Err(e);} + match Client::builder() + .proxy(Proxy::http(DEFAULT_TOR_PROXY).unwrap()) + .build() + { + Ok(client) => { + return Ok(client); + } + Err(e) => { + return Err(e); + } } } Network::I2P => { - match Client::builder().proxy(Proxy::http(DEFAULT_I2P_PROXY).unwrap()).build() { - Ok(client) => {return Ok(client);} - Err(e) => {return Err(e);} - } - - } - } -} - -pub fn get_onion_content(url: &str) -> Option { - match Client::builder().proxy( - Proxy::http(DEFAULT_TOR_PROXY).unwrap() - ).build() { - Ok(client) => { - let res = client.get(url) - .header(USER_AGENT,"RSS Reader") - .send(); - match res { - Ok(resp) => { - match resp.text() { - Ok(body) => {return Some(body);} - Err(_) => {return None;} + match Client::builder() + .proxy(Proxy::http(DEFAULT_I2P_PROXY).unwrap()) + .build() + { + Ok(client) => { + return Ok(client); + } + Err(e) => { + return Err(e); + } } } - Err(e) => { - println!("Error loading content via Tor\nError:{}",e); - return None; + Network::Unknown => { + println!("Fetching client for unknown network..."); + return Ok(Client::new()); } } - } - Err(e) => { - println!("Failed to get Tor client\nError:{}",e); - return None; - } - } - } fn get_content(url: &str) -> Option { - let client = Client::new(); - let res = client.get(url) - .header(USER_AGENT,"RSS Reader") - .send(); + let client = get_client(url_network(url)).unwrap(); + let res = client.get(url).header(USER_AGENT, "RSS Reader").send(); match res { - Ok(resp) => { - match resp.text() { - Ok(body) => {return Some(body)} - Err(_) => {return None} - } - } - Err(_) => {return None} + Ok(resp) => match resp.text() { + Ok(body) => return Some(body), + Err(_) => return None, + }, + Err(_) => return None, } } -pub fn get_feeds(url: &str) -> Option>{ +#[test] +fn get_onion_content() { + get_content("http://gabriel262me3lgv3w7xohtesg3laoojmtye644pwirhdm73qmedmsqd.onion/rss"); +} + +pub fn get_feeds(url: &str) -> Option> { let page = get_content(url).unwrap(); let doc = Html::parse_document(&page); let link_selector = Selector::parse("head link").unwrap(); @@ -90,7 +111,7 @@ pub fn get_feeds(url: &str) -> Option>{ if rel == "alternate" { if let Some(href) = e.value().attr("href") { match load_rss(href) { - Some(c) => {feeds.push(c)} + Some(c) => feeds.push(c), None => {} } } @@ -99,39 +120,37 @@ pub fn get_feeds(url: &str) -> Option>{ } return match feeds.len() { 0 => None, - _ => {Some(feeds)} - } + _ => Some(feeds), + }; } pub fn is_feed(url: &str) -> bool { match get_feeds(url) { Some(_) => true, - None => false + None => false, } } -pub fn load_rss(url: &str) -> Option{ +pub fn load_rss(url: &str) -> Option { let client = Client::new(); - let res = client.get(url) - .header(USER_AGENT,"RSS Reader") - .send(); + let res = client.get(url).header(USER_AGENT, "RSS Reader").send(); match res { - Ok(resp) => { - match resp.bytes() { - Ok(body) => { - match Channel::read_from(&*body) { - Ok(channel) => {Some(channel)} - Err(e) => {panic!("Error parsing feed:\n{}",e);} - } - - - }, - Err(_) => { panic!("Empty response")} + Ok(resp) => match resp.bytes() { + Ok(body) => match Channel::read_from(&*body) { + Ok(channel) => Some(channel), + Err(e) => { + panic!("Error parsing feed:\n{}", e); + } + }, + Err(_) => { + panic!("Empty response") } }, - Err(err) => {panic!("Error loading feed.:{}",err)} + Err(err) => { + panic!("Error loading feed.:{}", err) + } } -} +} pub fn get_item_image(item: &rss::Item) -> Option<&str> { // Only bother with itunes:image print!("{} \n", item.title().unwrap()); @@ -152,7 +171,7 @@ pub fn get_item_image(item: &rss::Item) -> Option<&str> { } } } -pub fn download_image(url: &str) -> Option{ +pub fn download_image(url: &str) -> Option { match reqwest::blocking::get(url) { Ok(r) => { let img: Handle = Handle::from_bytes(r.bytes().unwrap()); diff --git a/src/tests.rs b/src/tests.rs index 930ffd2..6730f7e 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -7,19 +7,6 @@ fn get_feed_test(){ } -#[test] -fn tor_gabe() { - let onion_gabe = net::get_onion_content("http://gabriel262me3lgv3w7xohtesg3laoojmtye644pwirhdm73qmedmsqd.onion/rss"); - match onion_gabe { - Some(b) => { - println!("Successfully loaded over Tor:\n{}",b); - } - None => { - panic!("Failed to load via Tor") - } - } -} - #[test] fn load_feeds() { let url = "https://gabe.rocks"; diff --git a/src/ui.rs b/src/ui.rs index bf228d2..8b9d073 100644 --- a/src/ui.rs +++ b/src/ui.rs @@ -145,7 +145,6 @@ fn view(state: &State) -> Element<'_, Message> { Page::AllItems => item_list(&state), Page::ItemView => item_view(&state), Page::Testing => testing(&state), - _ => {home(&state)} } }