aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorNathan2017-07-22 16:39:24 -0400
committerNathan2017-07-22 16:39:24 -0400
commit81324bf762067b1ed257e506c2ce88421387afd8 (patch)
treed8e4c02971df8a799b3bc615991d9969ac9cfd6e /src
parentc2a8ea951ad98baa7f1776cba6edf7127860cbb3 (diff)
downloadpodcast-81324bf762067b1ed257e506c2ce88421387afd8.tar.bz2
Release 0.2.0 - Now with async IO and download episode ranges
Diffstat (limited to 'src')
-rw-r--r--src/actions.rs48
-rw-r--r--src/main.rs23
-rw-r--r--src/structs.rs13
-rw-r--r--src/utils.rs2
4 files changed, 63 insertions, 23 deletions
diff --git a/src/actions.rs b/src/actions.rs
index d81aa8c..b87b2f1 100644
--- a/src/actions.rs
+++ b/src/actions.rs
@@ -4,6 +4,7 @@ use rss::Channel;
use std::fs::{DirBuilder, File};
use std::io::{self, Read, Write};
use std::process::Command;
+use rayon::prelude::*;
use structs::*;
use utils::*;
@@ -26,8 +27,7 @@ pub fn list_episodes(state: &State, search: &str) {
}
pub fn update_rss(state: &State) {
- let subs = state.subscriptions();
- for sub in subs {
+ state.subscriptions().par_iter().for_each(|ref sub| {
let mut path = get_podcast_dir();
path.push(".rss");
DirBuilder::new().recursive(true).create(&path).unwrap();
@@ -40,7 +40,7 @@ pub fn update_rss(state: &State) {
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) {
@@ -49,6 +49,28 @@ pub fn list_subscriptions(state: &State) {
}
}
+pub fn download_range(state: &State, p_search: &str, e_search: &str) {
+ let re_pod = Regex::new(p_search).unwrap();
+ let input = String::from(e_search);
+ let range: Vec<usize> = input
+ .split('-')
+ .map(|i| i.parse::<usize>().unwrap())
+ .collect();
+
+ for subscription in state.subscriptions() {
+ if re_pod.is_match(&subscription.name) {
+ let podcast = Podcast::from_url(&subscription.url).unwrap();
+ let episodes = podcast.episodes();
+
+ &episodes[episodes.len() - range[1]..episodes.len() - range[0]]
+ .par_iter()
+ .for_each(|ref ep| if let Err(err) = ep.download(podcast.title()) {
+ println!("{}", err);
+ });
+ }
+ }
+}
+
pub fn download_episode(state: &State, p_search: &str, e_search: &str) {
let re_pod = Regex::new(p_search).unwrap();
let ep_num = e_search.parse::<usize>().unwrap();
@@ -80,7 +102,14 @@ pub fn play_episode(state: &State, p_search: &str, ep_num_string: &str) {
let ep_num = ep_num_string.parse::<usize>().unwrap();
let mut path = get_podcast_dir();
path.push(".rss");
- DirBuilder::new().recursive(true).create(&path).unwrap();
+ if let Err(err) = DirBuilder::new().recursive(true).create(&path) {
+ eprintln!(
+ "Couldn't create directory: {}\nReason: {}",
+ path.to_str().unwrap(),
+ err
+ );
+ return;
+ }
for subscription in state.subscriptions() {
if re_pod.is_match(&subscription.name) {
let mut filename = String::from(subscription.name);
@@ -110,19 +139,22 @@ pub fn play_episode(state: &State, p_search: &str, ep_num_string: &str) {
}
}
-fn launch_player(url: &str) {
+fn launch_player(url: &str) {
if let Err(_) = launch_mpv(&url) {
launch_vlc(url)
}
}
fn launch_mpv(url: &str) -> Result<(), io::Error> {
- if let Err(err) = Command::new("mpv").args(&["--audio-display=no", "--ytdl=no", url]).status() {
+ if let Err(err) = Command::new("mpv")
+ .args(&["--audio-display=no", "--ytdl=no", url])
+ .status()
+ {
match err.kind() {
io::ErrorKind::NotFound => {
eprintln!("Couldn't open mpv\nTrying vlc...");
return Err(err);
- },
+ }
_ => eprintln!("Error: {}", err),
}
}
@@ -134,7 +166,7 @@ fn launch_vlc(url: &str) {
match err.kind() {
io::ErrorKind::NotFound => {
eprintln!("vlc not found in PATH\nAborting...");
- },
+ }
_ => eprintln!("Error: {}", err),
}
}
diff --git a/src/main.rs b/src/main.rs
index 0eab682..c408745 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,4 +1,5 @@
extern crate clap;
+extern crate rayon;
extern crate regex;
extern crate reqwest;
extern crate rss;
@@ -61,11 +62,9 @@ fn main() {
.subcommand(
SubCommand::with_name("search")
.about("searches for podcasts")
- .arg(
- Arg::with_name("debug")
- .short("d")
- .help("print debug information verbosely"),
- ),
+ .arg(Arg::with_name("debug").short("d").help(
+ "print debug information verbosely",
+ )),
)
.subcommand(
SubCommand::with_name("subscribe")
@@ -77,9 +76,9 @@ fn main() {
.index(1),
),
)
- .subcommand(
- SubCommand::with_name("update").about("update subscribed podcasts"),
- )
+ .subcommand(SubCommand::with_name("update").about(
+ "update subscribed podcasts",
+ ))
.get_matches();
match matches.subcommand_name() {
@@ -87,7 +86,13 @@ fn main() {
let download_matches = matches.subcommand_matches("download").unwrap();
let podcast = download_matches.value_of("PODCAST").unwrap();
match download_matches.value_of("EPISODE") {
- Some(ep) => download_episode(&state, podcast, ep),
+ Some(ep) => {
+ if String::from(ep).contains("-") {
+ download_range(&state, podcast, ep)
+ } else {
+ download_episode(&state, podcast, ep)
+ }
+ }
None => download_all(&state, podcast),
}
}
diff --git a/src/structs.rs b/src/structs.rs
index a94c96e..7087077 100644
--- a/src/structs.rs
+++ b/src/structs.rs
@@ -1,4 +1,5 @@
use actions::*;
+use rayon::prelude::*;
use reqwest;
use rss::{self, Channel, Item};
use serde_json;
@@ -113,15 +114,17 @@ impl Podcast {
let downloaded = already_downloaded(self.title());
- for ep in self.episodes() {
- if let Some(ep_title) = ep.title() {
+ self.episodes().par_iter().for_each(
+ |ref i| if let Some(ep_title) =
+ i.title()
+ {
if !downloaded.contains(ep_title) {
- if let Err(err) = ep.download(self.title()) {
+ if let Err(err) = i.download(self.title()) {
println!("{}", err);
}
}
- }
- }
+ },
+ );
}
}
diff --git a/src/utils.rs b/src/utils.rs
index e602932..b2c590a 100644
--- a/src/utils.rs
+++ b/src/utils.rs
@@ -28,7 +28,7 @@ pub fn already_downloaded(dir: &str) -> BTreeSet<String> {
}
pub fn get_podcast_dir() -> PathBuf {
- match env::var_os("PODCAST") {
+ match env::var_os("PODCAST") {
Some(val) => PathBuf::from(val),
None => {
let mut path = env::home_dir().unwrap();