added chat types from chat-service

This commit is contained in:
Franklin 2023-01-28 23:13:49 -04:00
parent 1b8cd0a46a
commit 19c4567323
7 changed files with 1434 additions and 41 deletions

1246
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -3,9 +3,10 @@ name = "chat-types"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[lib]
[dependencies]
serde = { version = "1.0", features = ["derive"] }
chrono = { version = "0.4", features = [ "serde" ] }
sqlx = { version = "0.6.0", features = [ "runtime-tokio-rustls", "mysql", "chrono", "decimal", "offline" ] }
serde_json = { version = "1" }

160
src/domain/chat_message.rs Normal file
View File

@ -0,0 +1,160 @@
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use sqlx::{
mysql::{MySqlTypeInfo, MySqlValueRef},
FromRow, MySql,
};
/// Used for Both registering delivered and seen time in messages.
/// The reasoning for this is that a chatroom can have many users
/// and the backend needs to be able to tell when each of them
/// has seen this message.
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
pub struct TimeSensitiveAction {
pub time: DateTime<Utc>,
pub by: u32,
}
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
pub struct TimeSensitiveActionVec {
pub list: Vec<TimeSensitiveAction>,
}
impl sqlx::Type<MySql> for TimeSensitiveActionVec {
fn type_info() -> MySqlTypeInfo {
<str as sqlx::Type<MySql>>::type_info()
}
}
impl sqlx::Encode<'_, MySql> for TimeSensitiveActionVec {
fn encode_by_ref(&self, buf: &mut Vec<u8>) -> sqlx::encode::IsNull {
let json_str = serde_json::to_string(self).unwrap();
<&str as sqlx::Encode<MySql>>::encode(&json_str, buf)
}
}
impl sqlx::Decode<'_, MySql> for TimeSensitiveActionVec {
fn decode(value: MySqlValueRef<'_>) -> Result<Self, sqlx::error::BoxDynError> {
match <&str as sqlx::Decode<MySql>>::decode(value).map(ToOwned::to_owned) {
Ok(json_str) => match serde_json::from_str(json_str.as_str()) {
Ok(time_sensitive_action) => Ok(time_sensitive_action),
Err(error) => Err(Box::new(error)),
},
Err(error) => Err(error),
}
}
}
impl TimeSensitiveAction {
pub fn new(by: u32) -> Self {
Self {
time: Utc::now(),
by,
}
}
}
/// Base message for chat rooms.
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, FromRow)]
pub struct ChatMessage {
pub id: u32,
/// User id
#[serde(rename = "fromId")]
pub from_id: u32,
/// ChatRoom id (Not a user id)
#[serde(rename = "toId")]
pub to_id: u32,
pub message: ChatMessageContent,
/// This must always be there. Since its created.
#[serde(rename = "timeSent")]
pub time_sent: DateTime<Utc>,
/// This is a Vec because there can be many recipients.
#[serde(rename = "timeDelivered")]
pub time_delivered: TimeSensitiveActionVec,
/// This is a Vec because there can be many recipients.
#[serde(rename = "timeSeen")]
pub time_seen: TimeSensitiveActionVec,
}
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
pub enum ChatMessageContent {
Text(String),
Image(Vec<u8>),
Video(Vec<u8>),
Audio(Vec<u8>),
}
impl sqlx::Type<MySql> for ChatMessageContent {
fn type_info() -> MySqlTypeInfo {
<str as sqlx::Type<MySql>>::type_info()
}
}
impl sqlx::Encode<'_, MySql> for ChatMessageContent {
fn encode_by_ref(&self, buf: &mut Vec<u8>) -> sqlx::encode::IsNull {
let json_str = serde_json::to_string(self).unwrap();
<&str as sqlx::Encode<MySql>>::encode(&json_str, buf)
}
}
impl sqlx::Decode<'_, MySql> for ChatMessageContent {
fn decode(value: MySqlValueRef<'_>) -> Result<Self, sqlx::error::BoxDynError> {
match <&str as sqlx::Decode<MySql>>::decode(value).map(ToOwned::to_owned) {
Ok(json_str) => match serde_json::from_str(json_str.as_str()) {
Ok(time_sensitive_action) => Ok(time_sensitive_action),
Err(error) => Err(Box::new(error)),
},
Err(error) => Err(error),
}
}
}
pub trait ChatSendable {
/// Creates a new message, automatically sets the time that the message was sent to the current time in UTC.
fn new(from: u32, message: ChatMessageSender) -> Self;
/// Sets the time that the message was delivered to the current time in UTC.
fn delivered(&mut self, by: u32);
/// Sets the time that the message was seen to the current time in UTC.
fn seen(&mut self, by: u32);
/// This returns the content of a given message, the backend might need this in the future.
fn get_content(&self) -> &ChatMessageContent;
}
impl ChatSendable for ChatMessage {
fn new(from_id: u32, message: ChatMessageSender) -> Self {
Self {
id: 0, //TODO: Assign a random number
from_id,
to_id: message.to,
message: message.message,
time_sent: Utc::now(),
time_delivered: TimeSensitiveActionVec { list: Vec::new() },
time_seen: TimeSensitiveActionVec { list: Vec::new() },
}
}
fn delivered(&mut self, by: u32) {
self.time_delivered.list.push(TimeSensitiveAction::new(by));
}
fn seen(&mut self, by: u32) {
self.time_seen.list.push(TimeSensitiveAction::new(by));
}
fn get_content(&self) -> &ChatMessageContent {
&self.message
}
}
/// This is what clients use to send messages (DTO)
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
pub struct ChatMessageSender {
pub message: ChatMessageContent,
pub to: u32,
}
/// This is what should be sent across the broadcast channels
/// All of them use the same object so that the client can just replace its own
/// Copy of it with the server's authority.
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
pub enum BroadcastMessage {
NewMessageRequest(ChatMessageSender),
NewMessage(ChatMessage),
DeliveredUpdate(ChatMessage),
SeenUpdate(ChatMessage),
}

