use crate::helpers::db; use crate::schema::{playlists, playlists_tracks}; use chrono::NaiveDateTime; use diesel::{prelude::*, result::Error}; use serde::{Deserialize, Serialize}; use super::artists_tracks::{ArtistTracks, TrackArtist}; use super::{playlists_tracks::PlaylistTracks, tracks::Tracks, users::Users}; #[derive(Debug, Deserialize, Serialize)] pub struct PlaylistCreator { pub id: String, pub name: String, } #[derive( AsChangeset, Debug, Deserialize, Identifiable, Queryable, Selectable, Serialize, PartialEq, )] #[diesel(table_name = playlists)] pub struct Playlists { pub id: String, pub name: String, pub public: bool, pub playlist_type: String, pub creator_id: String, pub parent_id: Option, pub created_at: Option, pub updated_at: Option, } #[derive(Debug, Deserialize, Insertable)] #[diesel(table_name = playlists)] pub struct NewPlaylist { pub name: String, pub public: bool, // pub playlist_type: String, pub creator_id: String, } impl Playlists { pub fn find(id: &str) -> Result { let conn = &mut db::connection()?; let playlist = playlists::table.filter(playlists::id.eq(id)).first(conn)?; Ok(playlist) } pub fn create(playlist: NewPlaylist) -> Result { let conn = &mut db::connection()?; let playlist = diesel::insert_into(playlists::table) .values(playlist) .get_result(conn)?; Ok(playlist) } pub fn find_for_user(user_id: &str, filter_public: bool) -> Result, Error> { let conn = &mut db::connection()?; let mut playlists = playlists::table .distinct() .select(Playlists::as_select()) .order((playlists::playlist_type.desc(), playlists::parent_id.desc())) .filter(playlists::creator_id.eq(user_id)) .into_boxed(); if filter_public { playlists = playlists.filter( playlists::public .eq(true) .and(playlists::playlist_type.ne("folder")), ); } let playlists = playlists.get_results(conn)?; Ok(playlists) } pub fn get_tracks(&self) -> Result, Error> { let tracks: Vec = PlaylistTracks::get_tracks(self)?; Ok(tracks) } pub fn get_creator(&self) -> Result { let creator = Users::find(&self.creator_id)?; Ok(creator) } pub fn get_data(&self, tracks: &[PlaylistTrack]) -> (usize, usize) { if tracks.is_empty() { return (0, 0); } let duration = tracks .iter() .map(|track| track.duration_ms) .reduce(|a, b| a + b) .unwrap() as usize; (duration, tracks.len()) } pub fn can_see(&self, creator: Option) -> bool { self.public || creator.map_or(false, |user| user.id == self.creator_id) } } // // Folder // struct Folder { // id: String, // name: String, // playlists: Vec, // } // impl Folder { // pub fn get_playlists(&self) -> Result, Error> { // let playlists = playlists::table // } // } #[derive(Deserialize, Serialize)] pub struct PlaylistTrack { pub id: String, pub title: String, pub duration_ms: i32, pub artists: Vec, pub added_at: NaiveDateTime, pub spotify_id: Option, pub tidal_id: Option, } impl From for PlaylistTrack { fn from(track: Tracks) -> Self { let artists = ArtistTracks::get_artists(&track).unwrap(); let added_at = playlists_tracks::table .filter(playlists_tracks::track_id.eq(&track.id)) .select(playlists_tracks::added_at) .first::(&mut db::connection().unwrap()) .unwrap(); PlaylistTrack { id: track.id, title: track.title, duration_ms: track.duration_ms, artists, added_at, spotify_id: track.spotify_id, tidal_id: track.tidal_id, } } }