mirror of
https://gitlab.com/comunic/comunicapiv3
synced 2024-11-22 21:39:21 +00:00
Start conversations system migration
This commit is contained in:
parent
cd5419edea
commit
60733f2d04
@ -5,31 +5,86 @@
|
|||||||
//! @author Pierre HUBERT
|
//! @author Pierre HUBERT
|
||||||
|
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
|
use serde_json::Value;
|
||||||
|
|
||||||
use crate::data::conversation_message::ConversationMessage;
|
use crate::data::conversation_message::{ConversationMessage, ConversationServerMessageType};
|
||||||
use crate::utils::user_data_utils::user_data_url;
|
use crate::utils::user_data_utils::user_data_url;
|
||||||
|
|
||||||
#[derive(Serialize)]
|
#[derive(Serialize)]
|
||||||
#[allow(non_snake_case)]
|
struct ConversationMessageFileAPI {
|
||||||
|
url: String,
|
||||||
|
size: u64,
|
||||||
|
name: String,
|
||||||
|
thumbnail: Option<String>,
|
||||||
|
r#type: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize)]
|
||||||
pub struct ConversationMessageAPI {
|
pub struct ConversationMessageAPI {
|
||||||
ID: u64,
|
id: u64,
|
||||||
convID: u64,
|
conv_id: u64,
|
||||||
ID_user: u64,
|
user_id: Option<u64>,
|
||||||
time_insert: u64,
|
time_insert: u64,
|
||||||
message: String,
|
message: Option<String>,
|
||||||
image_path: Option<String>,
|
file: Option<ConversationMessageFileAPI>,
|
||||||
|
server_message: Option<serde_json::Value>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ConversationMessageAPI {
|
impl ConversationMessageAPI {
|
||||||
/// Turn a conversation message into an API entry
|
/// Turn a conversation message into an API entry
|
||||||
pub fn new(msg: &ConversationMessage) -> ConversationMessageAPI {
|
pub fn new(msg: &ConversationMessage) -> ConversationMessageAPI {
|
||||||
|
let file = match &msg.file {
|
||||||
|
None => None,
|
||||||
|
Some(file) => Some(ConversationMessageFileAPI {
|
||||||
|
url: user_data_url(&file.path.clone()),
|
||||||
|
size: file.size,
|
||||||
|
name: file.name.clone(),
|
||||||
|
thumbnail: file.thumbnail.clone(),
|
||||||
|
r#type: file.r#type.clone(),
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
|
let server_message = match &msg.server_message {
|
||||||
|
None => None,
|
||||||
|
Some(msg) => {
|
||||||
|
let mut value = serde_json::Map::new();
|
||||||
|
|
||||||
|
match msg {
|
||||||
|
ConversationServerMessageType::UserCreatedConversation(user) => {
|
||||||
|
value.insert("type".to_string(), Value::from("user_created_conv"));
|
||||||
|
value.insert("user_id".to_string(), Value::from(user.id()));
|
||||||
|
}
|
||||||
|
|
||||||
|
ConversationServerMessageType::UserAddedAnotherUserToConversation(msg) => {
|
||||||
|
value.insert("type".to_string(), Value::from("user_added_another"));
|
||||||
|
value.insert("user_who_added".to_string(), Value::from(msg.user_who_added.id()));
|
||||||
|
value.insert("user_added".to_string(), Value::from(msg.user_added.id()));
|
||||||
|
}
|
||||||
|
|
||||||
|
ConversationServerMessageType::UserLeftConversation(u) => {
|
||||||
|
value.insert("type".to_string(), Value::from("user_left"));
|
||||||
|
value.insert("user_id".to_string(), Value::from(u.id()));
|
||||||
|
}
|
||||||
|
|
||||||
|
ConversationServerMessageType::UserRemovedFromConversation(msg) => {
|
||||||
|
value.insert("type".to_string(), Value::from("user_removed_another"));
|
||||||
|
value.insert("user_who_removed".to_string(), Value::from(msg.user_who_removed.id()));
|
||||||
|
value.insert("user_removed".to_string(), Value::from(msg.user_removed.id()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Some(serde_json::Value::Object(value))
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
ConversationMessageAPI {
|
ConversationMessageAPI {
|
||||||
ID: msg.id,
|
id: msg.id,
|
||||||
convID: msg.conv_id,
|
conv_id: msg.conv_id,
|
||||||
ID_user: msg.user_id.id(),
|
user_id: msg.user_id.clone().map(|u| u.id()),
|
||||||
time_insert: msg.time_sent,
|
time_insert: msg.time_sent,
|
||||||
message: msg.message.clone().unwrap_or(String::new()),
|
message: msg.message.clone(),
|
||||||
image_path: msg.image_path.as_ref().map(|f| user_data_url(f)),
|
file,
|
||||||
|
server_message,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -61,7 +61,7 @@ impl AccountExport {
|
|||||||
|
|
||||||
// Conversation messages
|
// Conversation messages
|
||||||
for (_, conv_messages) in &self.conversation_messages {
|
for (_, conv_messages) in &self.conversation_messages {
|
||||||
conv_messages.iter().for_each(|f| { set.insert(f.user_id.clone()); })
|
conv_messages.iter().for_each(|f| { set.extend(f.referenced_users_id()); })
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(set)
|
Ok(set)
|
||||||
|
@ -2,15 +2,141 @@
|
|||||||
//!
|
//!
|
||||||
//! Information about a single conversation message
|
//! Information about a single conversation message
|
||||||
|
|
||||||
|
use std::collections::HashSet;
|
||||||
|
|
||||||
|
use crate::data::error::{ExecError, Res};
|
||||||
use crate::data::user::UserID;
|
use crate::data::user::UserID;
|
||||||
|
|
||||||
|
pub type ConvMessageID = u64;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct ConversationMessageFile {
|
||||||
|
pub path: String,
|
||||||
|
pub size: u64,
|
||||||
|
pub name: String,
|
||||||
|
pub thumbnail: Option<String>,
|
||||||
|
pub r#type: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct UserAddedAnotherUserToConversation {
|
||||||
|
pub user_who_added: UserID,
|
||||||
|
pub user_added: UserID,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct UserRemovedAnotherUserToConversation {
|
||||||
|
pub user_who_removed: UserID,
|
||||||
|
pub user_removed: UserID,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum ConversationServerMessageType {
|
||||||
|
UserCreatedConversation(UserID),
|
||||||
|
UserAddedAnotherUserToConversation(UserAddedAnotherUserToConversation),
|
||||||
|
UserLeftConversation(UserID),
|
||||||
|
UserRemovedFromConversation(UserRemovedAnotherUserToConversation),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ConversationServerMessageType {
|
||||||
|
pub fn to_db(&self) -> String {
|
||||||
|
let info = match self {
|
||||||
|
ConversationServerMessageType::UserCreatedConversation(u) => ("user_created_conv", Some(u.clone()), None),
|
||||||
|
ConversationServerMessageType::UserAddedAnotherUserToConversation(msg) => ("user_added_another_user", Some(msg.user_who_added.clone()), Some(msg.user_added.clone())),
|
||||||
|
ConversationServerMessageType::UserLeftConversation(u) => ("user_left", Some(u.clone()), None),
|
||||||
|
ConversationServerMessageType::UserRemovedFromConversation(msg) => ("user_removed", Some(msg.user_who_removed.clone()), Some(msg.user_removed.clone())),
|
||||||
|
};
|
||||||
|
|
||||||
|
format!(
|
||||||
|
"{}-{}-{}",
|
||||||
|
info.0,
|
||||||
|
info.1.map(|u| u.id()).unwrap_or(0),
|
||||||
|
info.2.map(|u| u.id()).unwrap_or(0)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn from_db(str: &str) -> Res<Self> {
|
||||||
|
let split: Vec<&str> = str.split("-").collect();
|
||||||
|
|
||||||
|
if split.len() != 3 {
|
||||||
|
return Err(ExecError::boxed_new("Invalid ConversationSerMessageType"));
|
||||||
|
}
|
||||||
|
|
||||||
|
let id_1 = split[1].parse::<u64>()?;
|
||||||
|
let id_2 = split[2].parse::<u64>()?;
|
||||||
|
let info = (
|
||||||
|
split[0],
|
||||||
|
match id_1 {
|
||||||
|
0 => None,
|
||||||
|
id => Some(UserID::new(id))
|
||||||
|
},
|
||||||
|
match id_2 {
|
||||||
|
0 => None,
|
||||||
|
id => Some(UserID::new(id))
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
match info {
|
||||||
|
("user_created_conv", Some(user_id), _) => Ok(Self::UserCreatedConversation(user_id)),
|
||||||
|
|
||||||
|
("user_added_another_user", Some(user_id), Some(user_2)) => Ok(Self::UserAddedAnotherUserToConversation(UserAddedAnotherUserToConversation {
|
||||||
|
user_who_added: user_id,
|
||||||
|
user_added: user_2,
|
||||||
|
})),
|
||||||
|
|
||||||
|
("user_left", Some(user_id), _) => Ok(Self::UserLeftConversation(user_id)),
|
||||||
|
|
||||||
|
("user_removed", Some(user_id), Some(user_2)) => Ok(Self::UserRemovedFromConversation(UserRemovedAnotherUserToConversation {
|
||||||
|
user_who_removed: user_id,
|
||||||
|
user_removed: user_2,
|
||||||
|
})),
|
||||||
|
|
||||||
|
_ => Err(ExecError::boxed_new("Unknown server message type!"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Information about a single conversation message
|
/// Information about a single conversation message
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct ConversationMessage {
|
pub struct ConversationMessage {
|
||||||
pub id: u64,
|
pub id: ConvMessageID,
|
||||||
pub time_sent: u64,
|
pub time_sent: u64,
|
||||||
pub conv_id: u64,
|
pub conv_id: u64,
|
||||||
pub user_id: UserID,
|
pub user_id: Option<UserID>,
|
||||||
pub message: Option<String>,
|
pub message: Option<String>,
|
||||||
pub image_path: Option<String>,
|
pub server_message: Option<ConversationServerMessageType>,
|
||||||
|
pub file: Option<ConversationMessageFile>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ConversationMessage {
|
||||||
|
/// Get the entire list of referenced users in a conversation message
|
||||||
|
pub fn referenced_users_id(&self) -> HashSet<UserID> {
|
||||||
|
let mut users = HashSet::new();
|
||||||
|
|
||||||
|
if let Some(user_id) = &self.user_id {
|
||||||
|
users.insert(user_id.clone());
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(srv_msg) = &self.server_message {
|
||||||
|
match srv_msg {
|
||||||
|
ConversationServerMessageType::UserCreatedConversation(user) => {
|
||||||
|
users.insert(user.clone());
|
||||||
|
}
|
||||||
|
ConversationServerMessageType::UserAddedAnotherUserToConversation(msg) => {
|
||||||
|
users.insert(msg.user_who_added.clone());
|
||||||
|
users.insert(msg.user_added.clone());
|
||||||
|
}
|
||||||
|
|
||||||
|
ConversationServerMessageType::UserLeftConversation(user) => {
|
||||||
|
users.insert(user.clone());
|
||||||
|
}
|
||||||
|
ConversationServerMessageType::UserRemovedFromConversation(msg) => {
|
||||||
|
users.insert(msg.user_who_removed.clone());
|
||||||
|
users.insert(msg.user_removed.clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
users
|
||||||
|
}
|
||||||
}
|
}
|
@ -2,9 +2,9 @@
|
|||||||
//!
|
//!
|
||||||
//! @author Pierre Hubert
|
//! @author Pierre Hubert
|
||||||
|
|
||||||
use crate::constants::database_tables_names::{CONV_LIST_TABLE, CONV_MESSAGES_TABLE, CONV_MEMBERS_TABLE};
|
use crate::constants::database_tables_names::{CONV_LIST_TABLE, CONV_MEMBERS_TABLE, CONV_MESSAGES_TABLE};
|
||||||
use crate::data::conversation::Conversation;
|
use crate::data::conversation::Conversation;
|
||||||
use crate::data::conversation_message::ConversationMessage;
|
use crate::data::conversation_message::{ConversationMessage, ConversationMessageFile, ConversationServerMessageType};
|
||||||
use crate::data::error::{ExecError, Res, ResultBoxError};
|
use crate::data::error::{ExecError, Res, ResultBoxError};
|
||||||
use crate::data::new_conversation::NewConversation;
|
use crate::data::new_conversation::NewConversation;
|
||||||
use crate::data::new_conversation_message::NewConversationMessage;
|
use crate::data::new_conversation_message::NewConversationMessage;
|
||||||
@ -14,7 +14,7 @@ use crate::helpers::{database, events_helper};
|
|||||||
use crate::helpers::database::InsertQuery;
|
use crate::helpers::database::InsertQuery;
|
||||||
use crate::helpers::events_helper::Event;
|
use crate::helpers::events_helper::Event;
|
||||||
use crate::utils::date_utils::time;
|
use crate::utils::date_utils::time;
|
||||||
use crate::utils::user_data_utils::user_data_path;
|
use crate::utils::user_data_utils::delete_user_data_file_if_exists;
|
||||||
|
|
||||||
/// Create a new conversation. This method returns the ID of the created conversation
|
/// Create a new conversation. This method returns the ID of the created conversation
|
||||||
pub fn create(conv: &NewConversation) -> ResultBoxError<u64> {
|
pub fn create(conv: &NewConversation) -> ResultBoxError<u64> {
|
||||||
@ -377,11 +377,12 @@ pub fn update_message_content(msg_id: u64, new_content: &str) -> ResultBoxError<
|
|||||||
/// Remove a message from a conversation
|
/// Remove a message from a conversation
|
||||||
pub fn delete_message(msg: &ConversationMessage) -> ResultBoxError<()> {
|
pub fn delete_message(msg: &ConversationMessage) -> ResultBoxError<()> {
|
||||||
|
|
||||||
// Delete associated image (if any)
|
// Delete associated files
|
||||||
if let Some(img) = &msg.image_path {
|
if let Some(file) = &msg.file {
|
||||||
let path = user_data_path(img.as_ref());
|
delete_user_data_file_if_exists(&file.path)?;
|
||||||
if path.exists() {
|
|
||||||
std::fs::remove_file(path)?;
|
if let Some(thumb) = &file.thumbnail {
|
||||||
|
delete_user_data_file_if_exists(thumb)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -523,12 +524,39 @@ fn db_to_conversation_info(row: &database::RowResult) -> ResultBoxError<Conversa
|
|||||||
|
|
||||||
/// Turn a database entry into a ConversationMessgae object
|
/// Turn a database entry into a ConversationMessgae object
|
||||||
fn db_to_conversation_message(row: &database::RowResult) -> ResultBoxError<ConversationMessage> {
|
fn db_to_conversation_message(row: &database::RowResult) -> ResultBoxError<ConversationMessage> {
|
||||||
|
let user_id = match row.is_null("user_id")? {
|
||||||
|
true => None,
|
||||||
|
false => Some(row.get_user_id("user_id")?)
|
||||||
|
};
|
||||||
|
|
||||||
|
let file = match row.is_null_or_empty("filepath")? {
|
||||||
|
true => None,
|
||||||
|
false => Some(ConversationMessageFile {
|
||||||
|
path: row.get_str("filepath")?,
|
||||||
|
size: row.get_u64("file_size")?,
|
||||||
|
name: row.get_str("file_name")?,
|
||||||
|
thumbnail: row.get_optional_str("file_thumbnail")?,
|
||||||
|
r#type: row.get_str("file_type")?,
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
|
let server_message = match &user_id {
|
||||||
|
Some(_) => None,
|
||||||
|
None => Some(ConversationServerMessageType::from_db(&row.get_str("message")?)?)
|
||||||
|
};
|
||||||
|
|
||||||
|
let message = match server_message {
|
||||||
|
None => row.get_optional_str("message")?,
|
||||||
|
Some(_) => None,
|
||||||
|
};
|
||||||
|
|
||||||
Ok(ConversationMessage {
|
Ok(ConversationMessage {
|
||||||
id: row.get_u64("id")?,
|
id: row.get_u64("id")?,
|
||||||
time_sent: row.get_u64("time_insert")?,
|
time_sent: row.get_u64("time_sent")?,
|
||||||
conv_id: row.get_u64("conv_id")?,
|
conv_id: row.get_u64("conv_id")?,
|
||||||
user_id: row.get_user_id("user_id")?,
|
user_id,
|
||||||
message: row.get_optional_str("message")?,
|
message,
|
||||||
image_path: row.get_optional_str("image_path")?,
|
server_message,
|
||||||
|
file,
|
||||||
})
|
})
|
||||||
}
|
}
|
@ -380,6 +380,15 @@ impl<'a> RowResult<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Check out whether a given value is null or empty or not
|
||||||
|
pub fn is_null_or_empty(&self, name: &str) -> ResultBoxError<bool> {
|
||||||
|
if self.is_null(name)? {
|
||||||
|
return Ok(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(self.get_str(name)?.is_empty())
|
||||||
|
}
|
||||||
|
|
||||||
/// Get an optional string => Set to None if string is null / empty
|
/// Get an optional string => Set to None if string is null / empty
|
||||||
pub fn get_optional_str(&self, name: &str) -> ResultBoxError<Option<String>> {
|
pub fn get_optional_str(&self, name: &str) -> ResultBoxError<Option<String>> {
|
||||||
match self.is_null(name)? {
|
match self.is_null(name)? {
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
use comunic_server::{cleanup_thread, server};
|
use comunic_server::{cleanup_thread, server};
|
||||||
|
use comunic_server::api_data::conversation_message_api::ConversationMessageAPI;
|
||||||
use comunic_server::data::config::{conf, Config};
|
use comunic_server::data::config::{conf, Config};
|
||||||
use comunic_server::helpers::database;
|
use comunic_server::helpers::{conversations_helper, database};
|
||||||
|
|
||||||
#[actix_rt::main]
|
#[actix_rt::main]
|
||||||
async fn main() -> std::io::Result<()> {
|
async fn main() -> std::io::Result<()> {
|
||||||
@ -18,6 +19,10 @@ async fn main() -> std::io::Result<()> {
|
|||||||
// Start cleanup thread
|
// Start cleanup thread
|
||||||
cleanup_thread::start().expect("Failed to start cleanup thread!");
|
cleanup_thread::start().expect("Failed to start cleanup thread!");
|
||||||
|
|
||||||
|
let msg = conversations_helper::get_last_messages(120, 100).unwrap();
|
||||||
|
println!("{:#?}", msg);
|
||||||
|
println!("{:#?}", serde_json::to_string(&ConversationMessageAPI::for_list(&msg)));
|
||||||
|
|
||||||
// Start the server
|
// Start the server
|
||||||
server::start_server(conf()).await
|
server::start_server(conf()).await
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,7 @@ use std::path::{Path, PathBuf};
|
|||||||
use serde_json::to_string;
|
use serde_json::to_string;
|
||||||
|
|
||||||
use crate::data::config::conf;
|
use crate::data::config::conf;
|
||||||
use crate::data::error::{ExecError, ResultBoxError};
|
use crate::data::error::{ExecError, Res, ResultBoxError};
|
||||||
use crate::data::user::UserID;
|
use crate::data::user::UserID;
|
||||||
use crate::utils::crypt_utils::rand_str;
|
use crate::utils::crypt_utils::rand_str;
|
||||||
|
|
||||||
@ -62,3 +62,12 @@ pub fn generate_new_user_data_file_name(dir: &Path, ext: &str) -> ResultBoxError
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Delete a file from user data, if it exists
|
||||||
|
pub fn delete_user_data_file_if_exists(path: &str) -> Res {
|
||||||
|
let path = user_data_path(path.as_ref());
|
||||||
|
if path.exists() {
|
||||||
|
std::fs::remove_file(path)?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user