From eb8fdb2edbcc43c155fe6922f8cd2fcc9181736e Mon Sep 17 00:00:00 2001 From: Jordan Petridis Date: Sat, 28 Oct 2017 06:57:32 +0300 Subject: [PATCH] Implemented a downloaded/watched cleaner. --- Cargo.lock | 1 + hammond-data/Cargo.toml | 1 + hammond-data/src/dbcheckup.rs | 81 ++++++++++++++++++++++++++++++ hammond-data/src/dbqueries.rs | 19 ++++++- hammond-data/src/lib.rs | 2 + hammond-data/src/models.rs | 10 ++++ hammond-gtk/src/widgets/episode.rs | 36 +++---------- 7 files changed, 120 insertions(+), 30 deletions(-) create mode 100644 hammond-data/src/dbcheckup.rs diff --git a/Cargo.lock b/Cargo.lock index b5a444a..1d373c0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -618,6 +618,7 @@ dependencies = [ name = "hammond-data" version = "0.1.0" dependencies = [ + "chrono 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "diesel 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)", "diesel_codegen 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)", "dotenv 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/hammond-data/Cargo.toml b/hammond-data/Cargo.toml index 8cce8fb..edf33a7 100644 --- a/hammond-data/Cargo.toml +++ b/hammond-data/Cargo.toml @@ -16,6 +16,7 @@ diesel_codegen = { version = "0.16", features = ["sqlite"] } xdg = "2.1" lazy_static = "0.2" rss = "1.1" +chrono = "0.4" # overwrite diesel dependancy that disables a feature rss depends upon dotenv = "*" diff --git a/hammond-data/src/dbcheckup.rs b/hammond-data/src/dbcheckup.rs new file mode 100644 index 0000000..e41fa7e --- /dev/null +++ b/hammond-data/src/dbcheckup.rs @@ -0,0 +1,81 @@ +use rayon::prelude::*; + +use errors::*; +use dbqueries; +use index_feed::Database; +use models::Episode; +use chrono::prelude::*; + +use std::path::Path; +use std::fs; + +// TODO: Write unit test. +pub fn download_checker(db: Database) -> Result<()> { + let mut episodes = { + let tempdb = db.lock().unwrap(); + dbqueries::get_downloaded_episodes(&tempdb)? + }; + + episodes.par_iter_mut().for_each(|ep| { + if ep.local_uri().is_some() { + if !Path::new(ep.local_uri().unwrap()).exists() { + ep.set_local_uri(None); + let res = ep.save(&db.clone()); + if let Err(err) = res { + error!("Error while trying to update episode: {:#?}", ep); + error!("Error: {}", err); + }; + } + } + }); + + Ok(()) +} + +// TODO: Write unit test. +pub fn watched_cleaner(db: &Database) -> Result<()> { + let mut episodes = { + let tempdb = db.lock().unwrap(); + dbqueries::get_watched_episodes(&tempdb)? + }; + + let now_utc = Utc::now().timestamp() as i32; + episodes.par_iter_mut().for_each(|mut ep| { + if ep.local_uri().is_some() && ep.watched().is_some() { + let watched = ep.watched().unwrap().clone(); + // TODO: expose a config and a user set option. + let limit = watched + 172_800; // add 2days in seconds + if now_utc > limit { + let e = delete_local_content(db, &mut ep); + if let Err(err) = e { + error!("Error while trying to delete file: {:?}", ep.local_uri()); + error!("Error: {}", err); + }; + } + } + }); + Ok(()) +} + +// TODO: Write unit test. +pub fn delete_local_content(db: &Database, ep: &mut Episode) -> Result<()> { + if ep.local_uri().is_some() { + let uri = ep.local_uri().unwrap().to_owned(); + if Path::new(&uri).exists() { + let res = fs::remove_file(&uri); + if res.is_ok() { + ep.set_local_uri(None); + ep.save(db)?; + } else { + error!("Error while trying to delete file: {}", uri); + error!("Error: {}", res.unwrap_err()); + }; + } + } else { + error!( + "Something went wrong evaluating the following path: {:?}", + ep.local_uri(), + ); + } + Ok(()) +} diff --git a/hammond-data/src/dbqueries.rs b/hammond-data/src/dbqueries.rs index 382788e..9e9204a 100644 --- a/hammond-data/src/dbqueries.rs +++ b/hammond-data/src/dbqueries.rs @@ -37,6 +37,20 @@ pub fn get_episodes(con: &SqliteConnection) -> QueryResult> { eps } +pub fn get_downloaded_episodes(con: &SqliteConnection) -> QueryResult> { + use schema::episode::dsl::*; + + let eps = episode.filter(local_uri.is_not_null()).load::(con); + eps +} + +pub fn get_watched_episodes(con: &SqliteConnection) -> QueryResult> { + use schema::episode::dsl::*; + + let eps = episode.filter(watched.is_not_null()).load::(con); + eps +} + pub fn get_episode(con: &SqliteConnection, ep_id: i32) -> QueryResult { use schema::episode::dsl::*; @@ -44,7 +58,10 @@ pub fn get_episode(con: &SqliteConnection, ep_id: i32) -> QueryResult { ep } -pub fn get_episode_local_uri(con: &SqliteConnection, ep_id: i32) -> QueryResult> { +pub fn get_episode_from_local_uri( + con: &SqliteConnection, + ep_id: i32, +) -> QueryResult> { use schema::episode::dsl::*; let ep = episode diff --git a/hammond-data/src/lib.rs b/hammond-data/src/lib.rs index 97a9f6e..28cef58 100644 --- a/hammond-data/src/lib.rs +++ b/hammond-data/src/lib.rs @@ -16,6 +16,7 @@ extern crate diesel; #[macro_use] extern crate diesel_codegen; +extern crate chrono; extern crate hyper; extern crate rayon; extern crate reqwest; @@ -24,6 +25,7 @@ extern crate rss; extern crate xdg; pub mod dbqueries; +pub mod dbcheckup; pub mod models; pub mod index_feed; pub mod errors; diff --git a/hammond-data/src/models.rs b/hammond-data/src/models.rs index b1b2614..267ffa1 100644 --- a/hammond-data/src/models.rs +++ b/hammond-data/src/models.rs @@ -17,9 +17,11 @@ pub struct Episode { local_uri: Option, description: Option, published_date: Option, + /// Representation of system time. Should be in UTC. epoch: i32, length: Option, guid: Option, + /// Represent the epoch value of when the episode was last watched. watched: Option, podcast_id: i32, } @@ -94,6 +96,14 @@ impl Episode { self.length = value; } + pub fn watched(&self) -> Option { + self.watched + } + + pub fn set_watched(&mut self, value: Option) { + self.watched = value; + } + pub fn save(&self, db: &Database) -> Result<()> { let tempdb = db.lock().unwrap(); self.save_changes::(&*tempdb)?; diff --git a/hammond-gtk/src/widgets/episode.rs b/hammond-gtk/src/widgets/episode.rs index d56fe25..90001f7 100644 --- a/hammond-gtk/src/widgets/episode.rs +++ b/hammond-gtk/src/widgets/episode.rs @@ -4,6 +4,7 @@ use hammond_data::dbqueries; use hammond_data::models::Episode; use hammond_downloader::downloader; use hammond_data::index_feed::Database; +use hammond_data::dbcheckup::delete_local_content; use dissolve::strip_html_tags; @@ -11,7 +12,6 @@ use std::thread; use std::cell::RefCell; use std::sync::mpsc::{channel, Receiver}; use std::path::Path; -use std::fs; use glib; use gtk; @@ -141,7 +141,7 @@ fn on_download_clicked( fn on_play_bttn_clicked(db: &Database, episode_id: i32) { let local_uri = { let tempdb = db.lock().unwrap(); - dbqueries::get_episode_local_uri(&tempdb, episode_id).unwrap() + dbqueries::get_episode_from_local_uri(&tempdb, episode_id).unwrap() }; if let Some(uri) = local_uri { @@ -167,33 +167,11 @@ fn on_delete_bttn_clicked(db: &Database, episode_id: i32) { dbqueries::get_episode(&tempdb, episode_id).unwrap() }; - let ep2 = ep.clone(); - let local_uri = ep2.local_uri(); - - if local_uri.is_some() { - let uri = local_uri.unwrap().to_owned(); - if Path::new(&uri).exists() { - let res = fs::remove_file(&uri); - if res.is_ok() { - ep.set_local_uri(None); - let res2 = ep.save(db); - if res2.is_ok() { - info!("Deleted file at: {}", uri); - } else { - error!("Error while trying to delete file: {}", uri); - error!("Error: {}", res2.unwrap_err()); - } - } else { - error!("Error while trying to delete file: {}", uri); - error!("Error: {}", res.unwrap_err()); - }; - } - } else { - error!( - "Something went wrong evaluating the following path: {:?}", - local_uri - ); - } + let e = delete_local_content(db, &mut ep); + if let Err(err) = e { + error!("Error while trying to delete file: {:?}", ep.local_uri()); + error!("Error: {}", err); + }; } fn receive() -> glib::Continue {