api/src/models/playlists.rs
2024-01-13 01:16:01 +01:00

155 lines
4.2 KiB
Rust

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<String>,
pub created_at: Option<NaiveDateTime>,
pub updated_at: Option<NaiveDateTime>,
}
#[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<Self, Error> {
let conn = &mut db::connection()?;
let playlist = playlists::table.filter(playlists::id.eq(id)).first(conn)?;
Ok(playlist)
}
pub fn create(playlist: NewPlaylist) -> Result<Self, Error> {
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<Vec<Playlists>, 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<Vec<PlaylistTrack>, Error> {
let tracks: Vec<PlaylistTrack> = PlaylistTracks::get_tracks(self)?;
Ok(tracks)
}
pub fn get_creator(&self) -> Result<Users, Error> {
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<Users>) -> bool {
self.public || creator.map_or(false, |user| user.id == self.creator_id)
}
}
// // Folder
// struct Folder {
// id: String,
// name: String,
// playlists: Vec<Playlists>,
// }
// impl Folder {
// pub fn get_playlists(&self) -> Result<Vec<Playlists>, Error> {
// let playlists = playlists::table
// }
// }
#[derive(Deserialize, Serialize)]
pub struct PlaylistTrack {
pub id: String,
pub title: String,
pub duration_ms: i32,
pub artists: Vec<TrackArtist>,
pub added_at: NaiveDateTime,
pub spotify_id: Option<String>,
pub tidal_id: Option<String>,
}
impl From<Tracks> 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::<NaiveDateTime>(&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,
}
}
}