use crate::structs; use quick_xml::events::Event; use quick_xml::Reader; use std::env; use std::process::exit; extern crate serde_json; pub fn get_client() -> reqwest::Client { let mut builder = reqwest::Client::builder(); match env::var("NHENTAIRS_INSECURE") { Ok(val) => { if val == "true" || val == "yes" || val == "1" { builder = builder.danger_accept_invalid_certs(true); } } Err(env::VarError::NotPresent) => {} Err(err) => eprintln!("failed to parse NHENTAIRS_INSECURE: {err}"), }; match builder.build() { Ok(client) => client, Err(err) => { eprintln!("Failed to create reqwest client: {err}"); exit(1); } } } pub async fn get_sauce_info( client: reqwest::Client, sauce: i32, ) -> Result { let mut url = String::from("https://nhentai.net/api/gallery/"); url.push_str(&sauce.to_string()); let resp = client.get(&url).send().await?; Ok(serde_json::from_str(&resp.text().await?)?) } pub async fn get_related_galleries( client: &reqwest::Client, sauce: i32, ) -> Result { let mut url = String::from("https://nhentai.net/api/gallery/"); url.push_str(&sauce.to_string()); url.push_str("/related"); let resp = client.get(&url).send().await?; Ok(serde_json::from_str(&resp.text().await?)?) } pub async fn get_search_info( client: reqwest::Client, search_query: &str, ) -> Result, structs::Error> { let resp = client .get("https://nhentai.net/search/") .query(&[("q", search_query)]) .send() .await?; let text = resp.text().await?; let mut results = Vec::new(); let mut gallery_info = structs::MiniGalleryInfo { id: 0, title: "".to_string(), }; let mut reading_gallery = false; let mut reader = Reader::from_str(&text); reader.trim_text(true).check_end_names(false); loop { match reader.read_event() { Ok(Event::Start(e)) if e.local_name().as_ref() == "a".as_bytes() => { let class_attribute = match e.try_get_attribute("class")? { Some(a) => a, None => continue, }; if class_attribute.decode_and_unescape_value(&reader)? != "cover" { continue; } let href_attribute = match e.try_get_attribute("href")? { Some(a) => a, None => return Err(structs::Error::Unknown("failed to find href in ")), }; let href = href_attribute.decode_and_unescape_value(&reader)?; let id_str = match href.split('/').nth(2) { Some(i) => i, None => return Err(structs::Error::Unknown("failed to find id in ")), }; reading_gallery = true; gallery_info.id = id_str.parse()?; } Ok(Event::Text(e)) if reading_gallery => { gallery_info.title.push_str(&e.unescape()?); } Ok(Event::End(e)) if reading_gallery && e.local_name().as_ref() == "a".as_bytes() => { results.push(gallery_info); reading_gallery = false; gallery_info = structs::MiniGalleryInfo { id: 0, title: "".to_string(), }; } Ok(Event::Eof) => break, // why cast? i have no idea, the compiler just doesn't see the From Err(err) => return Err(structs::Error::QuickXML(err)), _ => {} }; } Ok(results) }