pub mod errors;
pub mod header;
pub mod resource;
pub mod twitter;
pub mod youtube;
use crate::errors::DownloadError;
use std::{future::Future, path::Path};
use url::Url;
#[async_trait::async_trait]
pub trait Downloader {
fn parse_url(link: &str, expected_url_format: Option<&str>) -> Result<Url, DownloadError> {
let expected_format =
expected_url_format.unwrap_or("https://www.<domain>.<extension>/<parameters>");
let url = Url::parse(link).map_err(|_| {
DownloadError::InvalidUrl(
format!("Invalid URL format! Please provide a URL in the format: {expected_format}. Ensure the URL includes a valid domain, extension, and any necessary parameters.")
,
)
})?;
Ok(url)
}
fn is_valid_url(url: &Url) -> bool;
fn print_dl_status(&mut self) -> &mut Self {
let status = self.get_dl_status();
*status = true;
self
}
fn get_dl_status(&mut self) -> &mut bool;
fn sanitize_file_name(s: &str) -> String {
s.replace("\\", "|").replace("/", "|")
}
async fn download(&self) -> Result<(), DownloadError> {
self.download_to("./").await
}
async fn download_to<P: AsRef<Path> + std::marker::Send>(
&self,
folder_path: P,
) -> Result<(), DownloadError>;
fn blocking_download(&self) -> Result<(), DownloadError>
where
Self: Sync,
{
Self::blocking(async { self.download().await })
}
fn blocking_download_to<P: AsRef<Path> + std::marker::Send>(
&self,
path: P,
) -> Result<(), DownloadError>
where
Self: Sync,
{
Self::blocking(async { self.download_to(path).await })
}
fn blocking<F: Future>(async_block: F) -> Result<(), DownloadError> {
let rt = tokio::runtime::Builder::new_multi_thread()
.enable_all()
.build()
.map_err(|_| {
DownloadError::FailedToBuildBlockingRuntime(
"Failed to build blocking runtime".to_owned(),
)
})?;
rt.block_on(async_block);
Ok(())
}
}
pub mod prelude {
pub use crate::errors::DownloadError;
pub use crate::Downloader;
pub use crate::resource::ResourceDownloader;
pub use crate::twitter::TwitterDownloader;
pub use crate::youtube::YoutubeDownloader;
}