resume download + fix bug where watched entries were not remembered
This commit is contained in:
parent
d1bfb69c0f
commit
2dc4c15aa2
7
.vscode/launch.json
vendored
Normal file
7
.vscode/launch.json
vendored
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
// Use IntelliSense to learn about possible attributes.
|
||||||
|
// Hover to view descriptions of existing attributes.
|
||||||
|
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||||
|
"version": "0.2.0",
|
||||||
|
"configurations": [],
|
||||||
|
}
|
@ -1,6 +1,6 @@
|
|||||||
use std::{
|
use std::{
|
||||||
error, fmt,
|
error, fmt,
|
||||||
fs::File,
|
fs::{File, OpenOptions},
|
||||||
io::{self, Read, Write},
|
io::{self, Read, Write},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -30,6 +30,16 @@ impl DualWriter {
|
|||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn len(&self) -> u64 {
|
||||||
|
match self {
|
||||||
|
DualWriter::File(f) => f.metadata().and_then(|x| Ok(x.len())).unwrap_or_else(|e| {
|
||||||
|
println!("Could not get metadata from file {:?}", e);
|
||||||
|
0
|
||||||
|
}),
|
||||||
|
DualWriter::Buffer(buf) => buf.len() as u64,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TryFrom<Option<&str>> for DualWriter {
|
impl TryFrom<Option<&str>> for DualWriter {
|
||||||
@ -37,7 +47,18 @@ impl TryFrom<Option<&str>> for DualWriter {
|
|||||||
|
|
||||||
fn try_from(file_name: Option<&str>) -> Result<Self, Self::Error> {
|
fn try_from(file_name: Option<&str>) -> Result<Self, Self::Error> {
|
||||||
Ok(if let Some(file_name) = file_name {
|
Ok(if let Some(file_name) = file_name {
|
||||||
Self::File(File::create(&file_name)?)
|
let file = match OpenOptions::new().append(true).open(&file_name) {
|
||||||
|
Ok(f) => f,
|
||||||
|
Err(e) => {
|
||||||
|
let e = e as io::Error;
|
||||||
|
if e.kind() == io::ErrorKind::NotFound {
|
||||||
|
File::create(&file_name)?
|
||||||
|
} else {
|
||||||
|
return Err(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Self::File(file)
|
||||||
} else {
|
} else {
|
||||||
Self::Buffer(Vec::<u8>::new())
|
Self::Buffer(Vec::<u8>::new())
|
||||||
})
|
})
|
||||||
@ -72,16 +93,21 @@ pub async fn download_with_progress(
|
|||||||
let mut dual_writer: DualWriter = file_name.try_into()?;
|
let mut dual_writer: DualWriter = file_name.try_into()?;
|
||||||
|
|
||||||
let client = Client::builder().gzip(true).deflate(true).build()?;
|
let client = Client::builder().gzip(true).deflate(true).build()?;
|
||||||
let resp = client.get(link).send().await?;
|
let builder = client
|
||||||
let content_length = if let Some(got_content_length) = resp.content_length() {
|
.get(link)
|
||||||
got_content_length
|
.header("Range", format!("bytes={}-", dual_writer.len()));
|
||||||
} else {
|
|
||||||
panic!("Could not retrive content length from server. {:?}", &resp);
|
let resp = builder.send().await?;
|
||||||
};
|
|
||||||
|
let content_length = resp.content_length().unwrap_or_default();
|
||||||
|
if content_length == 0 {
|
||||||
|
println!("File was already downloaded");
|
||||||
|
return Ok(dual_writer);
|
||||||
|
}
|
||||||
|
|
||||||
let progress_bar = ProgressBar::new(content_length);
|
let progress_bar = ProgressBar::new(content_length);
|
||||||
progress_bar.set_style(ProgressStyle::with_template("{spinner:.green} [{elapsed_precise}] [{wide_bar:.cyan/blue}] {bytes}/{total_bytes} ({eta})").unwrap()
|
progress_bar.set_style(ProgressStyle::with_template("{spinner:.green} [{elapsed_precise}] [{wide_bar:.cyan/blue}] {bytes}/{total_bytes} ({eta})").unwrap()
|
||||||
.with_key("eta", |state: &ProgressState, w: &mut dyn fmt::Write| write!(w, "{:.1}s", state.eta().as_secs_f64()).unwrap())
|
.with_key("eta", |state: &ProgressState, w: &mut dyn fmt::Write| write!(w, "{:.1}m", state.eta().as_secs_f64() / 60.0 ).unwrap())
|
||||||
.progress_chars("#>-"));
|
.progress_chars("#>-"));
|
||||||
|
|
||||||
let mut downloaded: u64 = 0;
|
let mut downloaded: u64 = 0;
|
||||||
|
@ -70,19 +70,15 @@ impl GrandMother {
|
|||||||
println!("Retrying {}/{}", counter, MAX_TRIES);
|
println!("Retrying {}/{}", counter, MAX_TRIES);
|
||||||
};
|
};
|
||||||
|
|
||||||
let watched_links = self
|
let watched_links = self.parser.get_watched_links();
|
||||||
.parser
|
let watched_links = watched_links.iter().map(|x| x.as_str()).collect();
|
||||||
.get_watched()
|
|
||||||
.iter()
|
|
||||||
.map(|x| x.link.as_str())
|
|
||||||
.collect();
|
|
||||||
self.parser = Box::new(OnlineParser::new(&content, &watched_links).await);
|
self.parser = Box::new(OnlineParser::new(&content, &watched_links).await);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn save_watched(&self) {
|
pub fn save_watched(&self) {
|
||||||
let watched_items = self.parser.get_watched();
|
let watched_items = self.parser.get_watched_links();
|
||||||
|
|
||||||
let resp = fs::write(
|
let resp = fs::write(
|
||||||
&self.config.seen_links_path,
|
&self.config.seen_links_path,
|
||||||
|
@ -214,7 +214,6 @@ async fn main() {
|
|||||||
println!("Not possible to refresh playlist while in offlinemode");
|
println!("Not possible to refresh playlist while in offlinemode");
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
|
|
||||||
stream(to_play, &*path_link, mpv_fs);
|
stream(to_play, &*path_link, mpv_fs);
|
||||||
gm.save_watched();
|
gm.save_watched();
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,7 @@ pub trait GetM3u8 {
|
|||||||
|
|
||||||
pub trait WatchedFind {
|
pub trait WatchedFind {
|
||||||
fn find(&self, name: &str) -> Vec<&M3u8>;
|
fn find(&self, name: &str) -> Vec<&M3u8>;
|
||||||
fn get_watched(&self) -> Vec<&M3u8>;
|
fn get_watched_links(&self) -> Vec<Rc<String>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: ?Sized + GetM3u8> WatchedFind for T {
|
impl<T: ?Sized + GetM3u8> WatchedFind for T {
|
||||||
@ -20,8 +20,12 @@ impl<T: ?Sized + GetM3u8> WatchedFind for T {
|
|||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_watched(&self) -> Vec<&M3u8> {
|
fn get_watched_links(&self) -> Vec<Rc<String>> {
|
||||||
self.get_m3u8().into_iter().filter(|x| x.watched).collect()
|
self.get_m3u8()
|
||||||
|
.into_iter()
|
||||||
|
.filter(|x| x.watched)
|
||||||
|
.map(|x| x.link.clone())
|
||||||
|
.collect()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub trait GetPlayPath {
|
pub trait GetPlayPath {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user