librespot_metadata/
episode.rs

1use std::{
2    fmt::Debug,
3    ops::{Deref, DerefMut},
4};
5
6use crate::{
7    audio::file::AudioFiles,
8    availability::Availabilities,
9    content_rating::ContentRatings,
10    image::Images,
11    request::RequestResult,
12    restriction::Restrictions,
13    util::{impl_deref_wrapped, impl_try_from_repeated},
14    video::VideoFiles,
15    Metadata,
16};
17
18use librespot_core::{date::Date, Error, Session, SpotifyId};
19
20use librespot_protocol as protocol;
21pub use protocol::metadata::episode::EpisodeType;
22
23#[derive(Debug, Clone)]
24pub struct Episode {
25    pub id: SpotifyId,
26    pub name: String,
27    pub duration: i32,
28    pub audio: AudioFiles,
29    pub description: String,
30    pub number: i32,
31    pub publish_time: Date,
32    pub covers: Images,
33    pub language: String,
34    pub is_explicit: bool,
35    pub show_name: String,
36    pub videos: VideoFiles,
37    pub video_previews: VideoFiles,
38    pub audio_previews: AudioFiles,
39    pub restrictions: Restrictions,
40    pub freeze_frames: Images,
41    pub keywords: Vec<String>,
42    pub allow_background_playback: bool,
43    pub availability: Availabilities,
44    pub external_url: String,
45    pub episode_type: EpisodeType,
46    pub has_music_and_talk: bool,
47    pub content_rating: ContentRatings,
48    pub is_audiobook_chapter: bool,
49}
50
51#[derive(Debug, Clone, Default)]
52pub struct Episodes(pub Vec<SpotifyId>);
53
54impl_deref_wrapped!(Episodes, Vec<SpotifyId>);
55
56#[async_trait]
57impl Metadata for Episode {
58    type Message = protocol::metadata::Episode;
59
60    async fn request(session: &Session, episode_id: &SpotifyId) -> RequestResult {
61        session.spclient().get_episode_metadata(episode_id).await
62    }
63
64    fn parse(msg: &Self::Message, _: &SpotifyId) -> Result<Self, Error> {
65        Self::try_from(msg)
66    }
67}
68
69impl TryFrom<&<Self as Metadata>::Message> for Episode {
70    type Error = librespot_core::Error;
71    fn try_from(episode: &<Self as Metadata>::Message) -> Result<Self, Self::Error> {
72        Ok(Self {
73            id: episode.try_into()?,
74            name: episode.name().to_owned(),
75            duration: episode.duration().to_owned(),
76            audio: episode.audio.as_slice().into(),
77            description: episode.description().to_owned(),
78            number: episode.number(),
79            publish_time: episode.publish_time.get_or_default().try_into()?,
80            covers: episode.cover_image.image.as_slice().into(),
81            language: episode.language().to_owned(),
82            is_explicit: episode.explicit().to_owned(),
83            show_name: episode.show.name().to_owned(),
84            videos: episode.video.as_slice().into(),
85            video_previews: episode.video_preview.as_slice().into(),
86            audio_previews: episode.audio_preview.as_slice().into(),
87            restrictions: episode.restriction.as_slice().into(),
88            freeze_frames: episode.freeze_frame.image.as_slice().into(),
89            keywords: episode.keyword.to_vec(),
90            allow_background_playback: episode.allow_background_playback(),
91            availability: episode.availability.as_slice().try_into()?,
92            external_url: episode.external_url().to_owned(),
93            episode_type: episode.type_(),
94            has_music_and_talk: episode.music_and_talk(),
95            content_rating: episode.content_rating.as_slice().into(),
96            is_audiobook_chapter: episode.is_audiobook_chapter(),
97        })
98    }
99}
100
101impl_try_from_repeated!(<Episode as Metadata>::Message, Episodes);