diff --git a/Cargo.lock b/Cargo.lock index fbfb0cb..dde269e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1169,6 +1169,7 @@ dependencies = [ "reqwest", "spin_on", "tokio", + "url", "urlparse", "utf16string", "winapi", diff --git a/Cargo.toml b/Cargo.toml index d574139..9f002b1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -27,6 +27,7 @@ reqwest = { version = "0.11", features = ["brotli", "deflate", "gzip", "rustls-t RustyXML = "0.3" spin_on = "0.1.1" tokio = { version = "1.18", features = ["rt", "macros", "rt-multi-thread", "time"] } +url = "2.2" urlparse = "0.7" utf16string = { version= "0.2", optional = true } diff --git a/src/download.rs b/src/download.rs index 74b9583..a6580e8 100644 --- a/src/download.rs +++ b/src/download.rs @@ -7,7 +7,7 @@ use crate::data::json::JSONDataFile; #[cfg(feature = "ugoira")] use crate::data::video::get_video_metadata; use crate::downloader::pd_file::enums::PdFileResult; -use crate::downloader::pd_file::file::PdFile; +use crate::downloader::pd_file::PdFile; use crate::gettext; use crate::opthelper::OptHelper; use crate::pixiv_link::PixivID; diff --git a/src/downloader/downloader.rs b/src/downloader/downloader.rs new file mode 100644 index 0000000..049bb94 --- /dev/null +++ b/src/downloader/downloader.rs @@ -0,0 +1,75 @@ +use super::pd_file::PdFile; +use super::pd_file::PdFileResult; +use super::error::DownloaderError; +use crate::webclient::WebClient; +use crate::webclient::ToHeaders; +use reqwest::IntoUrl; +use std::collections::HashMap; +use std::fs::File; +use std::path::Path; +use std::sync::Arc; +use std::sync::RwLock; +use url::Url; + +/// A file downloader +pub struct Downloader { + /// The webclient + client: Arc, + /// The download status + status: Arc, + /// The url of the file + url: Arc, + /// The HTTP headers map + headers: Arc>, + /// The target file + file: RwLock>, +} + +impl Downloader { + /// Create a new [Downloader] instance + /// * `url` - The url of the file + /// * `header` - HTTP headers + /// * `path` - The path to store downloaded file. + /// * `overwrite` - Whether to overwrite file + pub fn new + ?Sized>(url: U, headers: H, path: Option<&P>, overwrite: Option) -> Result { + let h = match headers.to_headers() { + Some(h) => { h } + None => { HashMap::new() } + }; + let mut already_exists = false; + let pd_file = match path { + Some(p) => { + let p = p.as_ref(); + match PdFile::open(p)? { + PdFileResult::TargetExisted => { + // #TODO + PdFile::new() + } + PdFileResult::Ok(p) => { p } + PdFileResult::ExistedOk(p) => { + already_exists = true; + p + } + } + } + None => { PdFile::new() } + }; + let file = match path { + Some(p) => { + if already_exists { + Some(File::open(p)?) + } else { + Some(File::create(p)?) + } + } + None => { None } + }; + Ok(Self { + client: Arc::new(WebClient::new()), + status: Arc::new(pd_file), + url: Arc::new(url.into_url()?), + headers: Arc::new(h), + file: RwLock::new(file), + }) + } +} diff --git a/src/downloader/error.rs b/src/downloader/error.rs new file mode 100644 index 0000000..8cbba5b --- /dev/null +++ b/src/downloader/error.rs @@ -0,0 +1,8 @@ +use crate::downloader::pd_file::PdFileError; + +#[derive(Debug, derive_more::From)] +pub enum DownloaderError { + ReqwestError(reqwest::Error), + PdFileError(PdFileError), + IoError(std::io::Error), +} diff --git a/src/downloader/mod.rs b/src/downloader/mod.rs index 610a386..37749fd 100644 --- a/src/downloader/mod.rs +++ b/src/downloader/mod.rs @@ -1 +1,7 @@ +/// A file downloader +pub mod downloader; +/// File downloader's error +pub mod error; +/// The pd file pub mod pd_file; +pub use downloader::Downloader; diff --git a/src/downloader/pd_file/mod.rs b/src/downloader/pd_file/mod.rs index a80f528..75f4e78 100644 --- a/src/downloader/pd_file/mod.rs +++ b/src/downloader/pd_file/mod.rs @@ -9,3 +9,6 @@ pub mod file; pub mod part_status; /// Version of the pd file pub mod version; +pub use enums::PdFileResult; +pub use error::PdFileError; +pub use file::PdFile; diff --git a/src/main.rs b/src/main.rs index 64db2c9..91ecee7 100644 --- a/src/main.rs +++ b/src/main.rs @@ -19,6 +19,7 @@ extern crate proc_macros; extern crate tokio; extern crate regex; extern crate reqwest; +extern crate url; extern crate urlparse; #[cfg(feature = "utf16string")] extern crate utf16string; diff --git a/src/pixiv_web.rs b/src/pixiv_web.rs index 8f48061..fb6b6ee 100644 --- a/src/pixiv_web.rs +++ b/src/pixiv_web.rs @@ -1,4 +1,4 @@ -use crate::downloader::pd_file::file::PdFile; +use crate::downloader::pd_file::PdFile; use crate::ext::rw_lock::GetRwLock; use crate::gettext; use crate::opthelper::OptHelper;