From 2ed67e5545edcd2b02a20d0335da2f50ee4c34d8 Mon Sep 17 00:00:00 2001 From: Ethan Girouard Date: Fri, 10 May 2024 20:28:39 -0400 Subject: [PATCH] Add various like/dislike functions for users --- src/models.rs | 129 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 129 insertions(+) diff --git a/src/models.rs b/src/models.rs index 15a6d12..5a01257 100644 --- a/src/models.rs +++ b/src/models.rs @@ -43,6 +43,135 @@ pub struct User { pub created_at: Option, } +impl User { + /// Like or unlike a song for this user + /// If likeing a song, remove dislike if it exists + #[cfg(feature = "ssr")] + pub async fn set_like_song(self: &Self, song_id: i32, like: bool, conn: &mut PgPooledConn) -> + Result<(), Box> { + use log::*; + debug!("Setting like for song {} to {}", song_id, like); + + use crate::schema::song_likes; + use crate::schema::song_dislikes; + + let my_id = self.id.ok_or("User id must be present (Some) to like/un-like a song")?; + + if like { + diesel::insert_into(song_likes::table) + .values((song_likes::song_id.eq(song_id), song_likes::user_id.eq(my_id))) + .execute(conn)?; + + // Remove dislike if it exists + diesel::delete(song_dislikes::table.filter(song_dislikes::song_id.eq(song_id) + .and(song_dislikes::user_id.eq(my_id)))) + .execute(conn)?; + } else { + diesel::delete(song_likes::table.filter(song_likes::song_id.eq(song_id).and(song_likes::user_id.eq(my_id)))) + .execute(conn)?; + } + + Ok(()) + } + + /// Get the like status of a song for this user + #[cfg(feature = "ssr")] + pub async fn get_like_song(self: &Self, song_id: i32, conn: &mut PgPooledConn) -> Result> { + use crate::schema::song_likes; + + let my_id = self.id.ok_or("User id must be present (Some) to get like status of a song")?; + + let like = song_likes::table + .filter(song_likes::song_id.eq(song_id).and(song_likes::user_id.eq(my_id))) + .first::<(i32, i32)>(conn) + .optional()? + .is_some(); + + Ok(like) + } + + /// Get songs liked by this user + #[cfg(feature = "ssr")] + pub async fn get_liked_songs(self: &Self, conn: &mut PgPooledConn) -> Result, Box> { + use crate::schema::songs::dsl::*; + use crate::schema::song_likes::dsl::*; + + let my_id = self.id.ok_or("User id must be present (Some) to get liked songs")?; + + let my_songs = songs + .inner_join(song_likes) + .filter(user_id.eq(my_id)) + .select(songs::all_columns()) + .load(conn)?; + + Ok(my_songs) + } + + /// Dislike or remove dislike from a song for this user + /// If disliking a song, remove like if it exists + #[cfg(feature = "ssr")] + pub async fn set_dislike_song(self: &Self, song_id: i32, dislike: bool, conn: &mut PgPooledConn) -> + Result<(), Box> { + use log::*; + debug!("Setting dislike for song {} to {}", song_id, dislike); + + use crate::schema::song_likes; + use crate::schema::song_dislikes; + + let my_id = self.id.ok_or("User id must be present (Some) to dislike/un-dislike a song")?; + + if dislike { + diesel::insert_into(song_dislikes::table) + .values((song_dislikes::song_id.eq(song_id), song_dislikes::user_id.eq(my_id))) + .execute(conn)?; + + // Remove like if it exists + diesel::delete(song_likes::table.filter(song_likes::song_id.eq(song_id) + .and(song_likes::user_id.eq(my_id)))) + .execute(conn)?; + } else { + diesel::delete(song_dislikes::table.filter(song_dislikes::song_id.eq(song_id) + .and(song_dislikes::user_id.eq(my_id)))) + .execute(conn)?; + } + + Ok(()) + } + + /// Get the dislike status of a song for this user + #[cfg(feature = "ssr")] + pub async fn get_dislike_song(self: &Self, song_id: i32, conn: &mut PgPooledConn) -> Result> { + use crate::schema::song_dislikes; + + let my_id = self.id.ok_or("User id must be present (Some) to get dislike status of a song")?; + + let dislike = song_dislikes::table + .filter(song_dislikes::song_id.eq(song_id).and(song_dislikes::user_id.eq(my_id))) + .first::<(i32, i32)>(conn) + .optional()? + .is_some(); + + Ok(dislike) + } + + /// Get songs disliked by this user + #[cfg(feature = "ssr")] + pub async fn get_disliked_songs(self: &Self, conn: &mut PgPooledConn) -> Result, Box> { + use crate::schema::songs::dsl::*; + use crate::schema::song_likes::dsl::*; + + let my_id = self.id.ok_or("User id must be present (Some) to get disliked songs")?; + + let my_songs = songs + .inner_join(song_likes) + .filter(user_id.eq(my_id)) + .select(songs::all_columns()) + .load(conn)?; + + Ok(my_songs) + } +} + /// Model for an artist #[cfg_attr(feature = "ssr", derive(Queryable, Selectable, Insertable))] #[cfg_attr(feature = "ssr", diesel(table_name = crate::schema::artists))]