1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
use std::collections::HashMap;

use chrono::{DateTime, NaiveDate, Utc};
use serde::{Deserialize, Serialize};

use crate::model::{
    ArtistSimplified, Copyright, DatePrecision, Image, Page, Restrictions, TrackSimplified,
    TypeAlbum,
};
use crate::util;

macro_rules! inherit_album_simplified {
    ($(#[$attr:meta])* $name:ident { $($(#[$f_attr:meta])* $f_name:ident : $f_ty:ty,)* }) => {
        to_struct!($(#[$attr])* $name {
            $(
                $(#[$f_attr])*
                $f_name: $f_ty,
            )*
            /// The list of artists who made this album.
            artists: Vec<ArtistSimplified>,
            /// The markets in which at least 1 of the album's tracks is available. Only Some if
            /// the market parameter is not supplied in the request. This is an ISO 3166 2-letter
            /// country code.
            available_markets: Option<Vec<String>>,
            /// Known external URLs for this album.
            external_urls: HashMap<String, String>,
            /// The cover art for the album in various sizes, widest first.
            images: Vec<Image>,
            /// The name of the album; if the album has been taken down, this is an empty string.
            name: String,
            /// When [track
            /// relinking](https://developer.spotify.com/documentation/general/guides/track-relinking-guide/)
            /// is applied, the original track isn't available in the given market and Spotify didn't have
            /// any tracks to relink it with, then this is Some.
            restrictions: Option<Restrictions>,
            /// The item type; `album`.
            #[serde(rename = "type")]
            item_type: TypeAlbum,
        });
    }
}

inherit_album_simplified!(
    /// A simplified album object.
    AlbumSimplified {
        /// The type of album: album, single or compilation. This can only be not present for the
        /// album of a local track, which can only ever be obtained from a playlist.
        album_type: Option<AlbumType>,
        /// The [Spotify ID](https://developer.spotify.com/documentation/web-api/#spotify-uris-and-ids)
        /// for this album. This can only be `None` for the album of a local track, which can only
        /// ever be obtained from a playlist.
        id: Option<String>,
        /// When the album was released. This can only be `None` for the album of a local track,
        /// which can only ever be obtained from a playlist.
        #[serde(deserialize_with = "util::de_date_any_precision_option")]
        release_date: Option<NaiveDate>,
        /// How precise the release date is: precise to the year, month or day. This can only be
        /// `None` for the album of a local track,which can only ever be obtained from a playlist.
        release_date_precision: Option<DatePrecision>,
    }
);

macro_rules! inherit_album_not_local {
    ($(#[$attr:meta])* $name:ident { $($(#[$f_attr:meta])* $f_name:ident : $f_ty:ty,)* }) => {
        inherit_album_simplified!($(#[$attr])* $name {
            $(
                $(#[$f_attr])*
                $f_name: $f_ty,
            )*
            /// The type of album: album, single or compilation.
            album_type: AlbumType,
            /// The [Spotify ID](https://developer.spotify.com/documentation/web-api/#spotify-uris-and-ids)
            /// for this album.
            id: String,
            /// When the album was released.
            #[serde(deserialize_with = "util::de_date_any_precision")]
            release_date: NaiveDate,
            /// How precise the release date is: precise to the year, month or day.
            release_date_precision: DatePrecision,
        });
    }
}

inherit_album_not_local!(
    /// An album object.
    Album {
        /// The known copyrights of this album.
        copyrights: Vec<Copyright>,
        /// Known external IDs for this album.
        external_ids: HashMap<String, String>,
        /// A list of the genres used to classify the album. For example: "Prog Rock", "Post-Grunge".
        /// If not yet classified, the array is empty.
        genres: Vec<String>,
        /// The label of the album.
        label: String,
        /// The popularity of the album. The value will be between 0 and 100, with 100 being the most
        /// popular. The popularity is calculated from the popularity of the album's individual tracks.
        popularity: u32,
        /// A page of tracks in the album.
        tracks: Page<TrackSimplified>,
    }
);
inherit_album_not_local!(
    /// A simplified album object from the context of an artist.
    ArtistsAlbum {
        /// Similar to AlbumType, but also includes if the artist features on the album, and didn't
        /// create it as an album, single or compilation.
        album_group: AlbumGroup,
    }
);

impl Album {
    /// Convert to an `AlbumSimplified`.
    #[must_use]
    pub fn simplify(self) -> AlbumSimplified {
        AlbumSimplified {
            album_type: Some(self.album_type),
            artists: self.artists,
            available_markets: self.available_markets,
            external_urls: self.external_urls,
            id: Some(self.id),
            images: self.images,
            name: self.name,
            release_date: Some(self.release_date),
            release_date_precision: Some(self.release_date_precision),
            restrictions: self.restrictions,
            item_type: TypeAlbum,
        }
    }
}
impl From<Album> for AlbumSimplified {
    fn from(album: Album) -> Self {
        album.simplify()
    }
}
impl ArtistsAlbum {
    /// Convert to an `AlbumSimplified`.
    #[must_use]
    pub fn simplify(self) -> AlbumSimplified {
        AlbumSimplified {
            album_type: Some(self.album_type),
            artists: self.artists,
            available_markets: self.available_markets,
            external_urls: self.external_urls,
            id: Some(self.id),
            images: self.images,
            name: self.name,
            release_date: Some(self.release_date),
            release_date_precision: Some(self.release_date_precision),
            restrictions: self.restrictions,
            item_type: TypeAlbum,
        }
    }
}
impl From<ArtistsAlbum> for AlbumSimplified {
    fn from(album: ArtistsAlbum) -> Self {
        album.simplify()
    }
}

/// The type of album.
#[derive(Debug, Clone, PartialEq, Eq, Copy, Hash, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum AlbumType {
    /// An album.
    #[serde(alias = "ALBUM")]
    Album,
    /// A single.
    #[serde(alias = "SINGLE")]
    Single,
    /// A compilation album.
    #[serde(alias = "COMPILATION")]
    Compilation,
}

/// Similar to `AlbumType`, but with an extra variant.
#[derive(Debug, Clone, PartialEq, Eq, Copy, Hash, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum AlbumGroup {
    /// An album.
    Album,
    /// A single.
    Single,
    /// A compilation album.
    Compilation,
    /// When getting all an artist's albums, if the artist didn't release the album but instead
    /// appeared on it, it is this value.
    AppearsOn,
}

impl AlbumGroup {
    /// Get the album's type as a string.
    #[must_use]
    pub fn as_str(self) -> &'static str {
        match self {
            AlbumGroup::Album => "album",
            AlbumGroup::Single => "single",
            AlbumGroup::Compilation => "compilation",
            AlbumGroup::AppearsOn => "appears_on",
        }
    }
}

/// Information about an album that has been saved.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct SavedAlbum {
    /// When the album was saved.
    pub added_at: DateTime<Utc>,
    /// Information about the album.
    pub album: Album,
}