librespot_metadata/
album.rs

1use std::{
2    fmt::Debug,
3    ops::{Deref, DerefMut},
4};
5
6use crate::{
7    artist::Artists,
8    availability::Availabilities,
9    copyright::Copyrights,
10    external_id::ExternalIds,
11    image::Images,
12    request::RequestResult,
13    restriction::Restrictions,
14    sale_period::SalePeriods,
15    track::Tracks,
16    util::{impl_deref_wrapped, impl_try_from_repeated},
17    Metadata,
18};
19
20use librespot_core::{date::Date, Error, Session, SpotifyId};
21
22use librespot_protocol as protocol;
23pub use protocol::metadata::album::Type as AlbumType;
24use protocol::metadata::Disc as DiscMessage;
25
26#[derive(Debug, Clone)]
27pub struct Album {
28    pub id: SpotifyId,
29    pub name: String,
30    pub artists: Artists,
31    pub album_type: AlbumType,
32    pub label: String,
33    pub date: Date,
34    pub popularity: i32,
35    pub genres: Vec<String>,
36    pub covers: Images,
37    pub external_ids: ExternalIds,
38    pub discs: Discs,
39    pub reviews: Vec<String>,
40    pub copyrights: Copyrights,
41    pub restrictions: Restrictions,
42    pub related: Albums,
43    pub sale_periods: SalePeriods,
44    pub cover_group: Images,
45    pub original_title: String,
46    pub version_title: String,
47    pub type_str: String,
48    pub availability: Availabilities,
49}
50
51#[derive(Debug, Clone, Default)]
52pub struct Albums(pub Vec<SpotifyId>);
53
54impl_deref_wrapped!(Albums, Vec<SpotifyId>);
55
56#[derive(Debug, Clone)]
57pub struct Disc {
58    pub number: i32,
59    pub name: String,
60    pub tracks: Tracks,
61}
62
63#[derive(Debug, Clone, Default)]
64pub struct Discs(pub Vec<Disc>);
65
66impl_deref_wrapped!(Discs, Vec<Disc>);
67
68impl Album {
69    pub fn tracks(&self) -> impl Iterator<Item = &SpotifyId> {
70        self.discs.iter().flat_map(|disc| disc.tracks.iter())
71    }
72}
73
74#[async_trait]
75impl Metadata for Album {
76    type Message = protocol::metadata::Album;
77
78    async fn request(session: &Session, album_id: &SpotifyId) -> RequestResult {
79        session.spclient().get_album_metadata(album_id).await
80    }
81
82    fn parse(msg: &Self::Message, _: &SpotifyId) -> Result<Self, Error> {
83        Self::try_from(msg)
84    }
85}
86
87impl TryFrom<&<Self as Metadata>::Message> for Album {
88    type Error = librespot_core::Error;
89    fn try_from(album: &<Self as Metadata>::Message) -> Result<Self, Self::Error> {
90        Ok(Self {
91            id: album.try_into()?,
92            name: album.name().to_owned(),
93            artists: album.artist.as_slice().try_into()?,
94            album_type: album.type_(),
95            label: album.label().to_owned(),
96            date: album.date.get_or_default().try_into()?,
97            popularity: album.popularity(),
98            genres: album.genre.to_vec(),
99            covers: album.cover_group.get_or_default().into(),
100            external_ids: album.external_id.as_slice().into(),
101            discs: album.disc.as_slice().try_into()?,
102            reviews: album.review.to_vec(),
103            copyrights: album.copyright.as_slice().into(),
104            restrictions: album.restriction.as_slice().into(),
105            related: album.related.as_slice().try_into()?,
106            sale_periods: album.sale_period.as_slice().try_into()?,
107            cover_group: album.cover_group.image.as_slice().into(),
108            original_title: album.original_title().to_owned(),
109            version_title: album.version_title().to_owned(),
110            type_str: album.type_str().to_owned(),
111            availability: album.availability.as_slice().try_into()?,
112        })
113    }
114}
115
116impl_try_from_repeated!(<Album as Metadata>::Message, Albums);
117
118impl TryFrom<&DiscMessage> for Disc {
119    type Error = librespot_core::Error;
120    fn try_from(disc: &DiscMessage) -> Result<Self, Self::Error> {
121        Ok(Self {
122            number: disc.number(),
123            name: disc.name().to_owned(),
124            tracks: disc.track.as_slice().try_into()?,
125        })
126    }
127}
128
129impl_try_from_repeated!(DiscMessage, Discs);