librespot_metadata/
episode.rs1use std::{
2 fmt::Debug,
3 ops::{Deref, DerefMut},
4};
5
6use crate::{
7 Metadata,
8 audio::file::AudioFiles,
9 availability::Availabilities,
10 content_rating::ContentRatings,
11 image::Images,
12 request::RequestResult,
13 restriction::Restrictions,
14 util::{impl_deref_wrapped, impl_try_from_repeated},
15 video::VideoFiles,
16};
17
18use librespot_core::{Error, Session, SpotifyId, date::Date};
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);