2024-12-14 12:53:44 -08:00
|
|
|
use std::error::Error;
|
2024-12-08 21:12:17 -08:00
|
|
|
use microrm::prelude::*;
|
|
|
|
|
use microrm::Stored;
|
2024-12-14 12:53:44 -08:00
|
|
|
|
|
|
|
|
use crate::models::participant::ParticipantID;
|
|
|
|
|
use crate::models::{
|
|
|
|
|
participant::Participant,
|
|
|
|
|
conversation::{
|
|
|
|
|
self, Conversation, ConversationID, PendingConversation
|
|
|
|
|
}
|
|
|
|
|
};
|
2024-12-08 21:12:17 -08:00
|
|
|
|
|
|
|
|
pub struct ChatDatabase {
|
|
|
|
|
db: DB,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(Database)]
|
|
|
|
|
struct DB {
|
|
|
|
|
conversations: microrm::IDMap<Conversation>,
|
2024-12-14 12:53:44 -08:00
|
|
|
participants: microrm::IDMap<Participant>,
|
2024-12-08 21:12:17 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl ChatDatabase {
|
|
|
|
|
pub fn new_in_memory() -> Result<Self, Box<dyn Error + Send + Sync>> {
|
|
|
|
|
let db = DB::open_path(":memory:")?;
|
|
|
|
|
return Ok(Self {
|
|
|
|
|
db: db,
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
2024-12-14 12:53:44 -08:00
|
|
|
pub fn insert_conversation(&self, conversation: PendingConversation) -> Result<ConversationID, microrm::Error> {
|
2024-12-08 21:12:17 -08:00
|
|
|
// First see if conversation guid already exists, update it if so
|
2024-12-14 12:53:44 -08:00
|
|
|
let guid = conversation.guid();
|
|
|
|
|
let mut existing = self.stored_conversation_by_guid(guid)?;
|
2024-12-08 21:12:17 -08:00
|
|
|
|
2024-12-14 12:53:44 -08:00
|
|
|
if let Some(existing) = existing.as_mut() {
|
|
|
|
|
conversation.update(existing);
|
2024-12-08 21:12:17 -08:00
|
|
|
existing.sync();
|
|
|
|
|
return Ok(existing.id());
|
|
|
|
|
} else {
|
|
|
|
|
// Otherwise, insert.
|
2024-12-14 12:53:44 -08:00
|
|
|
let inserted = self.db.conversations.insert_and_return(conversation.get_conversation())?;
|
|
|
|
|
|
|
|
|
|
// Insert participants
|
|
|
|
|
let participants = conversation.get_participants();
|
|
|
|
|
let inserted_participants = participants.iter()
|
|
|
|
|
.map(|p| self.db.participants.insert(p.clone()).unwrap())
|
|
|
|
|
.collect::<Vec<_>>();
|
|
|
|
|
inserted.connect_participants(inserted_participants);
|
|
|
|
|
|
|
|
|
|
return Ok(inserted.id());
|
2024-12-08 21:12:17 -08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn get_conversation_by_id(&self, id: ConversationID) -> Result<Option<Conversation>, microrm::Error> {
|
|
|
|
|
self.db.conversations
|
|
|
|
|
.by_id(id)
|
|
|
|
|
.map(|stored_conversation| stored_conversation
|
|
|
|
|
.map(|stored| stored.wrapped())
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn get_conversation_by_guid(&self, guid: &str) -> Result<Option<Conversation>, microrm::Error> {
|
|
|
|
|
self.db.conversations
|
|
|
|
|
.with(Conversation::Guid, guid)
|
|
|
|
|
.get()
|
|
|
|
|
.and_then(|v| Ok(v
|
|
|
|
|
.into_iter()
|
|
|
|
|
.map(|c| c.wrapped())
|
|
|
|
|
.last()
|
|
|
|
|
))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn all_conversations(&self) -> Result<Vec<Conversation>, microrm::Error> {
|
|
|
|
|
self.db.conversations
|
|
|
|
|
.get()
|
|
|
|
|
.map(|v| v
|
|
|
|
|
.into_iter()
|
|
|
|
|
.map(|c| c.wrapped())
|
|
|
|
|
.collect()
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
2024-12-14 12:53:44 -08:00
|
|
|
fn upsert_participants(&self, participants: Vec<Participant>) -> Vec<ParticipantID> {
|
|
|
|
|
// Filter existing participants and add to result
|
|
|
|
|
let existing_participants = participants.iter()
|
|
|
|
|
.filter_map(|p| self.db.participants
|
|
|
|
|
.with(Participant::DisplayName, &p.display_name)
|
|
|
|
|
.get()
|
|
|
|
|
.ok()
|
|
|
|
|
.and_then(|v| v
|
|
|
|
|
.into_iter()
|
|
|
|
|
.last()
|
|
|
|
|
.map(|p| p.id())
|
|
|
|
|
)
|
|
|
|
|
)
|
|
|
|
|
.collect::<Vec<_>>();
|
|
|
|
|
|
|
|
|
|
participants.iter()
|
|
|
|
|
.map(|p| self.db.participants.insert(p.clone()).unwrap())
|
|
|
|
|
.collect()
|
|
|
|
|
}
|
|
|
|
|
|
2024-12-08 21:12:17 -08:00
|
|
|
fn stored_conversation_by_guid(&self, guid: &str) -> Result<Option<Stored<Conversation>>, microrm::Error> {
|
|
|
|
|
self.db.conversations
|
|
|
|
|
.with(Conversation::Guid, guid)
|
|
|
|
|
.get()
|
|
|
|
|
.map(|v| v
|
|
|
|
|
.into_iter()
|
|
|
|
|
.last()
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
}
|