db/herodb/src/models/mcc/message.rs
2025-04-04 13:17:40 +02:00

134 lines
4.0 KiB
Rust

use serde::{Deserialize, Serialize};
use crate::db::{SledModel, Storable, SledDB, SledDBResult};
use chrono::{DateTime, Utc};
/// MessageStatus represents the status of a message
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum MessageStatus {
Sent,
Delivered,
Read,
Failed,
}
/// MessageMeta contains metadata for a chat message
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct MessageMeta {
pub created_at: DateTime<Utc>,
pub updated_at: DateTime<Utc>,
pub status: MessageStatus,
pub is_edited: bool,
pub reactions: Vec<String>,
}
/// Message represents a chat message
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Message {
pub id: u32, // Unique identifier
pub thread_id: String, // Thread/conversation identifier
pub sender_id: String, // Sender identifier
pub recipients: Vec<String>, // List of recipient identifiers
pub content: String, // Message content
pub attachments: Vec<String>, // References to attachments
pub groups: Vec<u32>, // Groups this message belongs to (references Circle IDs)
pub meta: MessageMeta, // Message metadata
}
impl Message {
/// Create a new message
pub fn new(id: u32, thread_id: String, sender_id: String, content: String) -> Self {
let now = Utc::now();
Self {
id,
thread_id,
sender_id,
recipients: Vec::new(),
content,
attachments: Vec::new(),
groups: Vec::new(),
meta: MessageMeta {
created_at: now,
updated_at: now,
status: MessageStatus::Sent,
is_edited: false,
reactions: Vec::new(),
},
}
}
/// Add a recipient to this message
pub fn add_recipient(&mut self, recipient: String) {
self.recipients.push(recipient);
}
/// Add an attachment to this message
pub fn add_attachment(&mut self, attachment: String) {
self.attachments.push(attachment);
}
/// Add a group to this message
pub fn add_group(&mut self, group_id: u32) {
if !self.groups.contains(&group_id) {
self.groups.push(group_id);
}
}
/// Remove a group from this message
pub fn remove_group(&mut self, group_id: u32) {
self.groups.retain(|&id| id != group_id);
}
/// Filter by groups - returns true if this message belongs to any of the specified groups
pub fn filter_by_groups(&self, groups: &[u32]) -> bool {
groups.iter().any(|g| self.groups.contains(g))
}
/// Search by content - returns true if the content contains the query (case-insensitive)
pub fn search_by_content(&self, query: &str) -> bool {
self.content.to_lowercase().contains(&query.to_lowercase())
}
/// Update message status
pub fn update_status(&mut self, status: MessageStatus) {
self.meta.status = status;
self.meta.updated_at = Utc::now();
}
/// Edit message content
pub fn edit_content(&mut self, new_content: String) {
self.content = new_content;
self.meta.is_edited = true;
self.meta.updated_at = Utc::now();
}
/// Add a reaction to the message
pub fn add_reaction(&mut self, reaction: String) {
self.meta.reactions.push(reaction);
self.meta.updated_at = Utc::now();
}
/// Get all messages in the same thread
pub fn get_thread_messages(&self, db: &SledDB<Message>) -> SledDBResult<Vec<Message>> {
let all_messages = db.list()?;
let thread_messages = all_messages
.into_iter()
.filter(|msg| msg.thread_id == self.thread_id)
.collect();
Ok(thread_messages)
}
}
// Implement Storable trait (provides default dump/load)
impl Storable for Message {}
// Implement SledModel trait
impl SledModel for Message {
fn get_id(&self) -> String {
self.id.to_string()
}
fn db_prefix() -> &'static str {
"message"
}
}