use std::{io::ErrorKind, path::PathBuf}; use reqwest::header::HeaderValue; use tokio::fs; use tracing::{error, trace, warn}; use url::Url; pub fn as_path(url: &Url, content_type: &HeaderValue) -> PathBuf { // extract data from url to save it accurately let mut url_path = PathBuf::from("./downloaded/".to_string() + url.domain().unwrap_or("UnknownDomain") + url.path()); if let Ok(header) = content_type.to_str() { // text/html; charset=UTF-8; option=value let ttype = if let Some((t, _)) = header.split_once(';') { t } else { header }; if let Some((ttype, subtype)) = ttype.split_once('/') { trace!(url = url.to_string(), main_type = ttype, sub_type = subtype, "Found Content-Type to be: {ttype}/{subtype}"); // If the Content-Type header is "*/html" (most likely "text/html") and the path's // extension is anything but html: if subtype=="html" && !url_path.extension().is_some_and(|f| f=="html" || f=="htm" ) { // time to slap a index.html to the end of that path there! url_path = url_path.join("index.html"); } } } else { warn!("Header: {:?} couldn't be parsed into a string!", content_type); } trace!(url = url.to_string(), path = &*url_path.to_string_lossy(), "Converted URL into path"); url_path } pub async fn init(filename: &PathBuf) -> Option { let file = async || tokio::fs::OpenOptions::new() .write(true) .append(true) .create(true) .open(&filename).await; match file().await { Ok(ok) => { trace!("Initialized file {}", filename.to_str().unwrap_or("N/A")); Some(ok) }, Err(err) => { // the file/folder isn't found if err.kind() == ErrorKind::NotFound { if let Some(parent ) = &filename.parent() { // create the folders if let Err(err) = fs::create_dir_all(&parent).await { error!("Dir creation: {err} {:?}", filename); } else if let Ok(ok) = file().await { return Some(ok); } } else { error!("Couldn't get file's parents: {:?}", &filename); } } else if err.kind() == ErrorKind::NotADirectory { // Example: // 1. example.com/user // 2. example.com/user/post // If file 1 exists it will prevent file 2 from existing // FIXME error!("One of the parent directories is actually a file...") } else { error!("File open error: {err} {:?}", filename); } // we don't care about other errors, we can't/shouldn't fix them None } } }