aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorNathan2017-07-23 12:01:23 -0400
committerNathan2017-07-23 12:01:23 -0400
commitd1c2572a0cb2882b2661dafac0631e5888144dce (patch)
tree8604681935932062cd97b8b1672d694dafc80cc1 /src
parentefb6ef328ca159bf4d3b5f1b02d13e1c0aef0764 (diff)
downloadpodcast-d1c2572a0cb2882b2661dafac0631e5888144dce.tar.bz2
Improve RSS downloading
Diffstat (limited to 'src')
-rw-r--r--src/actions.rs50
-rw-r--r--src/main.rs4
-rw-r--r--src/structs.rs32
-rw-r--r--src/utils.rs16
4 files changed, 71 insertions, 31 deletions
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();