use super::{Copyright, ExternalUrls, Image, ItemType, Market, Page, SimplifiedChapter};
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub struct Author {
pub name: String,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub struct Narrator {
pub name: String,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub struct Audiobook {
pub authors: Vec<Author>,
#[cfg(feature = "markets")]
#[serde(skip_serializing_if = "Vec::is_empty", default)]
pub available_markets: Vec<Market>,
pub copyrights: Vec<Copyright>,
pub description: String,
pub html_description: String,
pub edition: String,
pub explicit: bool,
pub external_urls: ExternalUrls,
pub href: String,
pub id: String,
pub images: Vec<Image>,
pub languages: Vec<String>,
pub media_type: String,
pub name: String,
pub narrators: Vec<Narrator>,
pub publisher: String,
#[serde(rename = "type")]
pub type_: ItemType,
pub uri: String,
pub total_chapters: usize,
#[cfg(feature = "page_items")]
pub chapters: Page<SimplifiedChapter>,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub struct SimplifiedAudiobook {
pub authors: Vec<Author>,
#[cfg(feature = "markets")]
#[serde(skip_serializing_if = "Vec::is_empty", default)]
pub available_markets: Vec<Market>,
pub copyrights: Vec<Copyright>,
pub description: String,
pub html_description: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub edition: Option<String>,
pub explicit: bool,
pub external_urls: ExternalUrls,
pub href: String,
pub id: String,
pub images: Vec<Image>,
pub languages: Vec<String>,
pub media_type: String,
pub name: String,
pub narrators: Vec<Narrator>,
pub publisher: String,
#[serde(rename = "type")]
pub type_: ItemType,
pub uri: String,
pub total_chapters: usize,
}
impl From<Audiobook> for SimplifiedAudiobook {
fn from(audiobook: Audiobook) -> Self {
Self {
authors: audiobook.authors,
#[cfg(feature = "markets")]
available_markets: audiobook.available_markets,
copyrights: audiobook.copyrights,
description: audiobook.description,
html_description: audiobook.html_description,
edition: Some(audiobook.edition),
explicit: audiobook.explicit,
external_urls: audiobook.external_urls,
href: audiobook.href,
id: audiobook.id,
images: audiobook.images,
languages: audiobook.languages,
media_type: audiobook.media_type,
name: audiobook.name,
narrators: audiobook.narrators,
publisher: audiobook.publisher,
type_: audiobook.type_,
uri: audiobook.uri,
total_chapters: audiobook.total_chapters,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub struct Audiobooks {
pub audiobooks: Vec<Option<Audiobook>>,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn audiobook() {
let json = r#"
{
"authors": [
{
"name": "string"
}
],
"available_markets": ["US"],
"copyrights": [
{
"text": "string",
"type": "C"
}
],
"description": "string",
"html_description": "string",
"edition": "Unabridged",
"explicit": false,
"external_urls": {
"spotify": "string"
},
"href": "string",
"id": "string",
"images": [
{
"url": "https://i.scdn.co/image/ab67616d00001e02ff9ca10b55ce82ae553c8228",
"height": 300,
"width": 300
}
],
"languages": ["string"],
"media_type": "string",
"name": "string",
"narrators": [
{
"name": "string"
}
],
"publisher": "string",
"type": "audiobook",
"uri": "string",
"total_chapters": 0,
"chapters": {
"href": "https://api.spotify.com/v1/me/shows?offset=0&limit=20",
"limit": 20,
"next": "https://api.spotify.com/v1/me/shows?offset=1&limit=1",
"offset": 0,
"previous": "https://api.spotify.com/v1/me/shows?offset=1&limit=1",
"total": 4,
"items": [
{
"audio_preview_url": "https://p.scdn.co/mp3-preview/2f37da1d4221f40b9d1a98cd191f4d6f1646ad17",
"available_markets": ["US"],
"chapter_number": 1,
"description": "We kept on ascending, with occasional periods of quick descent, but in the main always ascending. Suddenly, I became conscious of the fact that the driver was in the act of pulling up the horses in the courtyard of a vast ruined castle, from whose tall black windows came no ray of light, and whose broken battlements showed a jagged line against the moonlit sky.",
"html_description": "<p>We kept on ascending, with occasional periods of quick descent, but in the main always ascending. Suddenly, I became conscious of the fact that the driver was in the act of pulling up the horses in the courtyard of a vast ruined castle, from whose tall black windows came no ray of light, and whose broken battlements showed a jagged line against the moonlit sky.</p>",
"duration_ms": 1686230,
"explicit": false,
"external_urls": {
"spotify": "string"
},
"href": "https://api.spotify.com/v1/episodes/5Xt5DXGzch68nYYamXrNxZ",
"id": "5Xt5DXGzch68nYYamXrNxZ",
"images": [
{
"url": "https://i.scdn.co/image/ab67616d00001e02ff9ca10b55ce82ae553c8228",
"height": 300,
"width": 300
}
],
"is_playable": false,
"languages": ["fr", "en"],
"name": "Starting Your Own Podcast: Tips, Tricks, and Advice From Anchor Creators",
"release_date": "1981-12-15",
"release_date_precision": "day",
"resume_point": {
"fully_played": false,
"resume_position_ms": 0
},
"type": "episode",
"uri": "spotify:episode:0zLhl3WsOCQHbe1BPTiHgr",
"restrictions": {
"reason": "string"
}
}
]
}
}
"#;
crate::test::assert_deserialized!(Audiobook, json);
}
#[test]
fn simplified_audiobook() {
let json = r#"
{
"authors": [
{
"name": "string"
}
],
"available_markets": ["US"],
"copyrights": [
{
"text": "string",
"type": "C"
}
],
"description": "string",
"html_description": "string",
"edition": "Unabridged",
"explicit": false,
"external_urls": {
"spotify": "string"
},
"href": "string",
"id": "string",
"images": [
{
"url": "https://i.scdn.co/image/ab67616d00001e02ff9ca10b55ce82ae553c8228",
"height": 300,
"width": 300
}
],
"languages": ["string"],
"media_type": "string",
"name": "string",
"narrators": [
{
"name": "string"
}
],
"publisher": "string",
"type": "audiobook",
"uri": "string",
"total_chapters": 0
}
"#;
crate::test::assert_deserialized!(SimplifiedAudiobook, json);
}
}