spotify_rs/endpoint/
audiobook.rs

1use serde::Serialize;
2
3use crate::{
4    auth::{AuthFlow, Authorised},
5    error::Result,
6    model::{
7        audiobook::{
8            Audiobook, Audiobooks, Chapter, Chapters, SimplifiedAudiobook, SimplifiedChapter,
9        },
10        Page,
11    },
12    query_list, Nil,
13};
14
15use super::{Client, Endpoint};
16
17impl Endpoint for AudiobookEndpoint {}
18impl Endpoint for AudiobooksEndpoint {}
19impl Endpoint for AudiobookChaptersEndpoint {}
20impl Endpoint for SavedAudiobooksEndpoint {}
21impl Endpoint for ChapterEndpoint {}
22impl Endpoint for ChaptersEndpoint {}
23
24#[doc = include_str!("../docs/client_creds_error.md")]
25pub fn audiobook(id: impl Into<String>) -> AudiobookEndpoint {
26    AudiobookEndpoint {
27        id: id.into(),
28        market: None,
29    }
30}
31
32#[doc = include_str!("../docs/client_creds_error.md")]
33pub fn audiobooks<T: AsRef<str>>(ids: &[T]) -> AudiobooksEndpoint {
34    AudiobooksEndpoint {
35        ids: query_list(ids),
36        market: None,
37    }
38}
39
40#[doc = include_str!("../docs/client_creds_error.md")]
41pub fn audiobook_chapters(audiobook_id: impl Into<String>) -> AudiobookChaptersEndpoint {
42    AudiobookChaptersEndpoint {
43        id: audiobook_id.into(),
44        ..Default::default()
45    }
46}
47
48pub fn saved_audiobooks() -> SavedAudiobooksEndpoint {
49    SavedAudiobooksEndpoint::default()
50}
51
52pub async fn save_audiobooks<T: AsRef<str>>(
53    ids: &[T],
54    spotify: &Client<impl AuthFlow + Authorised>,
55) -> Result<Nil> {
56    spotify
57        .put::<(), _>(format!("/me/audiobooks?ids={}", query_list(ids)), None)
58        .await
59}
60
61pub async fn remove_saved_audiobooks<T: AsRef<str>>(
62    ids: &[T],
63    spotify: &Client<impl AuthFlow + Authorised>,
64) -> Result<Nil> {
65    spotify
66        .delete::<(), _>(format!("/me/audiobooks?ids={}", query_list(ids)), None)
67        .await
68}
69
70pub async fn check_saved_audiobooks<T: AsRef<str>>(
71    ids: &[T],
72    spotify: &Client<impl AuthFlow + Authorised>,
73) -> Result<Vec<bool>> {
74    spotify
75        .get(
76            "/me/audiobooks/contains".to_owned(),
77            [("ids", query_list(ids))],
78        )
79        .await
80}
81
82#[doc = include_str!("../docs/client_creds_error.md")]
83pub fn chapter(id: impl Into<String>) -> ChapterEndpoint {
84    ChapterEndpoint {
85        id: id.into(),
86        market: None,
87    }
88}
89
90#[doc = include_str!("../docs/client_creds_error.md")]
91pub fn chapters<T: AsRef<str>>(ids: &[T]) -> ChaptersEndpoint {
92    ChaptersEndpoint {
93        ids: query_list(ids),
94        market: None,
95    }
96}
97
98#[derive(Clone, Debug, Default, Serialize)]
99pub struct AudiobookEndpoint {
100    #[serde(skip)]
101    pub(crate) id: String,
102    pub(crate) market: Option<String>,
103}
104
105impl AudiobookEndpoint {
106    #[doc = include_str!("../docs/market.md")]
107    pub fn market(mut self, market: impl Into<String>) -> Self {
108        self.market = Some(market.into());
109        self
110    }
111
112    #[doc = include_str!("../docs/send.md")]
113    pub async fn get(self, spotify: &Client<impl AuthFlow>) -> Result<Audiobook> {
114        spotify.get(format!("/audiobooks/{}", self.id), self).await
115    }
116}
117
118#[derive(Clone, Debug, Default, Serialize)]
119pub struct AudiobooksEndpoint {
120    pub(crate) ids: String,
121    pub(crate) market: Option<String>,
122}
123
124impl AudiobooksEndpoint {
125    #[doc = include_str!("../docs/market.md")]
126    pub fn market(mut self, market: impl Into<String>) -> Self {
127        self.market = Some(market.into());
128        self
129    }
130
131    #[doc = include_str!("../docs/send.md")]
132    pub async fn get(self, spotify: &Client<impl AuthFlow>) -> Result<Vec<Option<Audiobook>>> {
133        spotify
134            .get("/audiobooks".to_owned(), self)
135            .await
136            .map(|a: Audiobooks| a.audiobooks)
137    }
138}
139
140#[derive(Clone, Debug, Default, Serialize)]
141pub struct AudiobookChaptersEndpoint {
142    #[serde(skip)]
143    pub(crate) id: String,
144    pub(crate) market: Option<String>,
145    pub(crate) limit: Option<u32>,
146    pub(crate) offset: Option<u32>,
147}
148
149impl AudiobookChaptersEndpoint {
150    #[doc = include_str!("../docs/market.md")]
151    pub fn market(mut self, market: impl Into<String>) -> Self {
152        self.market = Some(market.into());
153        self
154    }
155
156    #[doc = include_str!("../docs/limit.md")]
157    pub fn limit(mut self, limit: u32) -> Self {
158        self.limit = Some(limit);
159        self
160    }
161
162    #[doc = include_str!("../docs/offset.md")]
163    pub fn offset(mut self, offset: u32) -> Self {
164        self.offset = Some(offset);
165        self
166    }
167
168    #[doc = include_str!("../docs/send.md")]
169    pub async fn get(self, spotify: &Client<impl AuthFlow>) -> Result<Page<SimplifiedChapter>> {
170        spotify
171            .get(format!("/audiobooks/{}/chapters", self.id), self)
172            .await
173    }
174}
175
176#[derive(Clone, Debug, Default, Serialize)]
177pub struct SavedAudiobooksEndpoint {
178    pub(crate) limit: Option<u32>,
179    pub(crate) offset: Option<u32>,
180}
181
182impl SavedAudiobooksEndpoint {
183    #[doc = include_str!("../docs/limit.md")]
184    pub fn limit(mut self, limit: u32) -> Self {
185        self.limit = Some(limit);
186        self
187    }
188
189    #[doc = include_str!("../docs/offset.md")]
190    pub fn offset(mut self, offset: u32) -> Self {
191        self.offset = Some(offset);
192        self
193    }
194
195    #[doc = include_str!("../docs/send.md")]
196    pub async fn get(
197        self,
198        spotify: &Client<impl AuthFlow + Authorised>,
199    ) -> Result<Page<SimplifiedAudiobook>> {
200        // The map is required because the page's items might contain null (for some reason),
201        // so this filters out the nulls.
202        spotify.get("/me/audiobooks".to_owned(), self).await.map(
203            |p: Page<Option<SimplifiedAudiobook>>| Page {
204                href: p.href,
205                limit: p.limit,
206                next: p.next,
207                offset: p.offset,
208                previous: p.previous,
209                total: p.total,
210                items: p.items.into_iter().flatten().collect(),
211            },
212        )
213    }
214}
215
216#[derive(Clone, Debug, Default, Serialize)]
217pub struct ChapterEndpoint {
218    #[serde(skip)]
219    pub(crate) id: String,
220    pub(crate) market: Option<String>,
221}
222
223impl ChapterEndpoint {
224    #[doc = include_str!("../docs/market.md")]
225    pub fn market(mut self, market: impl Into<String>) -> Self {
226        self.market = Some(market.into());
227        self
228    }
229
230    #[doc = include_str!("../docs/send.md")]
231    pub async fn get(self, spotify: &Client<impl AuthFlow>) -> Result<Chapter> {
232        spotify.get(format!("/chapters/{}", self.id), self).await
233    }
234}
235
236#[derive(Clone, Debug, Default, Serialize)]
237pub struct ChaptersEndpoint {
238    pub(crate) ids: String,
239    pub(crate) market: Option<String>,
240}
241
242impl ChaptersEndpoint {
243    #[doc = include_str!("../docs/market.md")]
244    pub fn market(mut self, market: impl Into<String>) -> Self {
245        self.market = Some(market.into());
246        self
247    }
248
249    #[doc = include_str!("../docs/send.md")]
250    pub async fn get(self, spotify: &Client<impl AuthFlow>) -> Result<Vec<Option<Chapter>>> {
251        spotify
252            .get("/chapters/".to_owned(), self)
253            .await
254            .map(|c: Chapters| c.chapters)
255    }
256}