Downloader: Update the progress index of downloads.
This commit is contained in:
@@ -8,6 +8,7 @@ use std::fs::{rename, DirBuilder, File};
|
||||
use std::io::{BufWriter, Read, Write};
|
||||
use std::path::Path;
|
||||
use std::fs;
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
use errors::*;
|
||||
use hammond_data::{EpisodeWidgetQuery, PodcastCoverQuery};
|
||||
@@ -16,6 +17,11 @@ use hammond_data::xdg_dirs::{DL_DIR, HAMMOND_CACHE};
|
||||
// TODO: Replace path that are of type &str with std::path.
|
||||
// TODO: Have a convention/document absolute/relative paths, if they should end with / or not.
|
||||
|
||||
pub trait DownloadProgress {
|
||||
fn set_downloaded(&mut self, downloaded: u64);
|
||||
fn set_size(&mut self, bytes: u64);
|
||||
}
|
||||
|
||||
// Adapted from https://github.com/mattgathu/rget .
|
||||
// I never wanted to write a custom downloader.
|
||||
// Sorry to those who will have to work with that code.
|
||||
@@ -23,7 +29,12 @@ use hammond_data::xdg_dirs::{DL_DIR, HAMMOND_CACHE};
|
||||
// or bindings for a lib like youtube-dl(python),
|
||||
// But cant seem to find one.
|
||||
// TODO: Write unit-tests.
|
||||
fn download_into(dir: &str, file_title: &str, url: &str) -> Result<String> {
|
||||
fn download_into(
|
||||
dir: &str,
|
||||
file_title: &str,
|
||||
url: &str,
|
||||
progress: Option<Arc<Mutex<DownloadProgress>>>,
|
||||
) -> Result<String> {
|
||||
info!("GET request to: {}", url);
|
||||
let client = reqwest::Client::builder().referer(false).build()?;
|
||||
let mut resp = client.get(url).send()?;
|
||||
@@ -47,8 +58,15 @@ fn download_into(dir: &str, file_title: &str, url: &str) -> Result<String> {
|
||||
let tempdir = TempDir::new_in(HAMMOND_CACHE.to_str().unwrap(), "temp_download")?;
|
||||
let out_file = format!("{}/temp.part", tempdir.path().to_str().unwrap(),);
|
||||
|
||||
ct_len.map(|x| {
|
||||
if let Some(p) = progress.clone() {
|
||||
let mut m = p.lock().unwrap();
|
||||
m.set_size(x);
|
||||
}
|
||||
});
|
||||
|
||||
// Save requested content into the file.
|
||||
save_io(&out_file, &mut resp, ct_len)?;
|
||||
save_io(&out_file, &mut resp, ct_len, progress)?;
|
||||
|
||||
// Construct the desired path.
|
||||
let target = format!("{}/{}.{}", dir, file_title, ext);
|
||||
@@ -73,8 +91,14 @@ fn get_ext(content: Option<ContentType>) -> Option<String> {
|
||||
}
|
||||
|
||||
// TODO: Write unit-tests.
|
||||
// TODO: Refactor... Somehow.
|
||||
/// Handles the I/O of fetching a remote file and saving into a Buffer and A File.
|
||||
fn save_io(file: &str, resp: &mut reqwest::Response, content_lenght: Option<u64>) -> Result<()> {
|
||||
fn save_io(
|
||||
file: &str,
|
||||
resp: &mut reqwest::Response,
|
||||
content_lenght: Option<u64>,
|
||||
progress: Option<Arc<Mutex<DownloadProgress>>>,
|
||||
) -> Result<()> {
|
||||
info!("Downloading into: {}", file);
|
||||
let chunk_size = match content_lenght {
|
||||
Some(x) => x as usize / 99,
|
||||
@@ -89,6 +113,14 @@ fn save_io(file: &str, resp: &mut reqwest::Response, content_lenght: Option<u64>
|
||||
buffer.truncate(bcount);
|
||||
if !buffer.is_empty() {
|
||||
writer.write_all(buffer.as_slice())?;
|
||||
if let Some(prog) = progress.clone() {
|
||||
// This sucks.
|
||||
let len = writer.get_ref().metadata().map(|x| x.len());
|
||||
if let Ok(l) = len {
|
||||
let mut m = prog.lock().unwrap();
|
||||
m.set_downloaded(l);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
@@ -107,7 +139,11 @@ pub fn get_download_folder(pd_title: &str) -> Result<String> {
|
||||
}
|
||||
|
||||
// TODO: Refactor
|
||||
pub fn get_episode(ep: &mut EpisodeWidgetQuery, download_folder: &str) -> Result<()> {
|
||||
pub fn get_episode(
|
||||
ep: &mut EpisodeWidgetQuery,
|
||||
download_folder: &str,
|
||||
progress: Option<Arc<Mutex<DownloadProgress>>>,
|
||||
) -> Result<()> {
|
||||
// Check if its alrdy downloaded
|
||||
if ep.local_uri().is_some() {
|
||||
if Path::new(ep.local_uri().unwrap()).exists() {
|
||||
@@ -119,7 +155,12 @@ pub fn get_episode(ep: &mut EpisodeWidgetQuery, download_folder: &str) -> Result
|
||||
ep.save()?;
|
||||
};
|
||||
|
||||
let res = download_into(download_folder, &ep.rowid().to_string(), ep.uri().unwrap());
|
||||
let res = download_into(
|
||||
download_folder,
|
||||
&ep.rowid().to_string(),
|
||||
ep.uri().unwrap(),
|
||||
progress,
|
||||
);
|
||||
|
||||
if let Ok(path) = res {
|
||||
// If download succedes set episode local_uri to dlpath.
|
||||
@@ -166,7 +207,7 @@ pub fn cache_image(pd: &PodcastCoverQuery) -> Option<String> {
|
||||
.create(&cache_download_fold)
|
||||
.unwrap();
|
||||
|
||||
match download_into(&cache_download_fold, "cover", &url) {
|
||||
match download_into(&cache_download_fold, "cover", &url, None) {
|
||||
Ok(path) => {
|
||||
info!("Cached img into: {}", &path);
|
||||
Some(path)
|
||||
|
||||
Reference in New Issue
Block a user