View File

@ -0,0 +1,9 @@
use chrono::{DateTime, Utc};
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub enum ChatMessageUpdate {
/// User id that got the message delivered to, and the time it was delivered.
Delivered(u32, DateTime<Utc>),
/// User id that saw the message, and the time it was seen.
Seen(u32, DateTime<Utc>),
}

14
src/domain/chat_room.rs Normal file
View File

@ -0,0 +1,14 @@
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq, PartialOrd, Ord, Default)]
pub struct ChatRoom {
pub id: u32,
pub title: String,
#[serde(rename = "ownerId")]
pub owner_id: u32,
#[serde(rename = "timeCreated")]
pub time_created: DateTime<Utc>,
#[serde(rename = "lastUpdated")]
pub last_updated: DateTime<Utc>,
}

3
src/domain/mod.rs Normal file
View File

@ -0,0 +1,3 @@
pub mod chat_message;
pub mod chat_message_update;
pub mod chat_room;

View File

@ -1,39 +1 @@
use chrono::{DateTime, Utc};
use serde::{Serialize, Deserialize};
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct Message {
pub id: String,
pub text: String,
pub sender: User,
pub recipient: Room,
pub time_sent: DateTime<Utc>,
pub time_recieved: DateTime<Utc>,
}
#[derive(Serialize, Deserialize, Debug, Clone, Default)]
pub struct Room {
pub id: String,
pub title: String,
pub description: String,
pub time_created: DateTime<Utc>,
pub members: Vec<String>,
pub messages: Vec<String>,
}
/// A user for chats, mainly used for authentication
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct User {
pub id: String,
pub name: String,
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct KeySet {
pub private: String,
pub public: String
}
pub struct Platform {
pub id: String,
}
pub mod domain;