1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143
#[macro_use] extern crate serde; use percent_encoding::{utf8_percent_encode, NON_ALPHANUMERIC}; use thiserror::Error; #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct SearchResponse { #[serde(rename = "resultCount")] pub result_count: usize, pub results: Vec<SearchResult>, } #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct SearchResult { #[serde(rename = "wrapperType")] pub wrapper_type: Option<WrapperType>, pub kind: Option<Kind>, #[serde(rename = "artistId")] pub artist_id: Option<usize>, #[serde(rename = "collectionId")] pub collection_id: Option<usize>, #[serde(rename = "trackId")] pub track_id: Option<usize>, #[serde(rename = "artistName")] pub artist_name: Option<String>, #[serde(rename = "collectionName")] pub collection_name: Option<String>, #[serde(rename = "trackName")] pub track_name: Option<String>, #[serde(rename = "collectionCensoredName")] pub collection_censored_name: Option<String>, #[serde(rename = "trackCensoredName")] pub track_censored_name: Option<String>, #[serde(rename = "artistViewUrl")] pub artist_view_url: Option<String>, #[serde(rename = "collectionViewUrl")] pub collection_view_url: Option<String>, #[serde(rename = "feedUrl")] pub feed_url: Option<String>, #[serde(rename = "trackViewUrl")] pub track_view_url: Option<String>, #[serde(rename = "artworkUrl30")] pub artwork_url30: Option<String>, #[serde(rename = "artworkUrl60")] pub artwork_url60: Option<String>, #[serde(rename = "artworkUrl100")] pub artwork_url100: Option<String>, #[serde(rename = "collectionPrice")] pub collection_price: Option<f64>, #[serde(rename = "trackPrice")] pub track_price: Option<f64>, #[serde(rename = "trackRentalPrice")] pub track_rental_price: Option<f64>, #[serde(rename = "collectionHdPrice")] pub collection_hd_price: Option<f64>, #[serde(rename = "trackHdPrice")] pub track_hd_price: Option<f64>, #[serde(rename = "trackHdRentalPrice")] pub track_hd_rental_price: Option<f64>, #[serde(rename = "releaseDate")] pub release_date: Option<String>, #[serde(rename = "collectionExplicitness")] pub collection_explicitness: Option<Explicitness>, #[serde(rename = "trackExplicitness")] pub track_explicitness: Option<Explicitness>, #[serde(rename = "trackCount")] pub track_count: Option<usize>, #[serde(with = "serde_with::rust::display_fromstr")] pub country: celes::Country, pub currency: Option<iso_currency::Currency>, #[serde(rename = "primaryGenreName")] pub primary_genre_name: Option<String>, #[serde(rename = "contentAdvisoryRating")] pub content_advisory_rating: Option<ContentAdvisoryRating>, #[serde(rename = "artworkUrl600")] pub artwork_url600: Option<String>, #[serde(rename = "genreIds")] pub genre_ids: Option<Vec<String>>, pub genres: Option<Vec<String>>, } #[derive(Copy, Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] pub enum Explicitness { #[serde(rename = "cleaned")] Cleaned, #[serde(rename = "explicit")] Explicit, #[serde(rename = "notExplicit")] NotExplicit, } #[derive(Copy, Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] pub enum ContentAdvisoryRating { Clean, Explicit, } #[derive(Copy, Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] pub enum Kind { #[serde(rename = "podcast")] Podcast, } #[derive(Copy, Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] pub enum WrapperType { #[serde(rename = "track")] Track, #[serde(rename = "collection")] Collection, #[serde(rename = "artist")] Artist, } #[derive(Error, Debug)] pub enum PodcastSearchError { #[error("Failed to fetch information for itunes API {source:?}")] FetchError{ #[from] source: reqwest::Error }, #[error("Failed to parse response from itunes API {source:?}")] ParseError { #[from] source: serde_json::Error }, #[error("An unknown error occurred!")] Unknown, } pub async fn search(terms: &str) -> Result<SearchResponse, PodcastSearchError> { let encoded: String = utf8_percent_encode(terms, NON_ALPHANUMERIC).to_string(); let url = format!("https://itunes.apple.com/search?media=podcast&entity=podcast&term={}", encoded); let resp = reqwest::get(&url).await?.json::<SearchResponse>().await?; Ok(resp) } #[cfg(test)] mod tests { #[test] fn it_works() { assert_eq!(2 + 2, 4); } }