use music_player_types::types::{RemoteTrackUrl, Song, Track as TrackType};
use sea_orm::{entity::prelude::*, ActiveValue};
use serde::{Deserialize, Serialize};
use crate::{album, artist, select_result};
#[derive(Clone, Debug, Default, PartialEq, DeriveEntityModel, Serialize, Deserialize)]
#[sea_orm(table_name = "track")]
pub struct Model {
#[sea_orm(primary_key, auto_increment = false)]
pub id: String,
pub title: String,
pub artist: String,
pub genre: String,
pub year: Option<u32>,
pub track: Option<u32>,
pub bitrate: Option<u32>,
pub sample_rate: Option<u32>,
pub bit_depth: Option<u8>,
pub channels: Option<u8>,
pub duration: Option<f32>,
pub uri: String,
pub album_id: Option<String>,
pub artist_id: Option<String>,
#[sea_orm(ignore)]
pub artists: Vec<artist::Model>,
#[sea_orm(ignore)]
pub album: album::Model,
}
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
pub enum Relation {
#[sea_orm(
belongs_to = "super::album::Entity",
from = "Column::AlbumId",
to = "super::album::Column::Id"
)]
Album,
#[sea_orm(
belongs_to = "super::artist::Entity",
from = "Column::ArtistId",
to = "super::artist::Column::Id"
)]
Artist,
}
impl Related<super::album::Entity> for Entity {
fn to() -> RelationDef {
Relation::Album.def()
}
}
impl Related<super::playlist::Entity> for Entity {
fn to() -> RelationDef {
super::playlist_tracks::Relation::Playlist.def()
}
fn via() -> Option<RelationDef> {
Some(super::playlist_tracks::Relation::Track.def().rev())
}
}
impl Related<super::artist::Entity> for Entity {
fn to() -> RelationDef {
super::artist_tracks::Relation::Artist.def()
}
fn via() -> Option<RelationDef> {
Some(super::artist_tracks::Relation::Track.def().rev())
}
}
impl ActiveModelBehavior for ActiveModel {}
#[derive(Debug)]
pub struct TrackToAlbum;
impl Linked for TrackToAlbum {
type FromEntity = super::track::Entity;
type ToEntity = super::album::Entity;
fn link(&self) -> Vec<RelationDef> {
vec![
super::album::Relation::Track.def().rev(),
super::track::Relation::Album.def(),
]
}
}
#[derive(Debug)]
pub struct TrackToArtist;
impl Linked for TrackToArtist {
type FromEntity = super::track::Entity;
type ToEntity = super::artist::Entity;
fn link(&self) -> Vec<RelationDef> {
vec![
super::artist_tracks::Relation::Track.def().rev(),
super::artist_tracks::Relation::Artist.def(),
]
}
}
#[derive(Debug)]
pub struct TrackToPlaylist;
impl Linked for TrackToPlaylist {
type FromEntity = super::track::Entity;
type ToEntity = super::playlist::Entity;
fn link(&self) -> Vec<RelationDef> {
vec![
super::playlist_tracks::Relation::Track.def().rev(),
super::playlist_tracks::Relation::Playlist.def(),
]
}
}
impl From<&Song> for ActiveModel {
fn from(song: &Song) -> Self {
let id = format!("{:x}", md5::compute(song.uri.as_ref().unwrap()));
Self {
id: ActiveValue::set(id),
artist: ActiveValue::Set(song.artist.clone()),
title: ActiveValue::Set(song.title.clone()),
genre: ActiveValue::Set(song.genre.clone()),
year: ActiveValue::Set(song.year),
track: ActiveValue::Set(song.track),
bitrate: ActiveValue::Set(song.bitrate),
sample_rate: ActiveValue::Set(song.sample_rate),
bit_depth: ActiveValue::Set(song.bit_depth),
channels: ActiveValue::Set(song.channels),
duration: ActiveValue::Set(Some(song.duration.as_secs_f32())),
uri: ActiveValue::Set(song.uri.clone().unwrap_or_default()),
album_id: ActiveValue::Set(Some(format!(
"{:x}",
md5::compute(format!("{}", song.album))
))),
artist_id: ActiveValue::Set(Some(format!(
"{:x}",
md5::compute(song.album_artist.to_owned())
))),
}
}
}
impl From<select_result::PlaylistTrack> for Model {
fn from(playlist_track: select_result::PlaylistTrack) -> Self {
Self {
id: playlist_track.track_id,
title: playlist_track.track_title,
artist: playlist_track.track_artist,
uri: playlist_track.track_uri,
album_id: Some(playlist_track.album_id.clone()),
artist_id: Some(playlist_track.artist_id.clone()),
duration: Some(playlist_track.track_duration),
album: album::Model {
id: playlist_track.album_id,
title: playlist_track.album_title,
cover: playlist_track.album_cover,
..Default::default()
},
artists: vec![artist::Model {
id: playlist_track.artist_id,
name: playlist_track.artist_name,
..Default::default()
}],
..Default::default()
}
}
}
impl From<TrackType> for Model {
fn from(track: TrackType) -> Self {
let track_album = track.album.unwrap();
Self {
id: track.id,
title: track.title,
artist: track.artist,
uri: track.uri,
album_id: Some(track_album.id.clone()),
artist_id: if track.artists.is_empty() {
None
} else {
Some(track.artists[0].id.clone())
},
duration: track.duration,
album: album::Model {
id: track_album.id,
title: track_album.title,
cover: track_album.cover,
year: track_album.year,
..Default::default()
},
artists: track.artists.into_iter().map(Into::into).collect(),
..Default::default()
}
}
}
impl Into<TrackType> for Model {
fn into(self) -> TrackType {
TrackType {
id: self.id,
title: self.title,
artist: self.artist,
uri: self.uri,
duration: self.duration,
album: Some(self.album.into()),
artists: self.artists.into_iter().map(Into::into).collect(),
..Default::default()
}
}
}
impl RemoteTrackUrl for Model {
fn with_remote_track_url(&self, base_url: &str) -> Self {
Self {
uri: format!("{}/tracks/{}", base_url, self.id),
..self.clone()
}
}
}