Skip to main content

opensubsonic/api/
podcast.rs

1//! Podcast API endpoints.
2
3use crate::Client;
4use crate::data::{PodcastChannel, PodcastEpisode};
5use crate::error::Error;
6
7impl Client {
8    /// Get all podcast channels.
9    ///
10    /// If `include_episodes` is `false`, episodes are not included in the response.
11    ///
12    /// See <https://opensubsonic.netlify.app/docs/endpoints/getpodcasts/>
13    pub async fn get_podcasts(
14        &self,
15        include_episodes: Option<bool>,
16        id: Option<&str>,
17    ) -> Result<Vec<PodcastChannel>, Error> {
18        let mut params = Vec::new();
19        if let Some(ie) = include_episodes {
20            params.push(("includeEpisodes", ie.to_string()));
21        }
22        if let Some(id_val) = id {
23            params.push(("id", id_val.to_string()));
24        }
25        let param_refs: Vec<(&str, &str)> = params.iter().map(|(k, v)| (*k, v.as_str())).collect();
26        let data = self.get_response("getPodcasts", &param_refs).await?;
27        let channels = data
28            .get("podcasts")
29            .and_then(|v| v.get("channel"))
30            .cloned()
31            .unwrap_or_else(|| serde_json::Value::Array(vec![]));
32        Ok(serde_json::from_value(channels)?)
33    }
34
35    /// Get the newest podcast episodes.
36    ///
37    /// See <https://opensubsonic.netlify.app/docs/endpoints/getnewestpodcasts/>
38    pub async fn get_newest_podcasts(
39        &self,
40        count: Option<i32>,
41    ) -> Result<Vec<PodcastEpisode>, Error> {
42        let mut params = Vec::new();
43        if let Some(c) = count {
44            params.push(("count", c.to_string()));
45        }
46        let param_refs: Vec<(&str, &str)> = params.iter().map(|(k, v)| (*k, v.as_str())).collect();
47        let data = self.get_response("getNewestPodcasts", &param_refs).await?;
48        let episodes = data
49            .get("newestPodcasts")
50            .and_then(|v| v.get("episode"))
51            .cloned()
52            .unwrap_or_else(|| serde_json::Value::Array(vec![]));
53        Ok(serde_json::from_value(episodes)?)
54    }
55
56    /// Get a specific podcast episode (OpenSubsonic extension).
57    ///
58    /// See <https://opensubsonic.netlify.app/docs/endpoints/getpodcastepisode/>
59    pub async fn get_podcast_episode(&self, id: &str) -> Result<PodcastEpisode, Error> {
60        let data = self
61            .get_response("getPodcastEpisode", &[("id", id)])
62            .await?;
63        let episode = data
64            .get("podcastEpisode")
65            .ok_or_else(|| Error::Parse("Missing 'podcastEpisode' in response".into()))?;
66        Ok(serde_json::from_value(episode.clone())?)
67    }
68
69    /// Tell the server to check for new podcast episodes.
70    ///
71    /// See <https://opensubsonic.netlify.app/docs/endpoints/refreshpodcasts/>
72    pub async fn refresh_podcasts(&self) -> Result<(), Error> {
73        self.get_response("refreshPodcasts", &[]).await?;
74        Ok(())
75    }
76
77    /// Add a new podcast channel (by feed URL).
78    ///
79    /// See <https://opensubsonic.netlify.app/docs/endpoints/createpodcastchannel/>
80    pub async fn create_podcast_channel(&self, url: &str) -> Result<(), Error> {
81        self.get_response("createPodcastChannel", &[("url", url)])
82            .await?;
83        Ok(())
84    }
85
86    /// Delete a podcast channel.
87    ///
88    /// See <https://opensubsonic.netlify.app/docs/endpoints/deletepodcastchannel/>
89    pub async fn delete_podcast_channel(&self, id: &str) -> Result<(), Error> {
90        self.get_response("deletePodcastChannel", &[("id", id)])
91            .await?;
92        Ok(())
93    }
94
95    /// Delete a podcast episode.
96    ///
97    /// See <https://opensubsonic.netlify.app/docs/endpoints/deletepodcastepisode/>
98    pub async fn delete_podcast_episode(&self, id: &str) -> Result<(), Error> {
99        self.get_response("deletePodcastEpisode", &[("id", id)])
100            .await?;
101        Ok(())
102    }
103
104    /// Tell the server to download a podcast episode.
105    ///
106    /// See <https://opensubsonic.netlify.app/docs/endpoints/downloadpodcastepisode/>
107    pub async fn download_podcast_episode(&self, id: &str) -> Result<(), Error> {
108        self.get_response("downloadPodcastEpisode", &[("id", id)])
109            .await?;
110        Ok(())
111    }
112}