78 lines
2.9 KiB
Rust
78 lines
2.9 KiB
Rust
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<fs::File> {
|
|
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
|
|
}
|
|
}
|
|
}
|