diff options
| -rw-r--r-- | Cargo.toml | 4 | ||||
| -rw-r--r-- | src/actions.rs | 104 | ||||
| -rw-r--r-- | src/main.rs | 47 | 
3 files changed, 147 insertions, 8 deletions
| @@ -1,7 +1,7 @@  [package]  name = "podcast"  edition = "2018" -version = "0.6.1" +version = "0.7.0"  authors = ["Nathan Jaremko <njaremko@gmail.com>"]  description = "A command line podcast manager"  license = "GPL-3.0" @@ -25,7 +25,7 @@ dirs = "1.0"  error-chain = "0.12"  lazy_static = "1.2"  rayon = "1.0" -regex = "1.0" +regex = "1.1"  reqwest = "0.9"  rss = {version = "1.6", features = ["from_url"] }  serde = "1.0" diff --git a/src/actions.rs b/src/actions.rs index 0775aec..58cda4f 100644 --- a/src/actions.rs +++ b/src/actions.rs @@ -151,7 +151,7 @@ pub fn download_range(state: &State, p_search: &str, e_search: &str) -> Result<(      Ok(())  } -pub fn download_episode(state: &State, p_search: &str, e_search: &str) -> Result<()> { +pub fn download_episode_by_num(state: &State, p_search: &str, e_search: &str) -> Result<()> {      let re_pod = Regex::new(&format!("(?i){}", &p_search)).chain_err(|| UNABLE_TO_PARSE_REGEX)?;      let ep_num = e_search          .parse::<usize>() @@ -170,6 +170,52 @@ pub fn download_episode(state: &State, p_search: &str, e_search: &str) -> Result      Ok(())  } +pub fn download_episode_by_name( +    state: &State, +    p_search: &str, +    e_search: &str, +    download_all: bool, +) -> Result<()> { +    let re_pod = Regex::new(&format!("(?i){}", &p_search)).chain_err(|| UNABLE_TO_PARSE_REGEX)?; + +    for subscription in &state.subscriptions { +        if re_pod.is_match(&subscription.title) { +            let podcast = Podcast::from_title(&subscription.title) +                .chain_err(|| UNABLE_TO_RETRIEVE_PODCAST_BY_TITLE)?; +            let episodes = podcast.episodes(); +            if download_all { +                episodes +                    .iter() +                    .filter(|ep| { +                        ep.title() +                            .unwrap_or_else(|| "".to_string()) +                            .contains(e_search) +                    }) +                    .for_each(|ep| { +                        ep.download(podcast.title()).unwrap_or_else(|_| { +                            println!("Error downloading episode: {}", podcast.title()) +                        }); +                    }) +            } else { +                let filtered_episodes: Vec<&Episode> = episodes +                    .iter() +                    .filter(|ep| { +                        ep.title() +                            .unwrap_or_else(|| "".to_string()) +                            .contains(e_search) +                    }) +                    .collect(); + +                if let Some(ep) = filtered_episodes.first() { +                    ep.download(podcast.title()) +                        .chain_err(|| "unable to download episode")?; +                } +            } +        } +    } +    Ok(()) +} +  pub fn download_all(state: &State, p_search: &str) -> Result<()> {      let re_pod = Regex::new(&format!("(?i){}", &p_search)).chain_err(|| UNABLE_TO_PARSE_REGEX)?; @@ -240,7 +286,7 @@ pub fn play_latest(state: &State, p_search: &str) -> Result<()> {      Ok(())  } -pub fn play_episode(state: &State, p_search: &str, ep_num_string: &str) -> Result<()> { +pub fn play_episode_by_num(state: &State, p_search: &str, ep_num_string: &str) -> Result<()> {      let re_pod: Regex =          Regex::new(&format!("(?i){}", &p_search)).chain_err(|| UNABLE_TO_PARSE_REGEX)?;      let ep_num: usize = ep_num_string.parse::<usize>().unwrap(); @@ -287,6 +333,60 @@ pub fn play_episode(state: &State, p_search: &str, ep_num_string: &str) -> Resul      Ok(())  } +pub fn play_episode_by_name(state: &State, p_search: &str, ep_string: &str) -> Result<()> { +    let re_pod: Regex = +        Regex::new(&format!("(?i){}", &p_search)).chain_err(|| UNABLE_TO_PARSE_REGEX)?; +    let mut path: PathBuf = get_xml_dir()?; +    if let Err(err) = DirBuilder::new().recursive(true).create(&path) { +        eprintln!( +            "Couldn't create directory: {}\nReason: {}", +            path.to_str().unwrap(), +            err +        ); +        return Ok(()); +    } +    for subscription in &state.subscriptions { +        if re_pod.is_match(&subscription.title) { +            let mut filename: String = subscription.title.clone(); +            filename.push_str(".xml"); +            path.push(filename); + +            let mut file: File = File::open(&path).unwrap(); +            let mut content: Vec<u8> = Vec::new(); +            file.read_to_end(&mut content).unwrap(); + +            let podcast = Podcast::from(Channel::read_from(content.as_slice()).unwrap()); +            let episodes = podcast.episodes(); +            let filtered_episodes: Vec<&Episode> = episodes +                .iter() +                .filter(|ep| { +                    ep.title() +                        .unwrap_or_else(|| "".to_string()) +                        .contains(ep_string) +                }) +                .collect(); +            if let Some(episode) = filtered_episodes.first() { +                filename = episode.title().unwrap(); +                filename.push_str(episode.extension().unwrap()); +                path = get_podcast_dir()?; +                path.push(podcast.title()); +                path.push(filename); +                if path.exists() { +                    launch_player(path.to_str().chain_err(|| UNABLE_TO_CONVERT_TO_STR)?)?; +                } else { +                    launch_player( +                        episode +                            .url() +                            .chain_err(|| "unable to retrieve episode url")?, +                    )?; +                } +            } +            return Ok(()); +        } +    } +    Ok(()) +} +  pub fn check_for_update(version: &str) -> Result<()> {      println!("Checking for updates...");      let resp: String = diff --git a/src/main.rs b/src/main.rs index 3c03ab0..4eba999 100644 --- a/src/main.rs +++ b/src/main.rs @@ -22,7 +22,7 @@ pub mod structs;  pub mod utils;  pub mod errors {      // Create the Error, ErrorKind, ResultExt, and Result types -    error_chain!{} +    error_chain! {}  }  use self::actions::*; @@ -51,7 +51,26 @@ fn main() -> Result<()> {                          .required(true)                          .index(1),                  ) -                .arg(Arg::with_name("EPISODE").help("Episode index").index(2)), +                .arg( +                    Arg::with_name("EPISODE") +                        .required(false) +                        .help("Episode index") +                        .index(2), +                ) +                .arg( +                    Arg::with_name("name") +                        .short("e") +                        .long("episode") +                        .help("Download using episode name instead of number") +                        .required(false), +                ) +                .arg( +                    Arg::with_name("all") +                        .short("a") +                        .long("all") +                        .help("Download all matching episodes") +                        .required(false), +                ),          )          .subcommand(              SubCommand::with_name("ls") @@ -85,6 +104,13 @@ fn main() -> Result<()> {                          .help("Episode index")                          .required(false)                          .index(2), +                ) +                .arg( +                    Arg::with_name("name") +                        .short("e") +                        .long("episode") +                        .help("Play using episode name instead of number") +                        .required(false),                  ),          )          .subcommand( @@ -142,8 +168,15 @@ fn main() -> Result<()> {                  Some(ep) => {                      if String::from(ep).contains(|c| c == '-' || c == ',') {                          download_range(&state, podcast, ep)? +                    } else if download_matches.occurrences_of("name") > 0 { +                        download_episode_by_name( +                            &state, +                            podcast, +                            ep, +                            download_matches.occurrences_of("all") > 0, +                        )?                      } else { -                        download_episode(&state, podcast, ep)? +                        download_episode_by_num(&state, podcast, ep)?                      }                  }                  None => download_all(&state, podcast)?, @@ -167,7 +200,13 @@ fn main() -> Result<()> {                  .value_of("PODCAST")                  .chain_err(|| "unable to find subcommand match")?;              match play_matches.value_of("EPISODE") { -                Some(episode) => play_episode(&state, podcast, episode)?, +                Some(episode) => { +                    if play_matches.occurrences_of("name") > 0 { +                        play_episode_by_name(&state, podcast, episode)? +                    } else { +                        play_episode_by_num(&state, podcast, episode)? +                    } +                }                  None => play_latest(&state, podcast)?,              }          } | 
