diff options
| author | Nathan | 2017-07-23 12:01:23 -0400 |
|---|---|---|
| committer | Nathan | 2017-07-23 12:01:23 -0400 |
| commit | d1c2572a0cb2882b2661dafac0631e5888144dce (patch) | |
| tree | 8604681935932062cd97b8b1672d694dafc80cc1 | |
| parent | efb6ef328ca159bf4d3b5f1b02d13e1c0aef0764 (diff) | |
| download | podcast-d1c2572a0cb2882b2661dafac0631e5888144dce.tar.bz2 | |
Improve RSS downloading
| -rw-r--r-- | Cargo.toml | 2 | ||||
| -rw-r--r-- | src/actions.rs | 50 | ||||
| -rw-r--r-- | src/main.rs | 4 | ||||
| -rw-r--r-- | src/structs.rs | 32 | ||||
| -rw-r--r-- | src/utils.rs | 16 |
5 files changed, 72 insertions, 32 deletions
@@ -1,6 +1,6 @@ [package] name = "podcast" -version = "0.2.3" +version = "0.2.4" authors = ["njaremko <njaremko@gmail.com>"] description = "A command line podcast player" license = "GPL-3.0" diff --git a/src/actions.rs b/src/actions.rs index fb0d9e6..2f90205 100644 --- a/src/actions.rs +++ b/src/actions.rs @@ -2,7 +2,7 @@ use regex::Regex; use reqwest; use rss::Channel; use std::fs::{DirBuilder, File}; -use std::io::{self, Read, Write}; +use std::io::{self, BufReader, Read, Write}; use std::process::Command; use rayon::prelude::*; use structs::*; @@ -11,9 +11,9 @@ use utils::*; pub fn list_episodes(state: &State, search: &str) { let re = Regex::new(search).unwrap(); for podcast in state.subscriptions() { - if re.is_match(&podcast.name) { - println!("Episodes for {}:", &podcast.name); - match Podcast::from_url(&podcast.url) { + if re.is_match(&podcast.title()) { + println!("Episodes for {}:", &podcast.title()); + match Podcast::from_url(&podcast.url()) { Ok(podcast) => { let episodes = podcast.episodes(); for (index, episode) in episodes.iter().enumerate() { @@ -26,27 +26,43 @@ pub fn list_episodes(state: &State, search: &str) { } } +pub fn download_rss(url: &str) { + println!("Downloading RSS feed..."); + let mut path = get_podcast_dir(); + path.push(".rss"); + DirBuilder::new().recursive(true).create(&path).unwrap(); + let mut resp = reqwest::get(url).unwrap(); + let mut content: Vec<u8> = Vec::new(); + resp.read_to_end(&mut content).unwrap(); + let channel = Channel::read_from(BufReader::new(&content[..])).unwrap(); + let mut filename = String::from(channel.title()); + filename.push_str(".xml"); + path.push(filename); + let mut file = File::create(&path).unwrap(); + file.write_all(&content).unwrap(); +} + pub fn update_rss(state: &State) { println!("Updating RSS feeds..."); state.subscriptions().par_iter().for_each(|ref sub| { let mut path = get_podcast_dir(); path.push(".rss"); DirBuilder::new().recursive(true).create(&path).unwrap(); - let channel = Channel::from_url(&sub.url).unwrap(); + let mut resp = reqwest::get(&sub.url()).unwrap(); + let mut content: Vec<u8> = Vec::new(); + resp.read_to_end(&mut content).unwrap(); + let channel = Channel::read_from(BufReader::new(&content[..])).unwrap(); let mut filename = String::from(channel.title()); filename.push_str(".xml"); path.push(filename); let mut file = File::create(&path).unwrap(); - let mut resp = reqwest::get(&sub.url).unwrap(); - let mut content: Vec<u8> = Vec::new(); - resp.read_to_end(&mut content).unwrap(); file.write_all(&content).unwrap(); }); } pub fn list_subscriptions(state: &State) { for podcast in state.subscriptions() { - println!("{}", podcast.name); + println!("{}", podcast.title()); } } @@ -54,8 +70,8 @@ pub fn download_range(state: &State, p_search: &str, e_search: &str) { let re_pod = Regex::new(p_search).unwrap(); for subscription in state.subscriptions() { - if re_pod.is_match(&subscription.name) { - let podcast = Podcast::from_url(&subscription.url).unwrap(); + if re_pod.is_match(&subscription.title()) { + let podcast = Podcast::from_url(&subscription.url()).unwrap(); let episodes_to_download = parse_download_episodes(e_search); podcast.download_specific(episodes_to_download); } @@ -67,8 +83,8 @@ pub fn download_episode(state: &State, p_search: &str, e_search: &str) { let ep_num = e_search.parse::<usize>().unwrap(); for subscription in state.subscriptions() { - if re_pod.is_match(&subscription.name) { - let podcast = Podcast::from_url(&subscription.url).unwrap(); + if re_pod.is_match(&subscription.title()) { + let podcast = Podcast::from_url(&subscription.url()).unwrap(); let episodes = podcast.episodes(); if let Err(err) = episodes[episodes.len() - ep_num].download(podcast.title()) { println!("{}", err); @@ -81,8 +97,8 @@ pub fn download_all(state: &State, p_search: &str) { let re_pod = Regex::new(p_search).unwrap(); for subscription in state.subscriptions() { - if re_pod.is_match(&subscription.name) { - let podcast = Podcast::from_url(&subscription.url).unwrap(); + if re_pod.is_match(&subscription.title()) { + let podcast = Podcast::from_url(&subscription.url()).unwrap(); podcast.download(); } } @@ -102,8 +118,8 @@ pub fn play_episode(state: &State, p_search: &str, ep_num_string: &str) { return; } for subscription in state.subscriptions() { - if re_pod.is_match(&subscription.name) { - let mut filename = String::from(subscription.name); + if re_pod.is_match(&subscription.title()) { + let mut filename = String::from(subscription.title()); filename.push_str(".xml"); path.push(filename); diff --git a/src/main.rs b/src/main.rs index 6f23c6a..6d56a33 100644 --- a/src/main.rs +++ b/src/main.rs @@ -124,6 +124,6 @@ fn main() { _ => (), } if let Err(err) = state.save() { - eprintln!("{}", err); - } + eprintln!("{}", err); + } } diff --git a/src/structs.rs b/src/structs.rs index e0088be..07cb901 100644 --- a/src/structs.rs +++ b/src/structs.rs @@ -5,14 +5,24 @@ use reqwest; use rss::{self, Channel, Item}; use serde_json; use std::collections::BTreeSet; -use std::fs::{DirBuilder, File}; +use std::fs::{self, DirBuilder, File}; use std::io::{self, Read, Write}; use utils::*; #[derive(Serialize, Deserialize, Clone)] pub struct Subscription { - pub name: String, - pub url: String, + title: String, + url: String, +} + +impl Subscription { + pub fn title(&self) -> String { + self.title.clone() + } + + pub fn url(&self) -> String { + self.url.clone() + } } #[derive(Serialize, Deserialize, Clone)] @@ -50,20 +60,19 @@ impl State { pub fn subscribe(&mut self, url: &str) { let mut set = BTreeSet::new(); for sub in self.subscriptions() { - set.insert(sub.url); + set.insert(sub.title()); } - if !set.contains(url) { - let channel = Channel::from_url(url).unwrap(); + let channel = Channel::from_url(url).unwrap(); + if !set.contains(channel.title()) { self.subs.push(Subscription { - name: String::from(channel.title()), + title: String::from(channel.title()), url: String::from(url), }); } if let Err(err) = self.save() { eprintln!("{}", err); } - // TODO only download new rss, don't refresh all - update_rss(&self.clone()); + download_rss(url); } pub fn subscriptions(&self) -> Vec<Subscription> { @@ -71,14 +80,13 @@ impl State { } pub fn save(&self) -> Result<(), io::Error> { - // TODO write to a temp file and rename instead of overwriting - let mut path = get_podcast_dir(); DirBuilder::new().recursive(true).create(&path).unwrap(); - path.push(".subscriptions"); + 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())?; Ok(()) } } diff --git a/src/utils.rs b/src/utils.rs index 02c9983..5a6342b 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -46,6 +46,22 @@ pub fn get_podcast_dir() -> PathBuf { } } +pub fn get_sub_file() -> PathBuf { + match env::var_os("PODCAST") { + Some(val) => { + let mut path = PathBuf::from(val); + path.push(".subscriptions"); + path + } + None => { + let mut path = env::home_dir().unwrap(); + path.push("Podcasts"); + path.push(".subscriptions"); + path + } + } +} + pub fn parse_download_episodes(e_search: &str) -> Vec<usize> { let input = String::from(e_search); let mut ranges = Vec::<(usize, usize)>::new(); |
