use std::collections::HashMap;
use crate::client::models::{album::Album, artist::Artist, media::MediaMetadata};
#[derive(Debug, serde::Serialize, serde::Deserialize)]
pub struct Track {
pub id: u64,
pub title: String,
pub duration: u64,
#[serde(rename = "replayGain")]
pub replay_gain: f64,
pub peak: f32,
#[serde(rename = "allowStreaming")]
pub allow_streaming: bool,
#[serde(rename = "streamReady")]
pub stream_ready: bool,
#[serde(rename = "payToStream")]
pub pay_to_stream: bool,
#[serde(rename = "adSupportedStreamReady")]
pub ad_supported_stream_ready: bool,
#[serde(rename = "djReady")]
pub dj_ready: bool,
#[serde(rename = "stemReady")]
pub stem_ready: bool,
#[serde(rename = "streamStartDate")]
pub stream_start_date: String,
#[serde(rename = "premiumStreamingOnly")]
pub premium_streaming_only: bool,
#[serde(rename = "trackNumber")]
pub track_number: u32,
#[serde(rename = "volumeNumber")]
pub volume_number: u32,
pub version: Option<String>,
pub popularity: u32,
pub copyright: String,
pub bpm: Option<f32>,
pub url: String,
pub isrc: String,
pub editable: bool,
pub explicit: bool,
#[serde(rename = "audioQuality")]
pub audio_quality: String,
#[serde(rename = "audioModes")]
pub audio_modes: Vec<String>,
#[serde(rename = "mediaMetadata")]
pub media_metadata: Option<MediaMetadata>,
pub upload: bool,
#[serde(rename = "accessType")]
pub access_type: Option<String>,
pub spotlighted: Option<bool>,
#[serde(rename = "dateAdded")]
pub date_added: Option<String>,
pub index: Option<u64>,
pub artist: Artist,
pub artists: Vec<Artist>,
pub album: Album,
pub mixes: Option<HashMap<String, String>>,
#[serde(rename = "itemUuid")]
pub item_uuid: Option<String>,
}
#[derive(Debug, serde::Serialize, serde::Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct TrackPlaybackInfoPostPaywallResponse {
pub track_id: u64,
pub asset_presentation: String,
pub audio_mode: String,
pub audio_quality: String,
pub manifest_mime_type: String,
pub manifest_hash: String,
#[serde(skip_deserializing, default)]
pub manifest: Option<TrackManifest>,
#[serde(skip_deserializing, default)]
pub manifest_parsed: Option<ManifestType>,
pub album_replay_gain: f64,
pub album_peak_amplitude: f64,
pub track_replay_gain: f64,
pub track_peak_amplitude: f64,
}
impl TrackPlaybackInfoPostPaywallResponse {
pub fn get_stream_urls(&self) -> Option<Vec<String>> {
self.manifest_parsed.as_ref().map(|m| match m {
ManifestType::Json(json_manifest) => json_manifest.urls.clone(),
ManifestType::Dash(dash_manifest) => dash_manifest.urls.clone(),
})
}
pub fn get_primary_url(&self) -> Option<String> {
self.get_stream_urls()
.and_then(|urls| urls.into_iter().next())
}
pub fn get_mime_type(&self) -> Option<String> {
self.manifest_parsed.as_ref().map(|m| match m {
ManifestType::Json(json_manifest) => json_manifest.mime_type.clone(),
ManifestType::Dash(dash_manifest) => dash_manifest.mime_type.clone(),
})
}
pub fn get_codecs(&self) -> Option<String> {
self.manifest_parsed.as_ref().map(|m| match m {
ManifestType::Json(json_manifest) => json_manifest.codecs.clone(),
ManifestType::Dash(dash_manifest) => dash_manifest.codecs.clone(),
})
}
}
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct TrackManifest {
pub mime_type: String,
pub codecs: String,
pub encryption_type: String,
pub urls: Vec<String>,
}
#[derive(Debug, serde::Serialize, serde::Deserialize)]
pub enum ManifestType {
Json(TrackManifest),
Dash(DashManifest),
}
#[derive(Debug, serde::Serialize, serde::Deserialize)]
pub struct DashManifest {
pub mime_type: String,
pub codecs: String,
pub urls: Vec<String>,
pub bitrate: Option<u32>,
pub initialization_url: Option<String>,
pub media_url_template: Option<String>,
#[serde(skip_serializing_if = "Option::is_none", default)]
pub timescale: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none", default)]
pub duration: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none", default, rename = "startNumber")]
pub start_number: Option<u32>,
}
impl DashManifest {
pub fn get_init_url(&self) -> Option<&String> {
self.initialization_url
.as_ref()
.or_else(|| self.urls.first())
}
pub fn get_media_template(&self) -> Option<&String> {
self.media_url_template
.as_ref()
.or_else(|| self.urls.get(1))
}
pub fn get_segment_url(&self, segment_number: u32) -> Option<String> {
self.get_media_template()
.map(|template| template.replace("$Number$", &segment_number.to_string()))
}
}