use std::{cell::RefCell, str::FromStr, sync::Mutex}; use sled::Db; use crate::{ channels::ChannelReference, discord::{self, forward_to_discord}, matrix::{self, forward_to_matrix}, messages::{MessageReference, SentMessage}, }; pub struct Bridgers { pub db: Db, pub discord: Mutex>>, pub matrix: Mutex>>, } impl Bridgers { pub fn new() -> Self { let db = sled::open("data/phoebe.sled").expect("Failed to open database"); Self { db, discord: Mutex::new(RefCell::new(None)), matrix: Mutex::new(RefCell::new(None)), } } fn get_linked_discord_channel(&self, source: &MessageReference) -> Option { let discord_channels = self .db .open_tree("discord_channels") .expect("Failed to open discord channels tree"); match source { MessageReference::Matrix(room_id, _) => { let channel_ref = ChannelReference::Matrix(room_id.to_string()); let channel_ref = bincode::serialize(&channel_ref).unwrap(); discord_channels .get(channel_ref) .unwrap() .map(|bytes| bincode::deserialize::(&bytes).unwrap()) .map(discord::ChannelId) } _ => None, } } fn get_linked_matrix_room(&self, source: &MessageReference) -> Option { let matrix_channels = self .db .open_tree("matrix_channels") .expect("Failed to open matrix channels tree"); match source { MessageReference::Discord(channel_id, _) => { let channel_ref = ChannelReference::Discord(*channel_id); let channel_ref = bincode::serialize(&channel_ref).unwrap(); matrix_channels .get(channel_ref) .unwrap() .map(|bytes| bincode::deserialize::(&bytes).unwrap()) .as_deref() .map(matrix::RoomId::from_str) .map(Result::unwrap) } _ => None, } } pub fn link_channels(&self, channels: &[ChannelReference]) { let discord_channels = self .db .open_tree("discord_channels") .expect("Failed to open discord channels tree"); let matrix_channels = self .db .open_tree("matrix_channels") .expect("Failed to open matrix channels tree"); for channel in channels.iter() { let other_channels = channels .iter() .filter(|r| r != &channel) .collect::>(); match channel { ChannelReference::Discord(channel_id) => { for other_channel in other_channels { let key = bincode::serialize(other_channel).unwrap(); let value = bincode::serialize(channel_id).unwrap(); discord_channels.insert(key, value).unwrap(); } } ChannelReference::Matrix(room_id) => { for other_channel in other_channels { let key = bincode::serialize(other_channel).unwrap(); let value = bincode::serialize(room_id.as_str()).unwrap(); matrix_channels.insert(key, value).unwrap(); } } } } } pub async fn send_message(&self, message: SentMessage) -> Vec { let mut related_messages = vec![message.source.clone()]; if let Some(discord) = self.discord.lock().unwrap().borrow().as_ref() { if let Some(channel) = self.get_linked_discord_channel(&message.source) { if let Some(m) = forward_to_discord(discord, channel, &message).await { related_messages.push(m); } } } if let Some(matrix) = self.matrix.lock().unwrap().borrow().as_ref() { if let Some(room_id) = self.get_linked_matrix_room(&message.source) { if let Some(m) = forward_to_matrix(matrix, room_id, &message).await { related_messages.push(m); } } } let tree = self .db .open_tree("message_relations") .expect("Failed to open relations tree"); for source in related_messages.iter() { let relations = related_messages .iter() .filter(|r| r != &source) .collect::>(); tree.insert( bincode::serialize(source).expect("Failed to serialize message reference"), bincode::serialize(&relations).expect("Failed to serialize message relations"), ) .expect("Failed to store message relations"); } related_messages } }