char/phoebe
git clone https://git.t4t.associates/char/phoebe
e0731c2
legacy
1use std::{ cell:: RefCell , collections:: HashSet , str:: FromStr , sync:: Mutex }; 2 3use sled:: Db ; 4 5use crate ::{ 6 channels:: ChannelReference , 7 discord::{ 8self , delete_on_discord, edit_on_discord, forward_image_to_discord, forward_to_discord, 9}, 10 matrix::{ self , delete_on_matrix, edit_on_matrix, forward_image_to_matrix, forward_to_matrix}, 11 messages::{ DeletedMessage , EditedMessage , MessageReference , SentImageMessage , SentMessage }, 12}; 13 14pub struct Bridgers { 15pub db : Db , 16pub discord : Mutex < RefCell < Option < discord:: Context >>>, 17pub matrix : Mutex < RefCell < Option < matrix:: Client >>>, 18} 19 20impl Bridgers { 21pub fn new () ->Self { 22let db = sled:: open ( "data/phoebe.sled" ). expect ( "Failed to open database" ); 23 24Self { 25 db, 26discord : Mutex :: new ( RefCell :: new ( None )), 27matrix : Mutex :: new ( RefCell :: new ( None )), 28} 29} 30 31fn get_linked_discord_channel ( & self , source : & MessageReference ) ->Option < discord:: ChannelId > { 32let discord_channels =self 33. db 34. open_tree ( "discord_channels" ) 35. expect ( "Failed to open discord channels tree" ); 36 37match source{ 38MessageReference :: Matrix ( room_id, _) =>{ 39let channel_ref =ChannelReference :: Matrix ( room_id. to_string ()); 40let channel_ref = bincode:: serialize ( & channel_ref). unwrap (); 41 42 discord_channels 43. get ( channel_ref) 44. unwrap () 45. map ( |bytes| bincode:: deserialize ::< u64 >( & bytes). unwrap ()) 46. map ( discord:: ChannelId ) 47} 48 _ =>None , 49} 50} 51 52fn get_linked_matrix_room ( & self , source : & MessageReference ) ->Option < matrix:: RoomId > { 53let matrix_channels =self 54. db 55. open_tree ( "matrix_channels" ) 56. expect ( "Failed to open matrix channels tree" ); 57 58match source{ 59MessageReference :: Discord ( channel_id, _) =>{ 60let channel_ref =ChannelReference :: Discord ( * channel_id); 61let channel_ref = bincode:: serialize ( & channel_ref). unwrap (); 62 63 matrix_channels 64. get ( channel_ref) 65. unwrap () 66. map ( |bytes| bincode:: deserialize ::< String >( & bytes). unwrap ()) 67. as_deref () 68. map ( matrix:: RoomId :: from_str) 69. map ( Result :: unwrap) 70} 71 _ =>None , 72} 73} 74 75fn get_related_messages ( & self , source : & MessageReference ) ->Option < Vec < MessageReference >> { 76let message_relations =self 77. db 78. open_tree ( "message_relations" ) 79. expect ( "Failed to open relations tree" ); 80 81let key = bincode:: serialize ( source). expect ( "Failed to serialize message reference" ); 82 message_relations 83. get ( key) 84. expect ( "Failed to retrieve message references" ) 85. map ( |r|{ 86 bincode:: deserialize ::< Vec < MessageReference >>( & r) 87. expect ( "Failed to deserialize message references" ) 88}) 89} 90 91fn get_related_discord_message ( & self , source : & MessageReference ) ->Option <( u64 , u64 )> { 92if let MessageReference :: Discord ( channel_id, message_id) = source{ 93return Some (( * channel_id, * message_id)); 94} 95 96if let Some ( relations) =self . get_related_messages ( source) { 97for relationin relations{ 98if let MessageReference :: Discord ( channel_id, message_id) = relation{ 99return Some (( channel_id, message_id)); 100} 101} 102} 103 104None 105} 106 107fn get_related_matrix_message ( & self , source : & MessageReference ) ->Option < matrix:: EventId > { 108if let MessageReference :: Matrix ( _, event_id) = source{ 109return Some ( matrix:: EventId :: from_str ( event_id). unwrap ()); 110} 111 112if let Some ( relations) =self . get_related_messages ( source) { 113for relationin relations{ 114if let MessageReference :: Matrix ( _, event_id) = relation{ 115return Some ( matrix:: EventId :: from_str ( & event_id). unwrap ()); 116} 117} 118} 119 120None 121} 122 123pub fn link_channels ( & self , channels : & [ ChannelReference ]) { 124let discord_channels =self 125. db 126. open_tree ( "discord_channels" ) 127. expect ( "Failed to open discord channels tree" ); 128 129let matrix_channels =self 130. db 131. open_tree ( "matrix_channels" ) 132. expect ( "Failed to open matrix channels tree" ); 133 134for channelin channels. iter () { 135let other_channels = channels 136. iter () 137. filter ( |r| r !=& channel) 138. collect ::< Vec < _ >>(); 139 140match channel{ 141ChannelReference :: Discord ( channel_id) =>{ 142for other_channelin other_channels{ 143let key = bincode:: serialize ( other_channel). unwrap (); 144let value = bincode:: serialize ( channel_id). unwrap (); 145 discord_channels. insert ( key, value). unwrap (); 146} 147} 148ChannelReference :: Matrix ( room_id) =>{ 149for other_channelin other_channels{ 150let key = bincode:: serialize ( other_channel). unwrap (); 151let value = bincode:: serialize ( room_id. as_str ()). unwrap (); 152 matrix_channels. insert ( key, value). unwrap (); 153} 154} 155} 156} 157} 158 159fn store_related_messages ( & self , related_messages : & [ MessageReference ]) { 160let tree =self 161. db 162. open_tree ( "message_relations" ) 163. expect ( "Failed to open relations tree" ); 164 165for sourcein related_messages{ 166let relations = related_messages 167. iter () 168. filter ( |r| r !=& source) 169. collect ::< Vec < _ >>(); 170 171let key = bincode:: serialize ( source). expect ( "Failed to serialize message reference" ); 172let value = 173 bincode:: serialize ( & relations). expect ( "Failed to serialize message relations" ); 174 175 tree. insert ( key, value) 176. expect ( "Failed to store message relations" ); 177} 178} 179 180pub async fn send_message ( & self , message : SentMessage ) { 181if self . get_related_messages ( & message. source ). is_some () { 182return ; 183} 184 185let mut related_messages =vec! [ message. source . clone ()]; 186 187if let Some ( discord) =self . discord . lock (). unwrap (). borrow (). as_ref () { 188if let Some ( channel) =self . get_linked_discord_channel ( & message. source ) { 189let reply = message 190. replies_to 191. as_ref () 192. and_then ( |r|self . get_related_discord_message ( r)); 193 194if let Some ( m) =forward_to_discord ( discord, channel, & message, reply). await { 195 related_messages. push ( m); 196} 197} 198} 199 200if let Some ( matrix) =self . matrix . lock (). unwrap (). borrow (). as_ref () { 201if let Some ( room_id) =self . get_linked_matrix_room ( & message. source ) { 202let reply = message 203. replies_to 204. as_ref () 205. and_then ( |r|self . get_related_matrix_message ( r)); 206 207if let Some ( m) =forward_to_matrix ( matrix, room_id, & message, reply). await { 208 related_messages. push ( m); 209} 210} 211} 212 213self . store_related_messages ( & related_messages); 214} 215 216pub async fn edit_message ( & self , message : EditedMessage ) { 217if let Some ( related_messages) =self . get_related_messages ( & message. replacing ) { 218let mut new_related_messages =HashSet :: new (); 219 related_messages. iter (). for_each ( |r|{ 220 new_related_messages. insert ( r. clone ()); 221}); 222 223for related_messagein related_messages. iter () { 224match related_message{ 225MessageReference :: Discord ( channel_id, message_id) =>{ 226if let Some ( discord) =self . discord . lock (). unwrap (). borrow (). as_ref () { 227let channel_id = discord:: ChannelId ( * channel_id); 228let message_id = discord:: MessageId ( * message_id); 229 230if let Some ( m) = 231edit_on_discord ( discord, channel_id, message_id, & message). await 232{ 233 new_related_messages. insert ( m); 234} 235} 236} 237MessageReference :: Matrix ( room_id, event_id) =>{ 238if let Some ( matrix) =self . matrix . lock (). unwrap (). borrow (). as_ref () { 239let room_id = matrix:: RoomId :: from_str ( room_id). unwrap (); 240let event_id = matrix:: EventId :: from_str ( event_id). unwrap (); 241 242if let Some ( m) = 243edit_on_matrix ( matrix, room_id, event_id, & message). await 244{ 245 new_related_messages. insert ( m); 246} 247} 248} 249} 250} 251 252self . store_related_messages ( & new_related_messages. into_iter (). collect ::< Vec < _ >>()) 253} 254} 255 256pub async fn delete_message ( & self , message : DeletedMessage ) { 257if let Some ( related_messages) =self . get_related_messages ( & message. reference ) { 258for related_messagein related_messages. iter () { 259match related_message{ 260MessageReference :: Discord ( channel_id, message_id) =>{ 261if let Some ( discord) =self . discord . lock (). unwrap (). borrow (). as_ref () { 262let channel_id = discord:: ChannelId ( * channel_id); 263let message_id = discord:: MessageId ( * message_id); 264 265let _success = 266delete_on_discord ( discord, channel_id, message_id, & message). await ; 267} 268} 269MessageReference :: Matrix ( room_id, event_id) =>{ 270if let Some ( matrix) =self . matrix . lock (). unwrap (). borrow (). as_ref () { 271let room_id = matrix:: RoomId :: from_str ( room_id). unwrap (); 272let event_id = matrix:: EventId :: from_str ( event_id). unwrap (); 273 274let _success = 275delete_on_matrix ( matrix, room_id, event_id, & message). await ; 276} 277} 278} 279} 280} 281} 282 283pub async fn send_image ( & self , message : SentImageMessage ) { 284if self . get_related_messages ( & message. source ). is_some () { 285return ; 286} 287 288let mut related_messages =vec! [ message. source . clone ()]; 289 290if let Some ( discord) =self . discord . lock (). unwrap (). borrow (). as_ref () { 291if let Some ( discord_channel) =self . get_linked_discord_channel ( & message. source ) { 292if let Some ( m) =forward_image_to_discord ( discord, discord_channel, & message). await 293{ 294 related_messages. push ( m); 295} 296} 297} 298 299if let Some ( matrix) =self . matrix . lock (). unwrap (). borrow (). as_ref () { 300if let Some ( room_id) =self . get_linked_matrix_room ( & message. source ) { 301if let Some ( m) =forward_image_to_matrix ( matrix, room_id, & message). await { 302 related_messages. push ( m); 303} 304} 305} 306 307self . store_related_messages ( & related_messages); 308} 309}