use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "lowercase")]
pub enum ItemType {
User,
Album,
Artist,
Playlist,
Track,
Show,
Episode,
Audiobook,
Unknown,
Chapter,
Collection,
}
impl std::fmt::Display for ItemType {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let s = match self {
Self::User => "user",
Self::Album => "album",
Self::Artist => "artist",
Self::Playlist => "playlist",
Self::Track => "track",
Self::Show => "show",
Self::Episode => "episode",
Self::Audiobook => "audiobook",
Self::Unknown => "unknown",
Self::Chapter => "chapter",
Self::Collection => "collection",
};
write!(f, "{s}")
}
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub struct Image {
pub url: String,
pub height: Option<u16>,
pub width: Option<u16>,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub struct Icon {
pub url: String,
pub height: Option<u16>,
pub width: Option<u16>,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub struct VideoThumbnail {
pub url: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub struct ExternalUrls {
pub spotify: String,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub struct ExternalIds {
#[serde(skip_serializing_if = "Option::is_none")]
pub isrc: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub ean: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub upc: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub struct Followers {
pub href: Option<String>,
pub total: usize,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "lowercase")]
pub enum ReleaseDatePrecision {
Year,
Month,
Day,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub struct Restrictions {
pub reason: String,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub enum CopyrightType {
C,
P,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub struct Copyright {
pub text: String,
#[serde(rename = "type")]
pub type_: CopyrightType,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub struct Page<T> {
pub href: String,
pub limit: usize,
pub next: Option<String>,
pub offset: usize,
pub previous: Option<String>,
pub total: usize,
pub items: Vec<T>,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub struct Cursors {
#[serde(skip_serializing_if = "Option::is_none")]
pub after: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub before: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub struct ResumePoint {
pub fully_played: bool,
pub resume_position_ms: u32,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
#[serde(untagged)]
#[allow(clippy::large_enum_variant)]
pub enum TrackItem {
Track(super::Track),
Episode(super::Episode),
}
impl TrackItem {
pub fn id(&self) -> &str {
match &self {
Self::Track(track) => track.id.as_str(),
Self::Episode(episode) => episode.id.as_str(),
}
}
pub fn name(&self) -> &str {
match &self {
Self::Track(track) => track.name.as_str(),
Self::Episode(episode) => episode.name.as_str(),
}
}
pub fn is_playable(&self) -> bool {
match &self {
Self::Track(track) => track.is_playable.unwrap_or(false),
Self::Episode(episode) => episode.is_playable,
}
}
pub fn duration_ms(&self) -> u32 {
match &self {
Self::Track(track) => track.duration_ms,
Self::Episode(episode) => episode.duration_ms,
}
}
pub fn external_url(&self) -> &str {
match &self {
Self::Track(track) => track.external_urls.spotify.as_str(),
Self::Episode(episode) => episode.external_urls.spotify.as_str(),
}
}
pub fn href(&self) -> &str {
match &self {
Self::Track(track) => track.href.as_str(),
Self::Episode(episode) => episode.href.as_str(),
}
}
pub fn restrictions(&self) -> Option<&Restrictions> {
match &self {
Self::Track(track) => track.restrictions.as_ref(),
Self::Episode(episode) => episode.restrictions.as_ref(),
}
}
pub fn explicit(&self) -> bool {
match &self {
Self::Track(track) => track.explicit,
Self::Episode(episode) => episode.explicit,
}
}
pub fn uri(&self) -> &str {
match &self {
Self::Track(track) => track.uri.as_str(),
Self::Episode(episode) => episode.uri.as_str(),
}
}
}
#[derive(Debug, Default, Clone, Serialize, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "snake_case")]
pub enum TimeRange {
LongTerm,
#[default]
MediumTerm,
ShortTerm,
}
impl std::fmt::Display for TimeRange {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::LongTerm => write!(f, "long_term"),
Self::MediumTerm => write!(f, "medium_term"),
Self::ShortTerm => write!(f, "short_term"),
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "lowercase")]
pub enum TopItemType {
Artists,
Tracks,
}
impl std::fmt::Display for TopItemType {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Artists => write!(f, "artists"),
Self::Tracks => write!(f, "tracks"),
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
#[serde(untagged)]
#[allow(clippy::large_enum_variant)]
pub enum TopItem {
Artist(super::Artist),
Track(super::Track),
}
pub type TopItems = Page<TopItem>;
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "lowercase")]
pub enum FollowedArtistsType {
Artist,
}
impl std::fmt::Display for FollowedArtistsType {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Artist => write!(f, "artist"),
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "lowercase")]
pub enum FollowType {
Artist,
User,
}
impl std::fmt::Display for FollowType {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let s = match self {
Self::Artist => "artist",
Self::User => "user",
};
write!(f, "{s}")
}
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "lowercase")]
pub enum IncludeExternalType {
Audio,
}
impl std::fmt::Display for IncludeExternalType {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let s = match self {
Self::Audio => "audio",
};
write!(f, "{s}")
}
}