2021-12-26 20:18:42 +00:00
|
|
|
use std::{
|
|
|
|
convert::{TryFrom, TryInto},
|
|
|
|
fmt::Debug,
|
2022-08-02 10:45:37 +00:00
|
|
|
ops::{Deref, DerefMut},
|
2021-12-26 20:18:42 +00:00
|
|
|
};
|
2021-12-07 22:22:24 +00:00
|
|
|
|
|
|
|
use uuid::Uuid;
|
|
|
|
|
|
|
|
use crate::{
|
|
|
|
artist::{Artists, ArtistsWithRole},
|
|
|
|
audio::{
|
|
|
|
file::AudioFiles,
|
|
|
|
item::{AudioItem, AudioItemResult, InnerAudioItem},
|
|
|
|
},
|
|
|
|
availability::{Availabilities, UnavailabilityReason},
|
|
|
|
content_rating::ContentRatings,
|
|
|
|
external_id::ExternalIds,
|
|
|
|
restriction::Restrictions,
|
|
|
|
sale_period::SalePeriods,
|
2022-08-02 12:21:07 +00:00
|
|
|
util::{impl_deref_wrapped, impl_try_from_repeated},
|
2022-06-29 22:22:27 +00:00
|
|
|
Album, Metadata, RequestResult,
|
2021-12-07 22:22:24 +00:00
|
|
|
};
|
|
|
|
|
2021-12-26 20:18:42 +00:00
|
|
|
use librespot_core::{date::Date, Error, Session, SpotifyId};
|
2021-12-07 22:22:24 +00:00
|
|
|
use librespot_protocol as protocol;
|
|
|
|
|
|
|
|
#[derive(Debug, Clone)]
|
|
|
|
pub struct Track {
|
|
|
|
pub id: SpotifyId,
|
|
|
|
pub name: String,
|
2022-06-29 22:22:27 +00:00
|
|
|
pub album: Album,
|
2021-12-07 22:22:24 +00:00
|
|
|
pub artists: Artists,
|
|
|
|
pub number: i32,
|
|
|
|
pub disc_number: i32,
|
|
|
|
pub duration: i32,
|
|
|
|
pub popularity: i32,
|
|
|
|
pub is_explicit: bool,
|
|
|
|
pub external_ids: ExternalIds,
|
|
|
|
pub restrictions: Restrictions,
|
|
|
|
pub files: AudioFiles,
|
|
|
|
pub alternatives: Tracks,
|
|
|
|
pub sale_periods: SalePeriods,
|
|
|
|
pub previews: AudioFiles,
|
|
|
|
pub tags: Vec<String>,
|
|
|
|
pub earliest_live_timestamp: Date,
|
|
|
|
pub has_lyrics: bool,
|
|
|
|
pub availability: Availabilities,
|
|
|
|
pub licensor: Uuid,
|
|
|
|
pub language_of_performance: Vec<String>,
|
|
|
|
pub content_ratings: ContentRatings,
|
|
|
|
pub original_title: String,
|
|
|
|
pub version_title: String,
|
|
|
|
pub artists_with_role: ArtistsWithRole,
|
|
|
|
}
|
|
|
|
|
2022-07-31 22:44:43 +00:00
|
|
|
#[derive(Debug, Clone, Default)]
|
2021-12-07 22:22:24 +00:00
|
|
|
pub struct Tracks(pub Vec<SpotifyId>);
|
|
|
|
|
2022-08-02 10:45:37 +00:00
|
|
|
impl_deref_wrapped!(Tracks, Vec<SpotifyId>);
|
2021-12-07 22:22:24 +00:00
|
|
|
|
|
|
|
#[async_trait]
|
|
|
|
impl InnerAudioItem for Track {
|
|
|
|
async fn get_audio_item(session: &Session, id: SpotifyId) -> AudioItemResult {
|
2022-08-03 20:26:52 +00:00
|
|
|
let track = Self::get(session, &id).await?;
|
2021-12-07 22:22:24 +00:00
|
|
|
let alternatives = {
|
|
|
|
if track.alternatives.is_empty() {
|
|
|
|
None
|
|
|
|
} else {
|
|
|
|
Some(track.alternatives.clone())
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
// TODO: check meaning of earliest_live_timestamp in
|
2022-01-14 22:28:09 +00:00
|
|
|
let availability = if Date::now_utc() < track.earliest_live_timestamp {
|
2021-12-07 22:22:24 +00:00
|
|
|
Err(UnavailabilityReason::Embargo)
|
|
|
|
} else {
|
2021-12-11 19:22:44 +00:00
|
|
|
Self::available_for_user(
|
|
|
|
&session.user_data(),
|
|
|
|
&track.availability,
|
|
|
|
&track.restrictions,
|
|
|
|
)
|
2021-12-07 22:22:24 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
Ok(AudioItem {
|
|
|
|
id,
|
2022-02-14 11:15:19 +00:00
|
|
|
spotify_uri: id.to_uri()?,
|
2021-12-07 22:22:24 +00:00
|
|
|
files: track.files,
|
|
|
|
name: track.name,
|
|
|
|
duration: track.duration,
|
|
|
|
availability,
|
|
|
|
alternatives,
|
2021-12-30 22:50:28 +00:00
|
|
|
is_explicit: track.is_explicit,
|
2021-12-07 22:22:24 +00:00
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[async_trait]
|
|
|
|
impl Metadata for Track {
|
|
|
|
type Message = protocol::metadata::Track;
|
|
|
|
|
2022-08-03 20:26:52 +00:00
|
|
|
async fn request(session: &Session, track_id: &SpotifyId) -> RequestResult {
|
2021-12-26 20:18:42 +00:00
|
|
|
session.spclient().get_track_metadata(track_id).await
|
2021-12-07 22:22:24 +00:00
|
|
|
}
|
|
|
|
|
2022-08-03 20:26:52 +00:00
|
|
|
fn parse(msg: &Self::Message, _: &SpotifyId) -> Result<Self, Error> {
|
2021-12-07 22:22:24 +00:00
|
|
|
Self::try_from(msg)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl TryFrom<&<Self as Metadata>::Message> for Track {
|
2021-12-26 20:18:42 +00:00
|
|
|
type Error = librespot_core::Error;
|
2021-12-07 22:22:24 +00:00
|
|
|
fn try_from(track: &<Self as Metadata>::Message) -> Result<Self, Self::Error> {
|
|
|
|
Ok(Self {
|
|
|
|
id: track.try_into()?,
|
|
|
|
name: track.get_name().to_owned(),
|
|
|
|
album: track.get_album().try_into()?,
|
|
|
|
artists: track.get_artist().try_into()?,
|
|
|
|
number: track.get_number(),
|
|
|
|
disc_number: track.get_disc_number(),
|
|
|
|
duration: track.get_duration(),
|
|
|
|
popularity: track.get_popularity(),
|
|
|
|
is_explicit: track.get_explicit(),
|
|
|
|
external_ids: track.get_external_id().into(),
|
|
|
|
restrictions: track.get_restriction().into(),
|
|
|
|
files: track.get_file().into(),
|
|
|
|
alternatives: track.get_alternative().try_into()?,
|
2022-01-14 22:28:09 +00:00
|
|
|
sale_periods: track.get_sale_period().try_into()?,
|
2021-12-07 22:22:24 +00:00
|
|
|
previews: track.get_preview().into(),
|
|
|
|
tags: track.get_tags().to_vec(),
|
2022-07-28 16:46:16 +00:00
|
|
|
earliest_live_timestamp: Date::from_timestamp_ms(track.get_earliest_live_timestamp())?,
|
2021-12-07 22:22:24 +00:00
|
|
|
has_lyrics: track.get_has_lyrics(),
|
2022-01-14 22:28:09 +00:00
|
|
|
availability: track.get_availability().try_into()?,
|
2021-12-07 22:22:24 +00:00
|
|
|
licensor: Uuid::from_slice(track.get_licensor().get_uuid())
|
|
|
|
.unwrap_or_else(|_| Uuid::nil()),
|
|
|
|
language_of_performance: track.get_language_of_performance().to_vec(),
|
|
|
|
content_ratings: track.get_content_rating().into(),
|
|
|
|
original_title: track.get_original_title().to_owned(),
|
|
|
|
version_title: track.get_version_title().to_owned(),
|
|
|
|
artists_with_role: track.get_artist_with_role().try_into()?,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-08-02 12:21:07 +00:00
|
|
|
impl_try_from_repeated!(<Track as Metadata>::Message, Tracks);
|