diff --git a/Cargo.toml b/Cargo.toml index 729158d..c680416 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "podcast" edition = "2018" -version = "0.15.0" +version = "0.16.0" authors = ["Nathan Jaremko "] description = "A command line podcast manager" license = "GPL-3.0" @@ -36,4 +36,5 @@ serde_yaml = "0.8" toml = "0.5" percent-encoding = "2.1" semver-parser = "0.9.0" -tokio = { version = "0.2", features = ["full"]} \ No newline at end of file +tokio = { version = "0.2", features = ["full"]} +podcast_search = "0.1" \ No newline at end of file diff --git a/src/arg_parser.rs b/src/arg_parser.rs index 1b5e3f4..9e3d3a4 100644 --- a/src/arg_parser.rs +++ b/src/arg_parser.rs @@ -9,7 +9,6 @@ use crate::actions::*; use crate::download; use crate::errors::*; use crate::playback; -use crate::search; use crate::structs::*; pub async fn download(state: &mut State, matches: &ArgMatches<'_>) -> Result<()> { @@ -112,7 +111,7 @@ pub fn complete(app: &mut App, matches: &ArgMatches) -> Result<()> { pub async fn search(state: &mut State, config: Config, matches: &ArgMatches<'_>) -> Result<()> { let matches = matches.subcommand_matches("search").unwrap(); let podcast = matches.value_of("PODCAST").unwrap(); - let resp = search::search_for_podcast(podcast).await?; + let resp = podcast_search::search(podcast).await?; if resp.results.is_empty() { println!("No Results"); return Ok(()); @@ -122,7 +121,13 @@ pub async fn search(state: &mut State, config: Config, matches: &ArgMatches<'_>) let stdout = io::stdout(); let mut lock = stdout.lock(); for (i, r) in resp.results.iter().enumerate() { - writeln!(&mut lock, "({}) {}", i, r.collection_name.clone().unwrap_or_else(|| "".to_string()))?; + writeln!( + &mut lock, + "({}) {} [{}]", + i, + r.collection_name.clone().unwrap_or_else(|| "".to_string()), + r.feed_url.clone().unwrap_or_else(|| "".to_string()) + )?; } } diff --git a/src/main.rs b/src/main.rs index 0e76f0c..2e1c8ac 100644 --- a/src/main.rs +++ b/src/main.rs @@ -25,7 +25,6 @@ mod download; mod migration_handler; mod parser; mod playback; -mod search; mod structs; mod utils; @@ -39,7 +38,7 @@ use self::structs::*; use errors::Result; use std::io::Write; -const VERSION: &str = "0.15.0"; +const VERSION: &str = "0.16.0"; #[tokio::main] async fn main() -> Result<()> { diff --git a/src/search.rs b/src/search.rs deleted file mode 100644 index 5d3587a..0000000 --- a/src/search.rs +++ /dev/null @@ -1,202 +0,0 @@ -use failure::Error; -use percent_encoding::{utf8_percent_encode, NON_ALPHANUMERIC}; -use reqwest; - -#[derive(Debug, Serialize, Deserialize)] -pub struct ArtistSearchResponse { - #[serde(rename = "resultCount")] - pub result_count: usize, - pub results: Vec, -} - -#[derive(Debug, Serialize, Deserialize)] -pub struct ArtistSearchResult { - #[serde(rename = "wrapperType")] - pub wrapper_type: Option, - #[serde(rename = "artistType")] - pub artist_type: Option, - #[serde(rename = "artistName")] - pub artist_name: Option, - #[serde(rename = "artistLinkUrl")] - pub artist_link_url: Option, - #[serde(rename = "artistId")] - pub artist_id: Option, - #[serde(rename = "primaryGenreName")] - pub primary_genre_name: Option, - #[serde(rename = "primaryGenreId")] - pub primary_genre_id: Option, -} - - - -#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] -pub struct PodcastSearchResult { - #[serde(rename = "wrapperType")] - wrapper_type: Option, - kind: Option, - #[serde(rename = "artistId")] - artist_id: Option, - #[serde(rename = "collectionId")] - collection_id: Option, - #[serde(rename = "trackId")] - track_id: Option, - #[serde(rename = "artistName")] - artist_name: Option, - #[serde(rename = "collectionName")] - pub collection_name: Option, - #[serde(rename = "trackName")] - track_name: Option, - #[serde(rename = "collectionCensoredName")] - collection_censored_name: Option, - #[serde(rename = "trackCensoredName")] - track_censored_name: Option, - #[serde(rename = "artistViewUrl")] - artist_view_url: Option, - #[serde(rename = "collectionViewUrl")] - collection_view_url: Option, - #[serde(rename = "feedUrl")] - pub feed_url: Option, - #[serde(rename = "trackViewUrl")] - track_view_url: Option, - #[serde(rename = "artworkUrl30")] - artwork_url30: Option, - #[serde(rename = "artworkUrl60")] - artwork_url60: Option, - #[serde(rename = "artworkUrl100")] - artwork_url100: Option, - #[serde(rename = "collectionPrice")] - collection_price: Option, - #[serde(rename = "trackPrice")] - track_price: Option, - #[serde(rename = "trackRentalPrice")] - track_rental_price: Option, - #[serde(rename = "collectionHdPrice")] - collection_hd_price: Option, - #[serde(rename = "trackHdPrice")] - track_hd_price: Option, - #[serde(rename = "trackHdRentalPrice")] - track_hd_rental_price: Option, - #[serde(rename = "releaseDate")] - release_date: Option, - #[serde(rename = "collectionExplicitness")] - collection_explicitness: Option, - #[serde(rename = "trackExplicitness")] - track_explicitness: Option, - #[serde(rename = "trackCount")] - track_count: Option, - country: Option, - currency: Option, - #[serde(rename = "primaryGenreName")] - primary_genre_name: Option, - #[serde(rename = "contentAdvisoryRating")] - content_advisory_rating: Option, - #[serde(rename = "artworkUrl600")] - artwork_url600: Option, - #[serde(rename = "genreIds")] - genre_ids: Option>, - genres: Option>, -} - -#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] -pub enum Explicitness { - #[serde(rename = "cleaned")] - Cleaned, - #[serde(rename = "explicit")] - Explicit, - #[serde(rename = "notExplicit")] - NotExplicit, -} - -#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] -pub enum ContentAdvisoryRating { - Clean, - Explicit, -} - -#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] -pub enum Country { - #[serde(rename = "USA")] - Usa, -} - -#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] -pub enum Currency { - #[serde(rename = "USD")] - Usd, -} - -#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] -pub enum Kind { - #[serde(rename = "podcast")] - Podcast, -} - -#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] -pub enum WrapperType { - #[serde(rename = "track")] - Track, -} - - - -#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] -pub struct TrackSearchResponse { - #[serde(rename = "resultCount")] - pub result_count: usize, - pub results: Vec -} - -impl TrackSearchResponse { - pub fn result_count(&self) -> usize { - self.result_count - } - - pub fn results(&self) -> &[PodcastSearchResult] { - &self.results - } -} - -#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] -pub struct RssResponse { - error: Option, - url: Option, -} - -impl RssResponse { - pub fn error(&self) -> &Option { - &self.error - } - - pub fn url(&self) -> &Option { - &self.url - } -} - -const BASE: &str = "https://itunes.apple.com/search?media=podcast&term="; - -pub async fn search_for_podcast(podcast: &str) -> Result { - let encoded: String = podcast.chars().map(|c| { - if c == ' ' { - return '+'; - } - return c; - }).collect(); - let url = format!("https://itunes.apple.com/search?media=podcast&entity=podcast&term={}", encoded); - let r = reqwest::get(&url).await?.json::().await?; - Ok(r) -} - -pub async fn search_for_episode(podcast: &str, ep: &str) -> Result { - let podcast_encoded = utf8_percent_encode(podcast, NON_ALPHANUMERIC).to_string(); - let ep_encoded = utf8_percent_encode(ep, NON_ALPHANUMERIC).to_string(); - let url = BASE.to_string() + "/query/" + &podcast_encoded + "/episode/" + &ep_encoded; - let r = reqwest::get(&url).await?.json::().await?; - Ok(r) -} - -pub async fn retrieve_rss(podcast: &str) -> Result { - let encoded = utf8_percent_encode(podcast, NON_ALPHANUMERIC).to_string(); - let url = format!("https://itunes.apple.com/lookup?id={}&entity=podcast", encoded); - let r = reqwest::get(&url).await?.json::().await?; - Ok(r) -} diff --git a/src/structs.rs b/src/structs.rs index c6ae668..283e4c6 100644 --- a/src/structs.rs +++ b/src/structs.rs @@ -251,4 +251,4 @@ impl Episode { _ => find_extension(self.url().unwrap()), } } -} \ No newline at end of file +}