diff --git a/codegen/Cargo.toml b/codegen/Cargo.toml index f314152..d9e8f18 100644 --- a/codegen/Cargo.toml +++ b/codegen/Cargo.toml @@ -2,6 +2,7 @@ name = "codegen" version = "0.1.0" edition = "2021" +publish = false [dependencies] reqwest = "0.11.11" diff --git a/src/error.rs b/src/error.rs index 2f076a7..1cd27cf 100644 --- a/src/error.rs +++ b/src/error.rs @@ -12,6 +12,12 @@ pub enum Error { /// Website parsing error #[error("website parsing error: {0}")] WebsiteParsing(Cow<'static, str>), + /// Item not found on Bandcamp + #[error("{0}")] + NotFound(Cow<'static, str>), + /// Other error from Bandcamp + #[error("{0}")] + Bandcamp(Cow<'static, str>), #[error("invalid bandcamp url")] InvalidUrl, #[error("invalid album uid")] diff --git a/src/models.rs b/src/models.rs index 1e0ed49..832fdca 100644 --- a/src/models.rs +++ b/src/models.rs @@ -64,6 +64,13 @@ pub struct Track { pub band_name: Option, /// Duration in seconds pub duration: f32, + /// Map of audio formats and URLs. + /// + /// 128kbit/s MP3 is currently the only publicly available format. + /// + /// **Example:** + /// + /// `mp3-128` => `https://bandcamp.com/stream_redirect?enc=mp3-128&track_id=4173325157&ts=1686871135&t=a1f7904205e6caca970009ca6744ef0b512f353a` pub streaming_url: BTreeMap, pub track_num: u16, } diff --git a/src/requests.rs b/src/requests.rs index f593a71..58ac17c 100644 --- a/src/requests.rs +++ b/src/requests.rs @@ -38,6 +38,28 @@ struct SearchResultWrapper { auto: SearchResult, } +#[derive(Deserialize)] +#[serde(untagged)] +enum ResponseWrapper { + Ok(T), + Error { error_message: String }, +} + +impl ResponseWrapper { + fn convert(self) -> Result { + match self { + ResponseWrapper::Ok(data) => Ok(data), + ResponseWrapper::Error { error_message } => { + if error_message.starts_with("No such ") || error_message.ends_with(" not found") { + Err(Error::NotFound(error_message.into())) + } else { + Err(Error::Bandcamp(error_message.into())) + } + } + } + } +} + impl Bandcamp { pub async fn band(&self, band_id: u64) -> Result { let req = BandRequest { band_id }; @@ -50,9 +72,15 @@ impl Bandcamp { .await? .error_for_status()?; - Ok(resp.json().await?) + resp.json::>().await?.convert() } + /// Get a album (or a track) from the Bandcamp API + /// + /// # Parameters + /// - `band_id` The Band ID of the album/track + /// - `tralbum_id` Album/Track ID + /// - `tralbum_type` Track/Album pub async fn album( &self, band_id: u64, @@ -73,7 +101,7 @@ impl Bandcamp { .await? .error_for_status()?; - Ok(resp.json().await?) + resp.json::>().await?.convert() } pub async fn album_uid>(&self, uid: S) -> Result { @@ -103,7 +131,11 @@ impl Bandcamp { .await? .error_for_status()?; - Ok(resp.json::().await?.auto) + Ok(resp + .json::>() + .await? + .convert()? + .auto) } pub async fn feed(&self) -> Result { @@ -117,7 +149,7 @@ impl Bandcamp { .await? .error_for_status()?; - Ok(resp.json().await?) + resp.json::>().await?.convert() } pub async fn feed_cont>(&self, token: S) -> Result { @@ -134,7 +166,7 @@ impl Bandcamp { .await? .error_for_status()?; - Ok(resp.json().await?) + resp.json::>().await?.convert() } pub async fn band_id_from_url(&self, url: U) -> Result { diff --git a/tests/snapshots/tests__album_track.snap b/tests/snapshots/tests__album_track.snap new file mode 100644 index 0000000..6596342 --- /dev/null +++ b/tests/snapshots/tests__album_track.snap @@ -0,0 +1,44 @@ +--- +source: tests/tests.rs +assertion_line: 69 +expression: "&album" +--- +Album( + id: 716010980, + title: "All Was Well", + art_id: Some(2367528067), + type: t, + tralbum_artist: "Wintergatan", + band: BandInfo( + band_id: 2464198920, + name: "Wintergatan", + bio: "", + image_id: Some(1354613), + location: "Gothenburg, Sweden", + ), + bandcamp_url: "https://wintergatan.bandcamp.com/track/all-was-well", + credits: None, + about: None, + featured_track_id: 716010980, + release_date: 1366761600, + tags: [ + Tag( + name: "Pop", + norm_name: "pop", + isloc: false, + ), + ], + tracks: [ + Track( + track_id: 716010980, + title: "All Was Well", + album_id: 2572654767, + album_title: None, + band_id: 2464198920, + band_name: Some("Wintergatan"), + duration: 183.224, + streaming_url: "[streaming_url]", + track_num: 8, + ), + ], +) diff --git a/tests/tests.rs b/tests/tests.rs index 8f35ec3..9bf1fbb 100644 --- a/tests/tests.rs +++ b/tests/tests.rs @@ -58,6 +58,21 @@ async fn album2() { check_image(&album.img_url().unwrap()).await; } +#[tokio::test] +async fn album_track() { + let bc = Bandcamp::new(); + let album = bc + .album_uid(format!("{}t{}", BAND_WINTERGATAN, 716010980)) + .await + .unwrap(); + + insta::assert_ron_snapshot!(&album, { + ".tracks[].streaming_url" => "[streaming_url]" + }); + check_stream_urls(&album.tracks); + check_image(&album.img_url().unwrap()).await; +} + #[tokio::test] async fn search() { let bc = Bandcamp::new();