diff options
Diffstat (limited to 'src/structs.rs')
| -rw-r--r-- | src/structs.rs | 168 | 
1 files changed, 84 insertions, 84 deletions
| diff --git a/src/structs.rs b/src/structs.rs index ac6832e..03a9932 100644 --- a/src/structs.rs +++ b/src/structs.rs @@ -1,14 +1,15 @@  use actions::*; +use errors::*;  use utils::*;  use std::collections::BTreeSet; -use std::fs::{self, remove_dir_all, remove_file, DirBuilder, File}; +use std::fs::{self, DirBuilder, File};  use std::io::{self, BufReader, Read, Write};  use chrono::prelude::*;  use rayon::prelude::*;  use reqwest; -use rss::{self, Channel, Item}; +use rss::{Channel, Item};  use serde_json;  use yaml_rust::YamlLoader; @@ -17,14 +18,18 @@ pub struct Config {  }  impl Config { -    pub fn new() -> Config { -        let mut path = get_podcast_dir(); +    pub fn new() -> Result<Config> { +        let mut path = get_podcast_dir()?;          let mut download_limit = 1;          path.push(".config");          if path.exists() {              let mut s = String::new(); -            File::open(&path).unwrap().read_to_string(&mut s).unwrap(); -            let config = YamlLoader::load_from_str(&s).unwrap(); +            File::open(&path) +                .chain_err(|| UNABLE_TO_OPEN_FILE)? +                .read_to_string(&mut s) +                .chain_err(|| UNABLE_TO_READ_FILE_TO_STRING)?; +            let config = +                YamlLoader::load_from_str(&s).chain_err(|| "unable to load yaml from string")?;              if !config.is_empty() {                  let doc = &config[0];                  if let Some(val) = doc["auto_download_limit"].as_i64() { @@ -32,12 +37,13 @@ impl Config {                  }              }          } else { -            let mut file = File::create(&path).unwrap(); -            file.write_all(b"auto_download_limit: 1").unwrap(); +            let mut file = File::create(&path).chain_err(|| UNABLE_TO_CREATE_FILE)?; +            file.write_all(b"auto_download_limit: 1") +                .chain_err(|| UNABLE_TO_WRITE_FILE)?;          } -        Config { +        Ok(Config {              auto_download_limit: download_limit, -        } +        })      }  } @@ -56,29 +62,27 @@ pub struct State {  }  impl State { -    pub fn new(version: &str) -> Result<State, String> { -        let mut path = get_podcast_dir(); +    pub fn new(version: &str) -> Result<State> { +        let mut path = get_podcast_dir()?;          path.push(".subscriptions");          if path.exists() {              let mut s = String::new(); -            let mut file = match File::open(&path) { -                Ok(val) => val, -                Err(err) => return Err(format!("{}", err)), -            }; -            if let Err(err) = file.read_to_string(&mut s) { -                return Err(format!("{}", err)); -            }; +            let mut file = File::open(&path).chain_err(|| UNABLE_TO_OPEN_FILE)?; +            file.read_to_string(&mut s) +                .chain_err(|| UNABLE_TO_READ_FILE_TO_STRING)?;              let mut state: State = match serde_json::from_str(&s) {                  Ok(val) => val,                  // This will happen if the struct has changed between versions                  Err(_) => { -                    let v: serde_json::Value = serde_json::from_str(&s).unwrap(); +                    let v: serde_json::Value = +                        serde_json::from_str(&s).chain_err(|| "unable to read json from string")?;                      State {                          version: String::from(version),                          last_run_time: Utc::now(),                          subscriptions: match serde_json::from_value(v["subscriptions"].clone()) {                              Ok(val) => val, -                            Err(_) => serde_json::from_value(v["subs"].clone()).unwrap(), +                            Err(_) => serde_json::from_value(v["subs"].clone()) +                                .chain_err(|| "unable to parse value from json")?,                          },                      }                  } @@ -90,12 +94,10 @@ impl State {                  .num_seconds() > 86400              {                  update_rss(&mut state); -                check_for_update(&state.version); +                check_for_update(&state.version)?;              }              state.last_run_time = Utc::now(); -            if let Err(err) = state.save() { -                eprintln!("{}", err); -            } +            state.save()?;              Ok(state)          } else {              Ok(State { @@ -106,7 +108,7 @@ impl State {          }      } -    pub fn subscribe(&mut self, url: &str) { +    pub fn subscribe(&mut self, url: &str) -> Result<()> {          let mut set = BTreeSet::new();          for sub in self.subscriptions() {              set.insert(sub.title); @@ -119,22 +121,21 @@ impl State {                  num_episodes: podcast.episodes().len(),              });          } -        if let Err(err) = self.save() { -            eprintln!("{}", err); -        } +        self.save()      }      pub fn subscriptions(&self) -> Vec<Subscription> {          self.subscriptions.clone()      } -    pub fn save(&self) -> Result<(), io::Error> { -        let mut path = get_podcast_dir(); +    pub fn save(&self) -> Result<()> { +        let mut path = get_podcast_dir()?;          path.push(".subscriptions.tmp"); -        let serialized = serde_json::to_string(self)?; -        let mut file = File::create(&path)?; -        file.write_all(serialized.as_bytes())?; -        fs::rename(&path, get_sub_file())?; +        let serialized = serde_json::to_string(self).chain_err(|| "unable to serialize state")?; +        let mut file = File::create(&path).chain_err(|| UNABLE_TO_CREATE_FILE)?; +        file.write_all(serialized.as_bytes()) +            .chain_err(|| UNABLE_TO_WRITE_FILE)?; +        fs::rename(&path, get_sub_file()?).chain_err(|| "unable to rename file")?;          Ok(())      }  } @@ -168,61 +169,57 @@ impl Podcast {      }      #[allow(dead_code)] -    pub fn from_url(url: &str) -> Result<Podcast, rss::Error> { -        match Channel::from_url(url) { -            Ok(val) => Ok(Podcast::from(val)), -            Err(err) => Err(err), -        } +    pub fn from_url(url: &str) -> Result<Podcast> { +        Ok( +            Podcast::from(Channel::from_url(url).chain_err(|| UNABLE_TO_CREATE_CHANNEL_FROM_RESPONSE)?), +        )      } -    pub fn from_title(title: &str) -> Result<Podcast, String> { -        let mut path = get_xml_dir(); +    pub fn from_title(title: &str) -> Result<Podcast> { +        let mut path = get_xml_dir()?;          let mut filename = String::from(title);          filename.push_str(".xml");          path.push(filename); -        match File::open(&path) { -            Ok(file) => match Channel::read_from(BufReader::new(file)) { -                Ok(podcast) => Ok(Podcast::from(podcast)), -                Err(err) => Err(format!("Error: {}", err)), -            }, -            Err(err) => Err(format!("Error: {}", err)), -        } +        let file = File::open(&path).chain_err(|| UNABLE_TO_OPEN_FILE)?; +        Ok(Podcast::from(Channel::read_from(BufReader::new(file)) +            .chain_err(|| UNABLE_TO_CREATE_CHANNEL_FROM_FILE)?))      } -    pub fn delete(title: &str) -> io::Result<()> { -        let mut path = get_xml_dir(); +    pub fn delete(title: &str) -> Result<()> { +        let mut path = get_xml_dir()?;          let mut filename = String::from(title);          filename.push_str(".xml");          path.push(filename); -        remove_file(path) +        fs::remove_file(path).chain_err(|| UNABLE_TO_REMOVE_FILE)      } -    pub fn delete_all() -> io::Result<()> { -        let path = get_xml_dir(); -        remove_dir_all(path) +    pub fn delete_all() -> Result<()> { +        let path = get_xml_dir()?; +        fs::remove_dir_all(path).chain_err(|| UNABLE_TO_READ_DIRECTORY)      }      pub fn episodes(&self) -> Vec<Episode> {          let mut result = Vec::new(); - -        let items = self.0.items().to_vec(); -        for item in items { +        for item in self.0.items().to_vec() {              result.push(Episode::from(item));          }          result      } -    pub fn download(&self) -> Result<(), io::Error> { +    pub fn download(&self) -> Result<()> {          print!("You are about to download all episodes (y/n): ");          io::stdout().flush().ok();          let mut input = String::new(); -        if io::stdin().read_line(&mut input).is_ok() && input.to_lowercase().trim() != "y" { +        io::stdin() +            .read_line(&mut input) +            .chain_err(|| "unable to read stdin")?; +        if input.to_lowercase().trim() != "y" {              return Ok(());          } -        let mut path = get_podcast_dir(); +        let mut path = get_podcast_dir()?;          path.push(self.title());          match already_downloaded(self.title()) { @@ -231,7 +228,7 @@ impl Podcast {                      if let Some(ep_title) = i.title() {                          if !downloaded.contains(ep_title) {                              if let Err(err) = i.download(self.title()) { -                                println!("{}", err); +                                eprintln!("{}", err);                              }                          }                      } @@ -240,7 +237,7 @@ impl Podcast {              Err(_) => {                  self.episodes().par_iter().for_each(|i| {                      if let Err(err) = i.download(self.title()) { -                        println!("{}", err); +                        eprintln!("{}", err);                      }                  });              } @@ -249,8 +246,8 @@ impl Podcast {          Ok(())      } -    pub fn download_specific(&self, episode_numbers: &[usize]) -> Result<(), io::Error> { -        let mut path = get_podcast_dir(); +    pub fn download_specific(&self, episode_numbers: &[usize]) -> Result<()> { +        let mut path = get_podcast_dir()?;          path.push(self.title());          let downloaded = already_downloaded(self.title())?; @@ -282,38 +279,41 @@ impl Episode {      }      pub fn extension(&self) -> Option<&str> { -        match self.0.enclosure() { -            Some(enclosure) => match enclosure.mime_type() { -                "audio/mpeg" => Some(".mp3"), -                "audio/mp4" => Some(".m4a"), -                "audio/ogg" => Some(".ogg"), -                _ => find_extension(self.url().unwrap()), -            }, -            None => None, +        match self.0.enclosure()?.mime_type() { +            "audio/mpeg" => Some(".mp3"), +            "audio/mp4" => Some(".m4a"), +            "audio/ogg" => Some(".ogg"), +            _ => find_extension(self.url().unwrap()),          }      } -    pub fn download(&self, podcast_name: &str) -> Result<(), io::Error> { -        let mut path = get_podcast_dir(); +    pub fn download(&self, podcast_name: &str) -> Result<()> { +        let mut path = get_podcast_dir()?;          path.push(podcast_name); -        DirBuilder::new().recursive(true).create(&path).unwrap(); +        DirBuilder::new() +            .recursive(true) +            .create(&path) +            .chain_err(|| UNABLE_TO_CREATE_DIRECTORY)?;          if let Some(url) = self.url() {              if let Some(title) = self.title() {                  let mut filename = String::from(title); -                filename.push_str(self.extension().unwrap()); +                filename.push_str(self.extension() +                    .chain_err(|| "unable to retrieve extension")?);                  path.push(filename);                  if !path.exists() {                      println!("Downloading: {}", path.to_str().unwrap()); -                    let mut file = File::create(&path)?; -                    let mut resp = reqwest::get(url).unwrap(); +                    let mut file = File::create(&path).chain_err(|| UNABLE_TO_CREATE_FILE)?; +                    let mut resp = reqwest::get(url).chain_err(|| UNABLE_TO_GET_HTTP_RESPONSE)?;                      let mut content: Vec<u8> = Vec::new(); -                    resp.read_to_end(&mut content)?; -                    file.write_all(&content)?; -                    return Ok(()); +                    resp.read_to_end(&mut content) +                        .chain_err(|| UNABLE_TO_READ_RESPONSE_TO_END)?; +                    file.write_all(&content).chain_err(|| UNABLE_TO_WRITE_FILE)?;                  } else { -                    println!("File already exists: {}", path.to_str().unwrap()); -                    return Ok(()); +                    println!( +                        "File already exists: {}", +                        path.to_str().chain_err(|| UNABLE_TO_CONVERT_TO_STR)? +                    );                  }              }          } | 
