diff options
Diffstat (limited to 'src/database')
-rw-r--r-- | src/database/friends.rs | 97 | ||||
-rw-r--r-- | src/database/likes.rs | 8 | ||||
-rw-r--r-- | src/database/mod.rs | 2 | ||||
-rw-r--r-- | src/database/users.rs | 2 |
4 files changed, 103 insertions, 6 deletions
diff --git a/src/database/friends.rs b/src/database/friends.rs new file mode 100644 index 0000000..0b78488 --- /dev/null +++ b/src/database/friends.rs @@ -0,0 +1,97 @@ +use tracing::instrument; + +use crate::{ + database::{self, users::user_from_row}, + types::user::{User, FOLLOWED, FOLLOWING, NO_RELATION}, +}; + +pub fn init() -> Result<(), rusqlite::Error> { + let sql = " + CREATE TABLE IF NOT EXISTS friends ( + follower_id INTEGER NOT NULL, + followee_id INTEGER NOT NULL, + FOREIGN KEY(follower_id) REFERENCES users(user_id), + FOREIGN KEY(followee_id) REFERENCES users(user_id), + PRIMARY KEY (follower_id, followee_id) + ); + "; + let conn = database::connect()?; + conn.execute(sql, ())?; + Ok(()) +} + +#[instrument()] +pub fn get_friend_status(user_id_1: u64, user_id_2: u64) -> Result<u8, rusqlite::Error> { + tracing::trace!("Retrieving friend status"); + let conn = database::connect()?; + let mut stmt = conn.prepare("SELECT * FROM friends WHERE (follower_id = ? AND followee_id = ?) OR (follower_id = ? AND followee_id = ?);")?; + let mut status = NO_RELATION; + let rows: Vec<u64> = stmt + .query_map([user_id_1, user_id_2, user_id_2, user_id_1], |row| { + let id: u64 = row.get(0)?; + Ok(id) + })? + .into_iter() + .flatten() + .collect(); + + for follower in rows { + if follower == user_id_1 { + status |= FOLLOWING; + } + + if follower == user_id_2 { + status |= FOLLOWED; + } + } + + Ok(status) +} + +#[instrument()] +pub fn get_friends(user_id: u64) -> Result<Vec<User>, rusqlite::Error> { + tracing::trace!("Retrieving friends"); + let conn = database::connect()?; + let mut stmt = conn.prepare( + " + SELECT * + FROM users u + WHERE EXISTS ( + SELECT NULL + FROM friends f + WHERE u.user_id = f.follower_id + AND f.followee_id = ? + ) + AND EXISTS ( + SELECT NULL + FROM friends f + WHERE u.user_id = f.followee_id + AND f.follower_id = ? + ) + ", + )?; + let row = stmt.query_map([user_id, user_id], |row| { + let row = user_from_row(row, true)?; + Ok(row) + })?; + Ok(row.into_iter().flatten().collect()) +} + +#[instrument()] +pub fn set_following(user_id_1: u64, user_id_2: u64) -> Result<bool, rusqlite::Error> { + tracing::trace!("Setting following"); + let conn = database::connect()?; + let mut stmt = + conn.prepare("INSERT OR REPLACE INTO friends (follower_id, followee_id) VALUES (?,?)")?; + let changes = stmt.execute([user_id_1, user_id_2])?; + Ok(changes == 1) +} + +#[instrument()] +pub fn remove_following(user_id_1: u64, user_id_2: u64) -> Result<bool, rusqlite::Error> { + tracing::trace!("Removing following"); + let conn = database::connect()?; + let mut stmt = conn.prepare("DELETE FROM friends WHERE follower_id = ? AND followee_id = ?")?; + let changes = stmt.execute([user_id_1, user_id_2])?; + Ok(changes == 1) +} diff --git a/src/database/likes.rs b/src/database/likes.rs index 6f6939e..f6a130b 100644 --- a/src/database/likes.rs +++ b/src/database/likes.rs @@ -37,9 +37,7 @@ pub fn get_liked(user_id: u64, post_id: u64) -> Result<bool, rusqlite::Error> { tracing::trace!("Retrieving if liked"); let conn = database::connect()?; let mut stmt = conn.prepare("SELECT * FROM likes WHERE user_id = ? AND post_id = ?")?; - let liked = stmt.query_row([user_id, post_id], |_| { - Ok(()) - }).optional()?; + let liked = stmt.query_row([user_id, post_id], |_| Ok(())).optional()?; Ok(liked.is_some()) } @@ -49,7 +47,7 @@ pub fn add_liked(user_id: u64, post_id: u64) -> Result<bool, rusqlite::Error> { let conn = database::connect()?; let mut stmt = conn.prepare("INSERT OR REPLACE INTO likes (user_id, post_id) VALUES (?,?)")?; let changes = stmt.execute([user_id, post_id])?; - Ok(changes == 1) + Ok(changes == 1) } #[instrument()] @@ -69,7 +67,7 @@ pub fn get_all_likes() -> Result<Vec<Like>, rusqlite::Error> { let row = stmt.query_map([], |row| { let like = Like { user_id: row.get(0)?, - post_id: row.get(1)? + post_id: row.get(1)?, }; Ok(like) })?; diff --git a/src/database/mod.rs b/src/database/mod.rs index 6d4853a..d22a350 100644 --- a/src/database/mod.rs +++ b/src/database/mod.rs @@ -1,6 +1,7 @@ use tracing::instrument; pub mod comments; +pub mod friends; pub mod likes; pub mod posts; pub mod sessions; @@ -16,6 +17,7 @@ pub fn init() -> Result<(), rusqlite::Error> { sessions::init()?; likes::init()?; comments::init()?; + friends::init()?; Ok(()) } diff --git a/src/database/users.rs b/src/database/users.rs index 15565f1..6062ea8 100644 --- a/src/database/users.rs +++ b/src/database/users.rs @@ -31,7 +31,7 @@ pub fn init() -> Result<(), rusqlite::Error> { Ok(()) } -fn user_from_row(row: &Row, hide_password: bool) -> Result<User, rusqlite::Error> { +pub fn user_from_row(row: &Row, hide_password: bool) -> Result<User, rusqlite::Error> { let user_id = row.get(0)?; let firstname = row.get(1)?; let lastname = row.get(2)?; |