//! # Friends helper //! //! @author Pierre Hubert use crate::constants::database_tables_names::{FRIENDS_TABLE, USERS_TABLE}; use crate::data::error::{ExecError, ResultBoxError}; use crate::data::friend::Friend; use crate::data::friendship_status::FriendshipStatus; use crate::data::user::UserID; use crate::helpers::database; use crate::helpers::database::QueryInfo; /// Structure used to get a friend information pub struct GetFriendsQuery { target_user: UserID, friend_id: Option, } impl GetFriendsQuery { /// Construct a new request pub fn new(target_user: &UserID) -> GetFriendsQuery { GetFriendsQuery { target_user: target_user.clone(), friend_id: None, } } /// Get the list of friends pub fn exec(self) -> ResultBoxError> { get_list(&self) } /// Get information about a single friendship pub fn get_single_friend(mut self, friend_id: &UserID) -> ResultBoxError { self.friend_id = Some(friend_id.clone()); get_list(&self)? .pop() .ok_or(ExecError::boxed_new("Single friend not found!")) } } /// Get the list of friends of a user fn get_list(friend_query: &GetFriendsQuery) -> ResultBoxError> { let mut query = database::QueryInfo::new(FRIENDS_TABLE) .alias("f") .cond_user_id("ID_personne", &friend_query.target_user) .join(USERS_TABLE, "u", "f.ID_amis = u.ID") .add_field("u.last_activity") .add_field("f.ID_amis") .add_field("f.actif") .add_field("f.abonnement") .add_field("f.autoriser_post_page") .set_order("u.last_activity DESC"); if let Some(friend_id) = friend_query.friend_id.as_ref() { query = query.cond_user_id("ID_amis", friend_id); } query.exec(db_to_friend) } /// Send a new friendship request pub fn send_request(user_id: &UserID, target_user: &UserID) -> ResultBoxError { database::InsertQuery::new(FRIENDS_TABLE) .add_user_id("ID_personne", target_user) .add_user_id("ID_amis", user_id) .add_legacy_bool("actif", false) .insert_drop_result() } /// Remove a friendship request pub fn remove_request(user_id: &UserID, target_user: &UserID) -> ResultBoxError { database::DeleteQuery::new(FRIENDS_TABLE) .cond_user_id("ID_personne", target_user) .cond_user_id("ID_amis", user_id) .cond_legacy_bool("actif", false) .exec() } /// Check out whether a user has sent a request to another user pub fn sent_request(user_id: &UserID, target_user: &UserID) -> ResultBoxError { database::QueryInfo::new(FRIENDS_TABLE) .cond_user_id("ID_personne", target_user) .cond_user_id("ID_amis", user_id) .cond_legacy_bool("actif", false) .exec_count() .map(|f| f > 0) } /// Respond to a friendship request pub fn respond_request(user_id: &UserID, friend_id: &UserID, accept: bool) -> ResultBoxError { // Delete the request remove_request(friend_id, user_id)?; if accept { database::InsertQuery::new(FRIENDS_TABLE) .add_user_id("ID_personne", user_id) .add_user_id("ID_amis", friend_id) .add_legacy_bool("actif", true) .insert_drop_result()?; database::InsertQuery::new(FRIENDS_TABLE) .add_user_id("ID_personne", friend_id) .add_user_id("ID_amis", user_id) .add_legacy_bool("actif", true) .insert_drop_result()?; } Ok(()) } /// Check out whether two users are friend or not pub fn are_friend(user_one: &UserID, user_two: &UserID) -> ResultBoxError { Ok(database::count(QueryInfo::new(FRIENDS_TABLE) .cond_user_id("ID_personne", user_one) .cond_user_id("ID_amis", user_two) .cond_i64("actif", 1))? > 0) } /// Delete a friendship pub fn remove_friendship(user_one: &UserID, user_two: &UserID) -> ResultBoxError { database::DeleteQuery::new(FRIENDS_TABLE) .cond_user_id("ID_personne", user_one) .cond_user_id("ID_amis", user_two) .exec()?; database::DeleteQuery::new(FRIENDS_TABLE) .cond_user_id("ID_personne", user_two) .cond_user_id("ID_amis", user_one) .exec()?; Ok(()) } /// Count the number of friends of a user pub fn count_friends(user_id: &UserID) -> ResultBoxError { QueryInfo::new(FRIENDS_TABLE) .cond_user_id("ID_amis", user_id) .cond_u32("actif", 1) .exec_count() } /// Check if a user can create posts on another friend's page pub fn can_post_texts(user_id: &UserID, target_user: &UserID) -> ResultBoxError { QueryInfo::new(FRIENDS_TABLE) .cond_user_id("ID_personne", target_user) .cond_user_id("ID_amis", user_id) .add_field("autoriser_post_page") .query_row(|res| res.get_legacy_bool("autoriser_post_page")) .or(Ok(false)) } /// Check out whether a user is following another user or not pub fn is_following(user_id: &UserID, friend_id: &UserID) -> ResultBoxError { database::QueryInfo::new(FRIENDS_TABLE) .cond_user_id("ID_personne", user_id) .cond_user_id("ID_amis", friend_id) .cond_legacy_bool("actif", true) .cond_legacy_bool("abonnement", true) .exec_count() .map(|f| f > 0) } /// Update following status of a friendship pub fn set_following(user_id: &UserID, friend_id: &UserID, follow: bool) -> ResultBoxError { database::UpdateInfo::new(FRIENDS_TABLE) .cond_user_id("ID_personne", user_id) .cond_user_id("ID_amis", friend_id) .set_legacy_bool("abonnement", follow) .exec() } /// Get the status of a friendship pub fn get_status(user_id: &UserID, friend_id: &UserID) -> ResultBoxError { let mut status = FriendshipStatus { are_friend: false, sent_request: false, received_request: false, following: false, }; status.are_friend = are_friend(user_id, friend_id)?; match status.are_friend { false => { status.sent_request = sent_request(user_id, friend_id)?; status.received_request = sent_request(friend_id, user_id)?; } true => { status.following = is_following(user_id, friend_id)?; } } Ok(status) } /// Turn a database entry into a Friend structure fn db_to_friend(row: &database::RowResult) -> ResultBoxError { Ok(Friend { friend_id: row.get_user_id("ID_amis")?, accepted: row.get_legacy_bool("actif")?, following: row.get_legacy_bool("abonnement")?, last_activity_time: row.get_u64("last_activity")?, can_post_texts: row.get_legacy_bool("autoriser_post_page")?, }) }