use crate::models::participant::Participant; use chrono::{DateTime, NaiveDateTime}; use kordophone::model::message::AttachmentMetadata; use kordophone::model::outgoing_message::OutgoingMessage; use std::collections::HashMap; use uuid::Uuid; #[derive(Clone, Debug)] pub struct Message { pub id: String, pub sender: Participant, pub text: String, pub date: NaiveDateTime, pub file_transfer_guids: Vec, pub attachment_metadata: Option>, } impl Message { pub fn builder() -> MessageBuilder { MessageBuilder::new() } } impl From for Message { fn from(value: kordophone::model::Message) -> Self { let sender_participant = match value.sender { Some(sender) => Participant::Remote { contact_id: None, // Weird server quirk: some sender handles are encoded with control characters. handle: sender .chars() .filter(|c| { !c.is_control() && !matches!( c, '\u{202A}' | // LRE '\u{202B}' | // RLE '\u{202C}' | // PDF '\u{202D}' | // LRO '\u{202E}' | // RLO '\u{2066}' | // LRI '\u{2067}' | // RLI '\u{2068}' | // FSI '\u{2069}' // PDI ) }) .collect::(), }, None => Participant::Me, }; Self { id: value.guid, sender: sender_participant, text: value.text, date: DateTime::from_timestamp( value.date.unix_timestamp(), value.date.unix_timestamp_nanos().try_into().unwrap_or(0), ) .unwrap() .naive_local(), file_transfer_guids: value.file_transfer_guids, attachment_metadata: value.attachment_metadata, } } } impl From<&OutgoingMessage> for Message { fn from(value: &OutgoingMessage) -> Self { Self { id: value.guid.to_string(), sender: Participant::Me, text: value.text.clone(), date: value.date, file_transfer_guids: Vec::new(), // Outgoing messages don't have file transfer GUIDs initially attachment_metadata: None, // Outgoing messages don't have attachment metadata initially } } } pub struct MessageBuilder { id: Option, sender: Option, text: Option, date: Option, file_transfer_guids: Option>, attachment_metadata: Option>, } impl Default for MessageBuilder { fn default() -> Self { Self::new() } } impl MessageBuilder { pub fn new() -> Self { Self { id: None, sender: None, text: None, date: None, file_transfer_guids: None, attachment_metadata: None, } } pub fn sender(mut self, sender: Participant) -> Self { self.sender = Some(sender); self } pub fn text(mut self, text: String) -> Self { self.text = Some(text); self } pub fn date(mut self, date: NaiveDateTime) -> Self { self.date = Some(date); self } pub fn file_transfer_guids(mut self, file_transfer_guids: Vec) -> Self { self.file_transfer_guids = Some(file_transfer_guids); self } pub fn attachment_metadata( mut self, attachment_metadata: HashMap, ) -> Self { self.attachment_metadata = Some(attachment_metadata); self } pub fn build(self) -> Message { Message { id: self.id.unwrap_or_else(|| Uuid::new_v4().to_string()), sender: self.sender.unwrap_or(Participant::Me), text: self.text.unwrap_or_default(), date: self.date.unwrap_or_else(|| chrono::Utc::now().naive_utc()), file_transfer_guids: self.file_transfer_guids.unwrap_or_default(), attachment_metadata: self.attachment_metadata, } } }