//! # Posts helper //! //! @author Pierre Hubert use crate::constants::database_tables_names::POSTS_TABLE; use crate::data::error::{ExecError, ResultBoxError}; use crate::data::post::{Post, PostFile, PostKind, PostPageKind, PostVisibilityLevel}; use crate::data::post::PostKind::POST_KIND_IMAGE; use crate::data::user::UserID; use crate::helpers::{database, friends_helper}; use crate::utils::date_utils::time; impl PostVisibilityLevel { pub fn to_db(&self) -> u32 { match self { PostVisibilityLevel::VISIBILITY_PUBLIC => 1, PostVisibilityLevel::VISIBILITY_FRIENDS => 2, PostVisibilityLevel::VISIBILITY_USER => 3, PostVisibilityLevel::VISIBILITY_GROUP_MEMBERS => 50, } } pub fn from_db(val: u32) -> PostVisibilityLevel { match val { 1 => PostVisibilityLevel::VISIBILITY_PUBLIC, 2 => PostVisibilityLevel::VISIBILITY_FRIENDS, 3 => PostVisibilityLevel::VISIBILITY_USER, 50 => PostVisibilityLevel::VISIBILITY_GROUP_MEMBERS, _ => PostVisibilityLevel::VISIBILITY_PUBLIC, } } } pub struct PostsQuery { /// The ID of the user making the request user_id: Option, /// Maximum number of posts to get limit: u64, /// Starting post start_from: u64, } impl PostsQuery { /// Construct a new request pub fn new(user_id: Option) -> PostsQuery { PostsQuery { user_id, limit: 10, start_from: 0, } } /// Start starting point pub fn set_start_from(mut self, start_from: u64) -> PostsQuery { self.start_from = start_from; self } /// Set the limit for this query pub fn set_limit(mut self, limit: u64) -> PostsQuery { self.limit = limit; self } /// Get the posts of a user pub fn get_user(self, user_id: &UserID) -> ResultBoxError> { get_user(&self, user_id) } } /// Get the posts of `target_id` fn get_user(query: &PostsQuery, target_id: &UserID) -> ResultBoxError> { // Max user visibility let mut level = PostVisibilityLevel::VISIBILITY_PUBLIC; if let Some(user_id) = &query.user_id { if user_id == target_id { level = PostVisibilityLevel::VISIBILITY_USER; } else if friends_helper::are_friend(user_id, target_id)? { level = PostVisibilityLevel::VISIBILITY_FRIENDS; } } // Start request let mut db_query = database::QueryInfo::new(POSTS_TABLE); let mut custom_where = String::new(); // Preprocess conditions // ============= PERMISSION CONDITIONS ================= custom_where.push_str("((niveau_visibilite <= ?) "); db_query = db_query.add_custom_where_argument_u32(level.to_db()); // Add user posts (if signed in) if let Some(user_id) = &query.user_id { custom_where.push_str(" OR (ID_amis = ?) "); db_query = db_query.add_custom_where_argument_user_id(user_id); } custom_where.push_str(")"); // ============= /PERMISSION CONDITIONS ================= // ============== START POINT CONDITION ================= if query.start_from != 0 { custom_where.push_str(" AND ID <= ?"); db_query = db_query.add_custom_where_argument_u64(query.start_from); } // ============== /START POINT CONDITION ================ // Perform the request db_query .cond_user_id("ID_personne", target_id) .cond_u64("group_id", 0) .set_custom_where(&custom_where) .set_order("ID DESC") .set_limit(query.limit) .exec(db_to_post) } /// Turn a post into a database entry fn db_to_post(res: &database::RowResult) -> ResultBoxError { let user_id = if res.get_u64("ID_amis")? == 0 { res.get_user_id("ID_personne") } else { res.get_user_id("ID_amis") }?; let target_page = if res.get_u64("group_id")? == 0 { PostPageKind::PAGE_KIND_USER(res.get_user_id("ID_personne")?) } else { PostPageKind::PAGE_KIND_GROUP(res.get_group_id("group_id")?) }; let file = match res.get_optional_str("path")? { None => None, Some(path) => Some(PostFile { path, size: res.get_usize("size").unwrap_or(0), file_type: res.get_optional_str("file_type")?, }), }; let mut post = Post { // General information id: res.get_u64("ID")?, user_id: user_id.clone(), time_create: res.get_u64("time_insert").unwrap_or(time()), target_page, content: res.get_optional_str("texte")?, visibility: PostVisibilityLevel::from_db(res.get_u32("niveau_visibilite")?), kind: PostKind::POST_KIND_TEXT, }; let file = file.ok_or(ExecError::new("A file is required with this post type!")); match res.get_str("type")?.as_str() { "image" => post.kind = POST_KIND_IMAGE(file?), _ => {} } Ok(post) }