char/phoebe
git clone https://git.t4t.associates/char/phoebe
4fc8c15
main
1use color_eyre:: Result ; 2use futures::{ future, StreamExt }; 3use tracing:: info; 4use tracing_subscriber:: EnvFilter ; 5 6use phoebe::{ 7 get_linked_channels, get_linked_messages, link_messages, 8 prelude::{ ChatEvent , SqlitePool }, 9 service:: Service , 10 unlink_message, DynServiceLookup , 11}; 12 13async fn handle_events ( 14dyn_service : DynServiceLookup , 15db : SqlitePool , 16mut service : Box < dyn Service +Send +Sync >, 17mut rx : tokio:: sync:: broadcast:: Receiver < ChatEvent >, 18) { 19info! ( "Handling events for {}…" , service. tag ()); 20 21let mut conn = db 22. acquire () 23. await 24. expect ( "Failed to acquire core DB connection" ); 25 26while let Ok ( event) = rx. recv (). await { 27match event{ 28ChatEvent :: NewMessage ( message) =>{ 29let linked_channels = 30get_linked_channels ( & mut conn, dyn_service, & message. origin . channel ). await ; 31 32let mut resulting_messages =vec! []; 33for destination_channelin linked_channels{ 34 resulting_messages. extend ( 35 service 36. send_chat_message ( & message, destination_channel) 37. await , 38) 39} 40 41if !resulting_messages. is_empty () { 42if let Err ( e) = 43link_messages ( & mut conn, & message. origin , & resulting_messages). await 44{ 45 tracing:: error!( "Failed to link messages: {e}" ); 46} 47} 48} 49 50ChatEvent :: DeleteMessage ( origin) =>{ 51let messages =if let Ok ( message_stream) = 52get_linked_messages ( & mut conn, dyn_service, & origin). await 53{ 54 message_stream 55. filter ( |r| future:: ready ( r. channel . service == service. tag ())) 56. collect ::< Vec < _ >>() 57. await 58} else { 59vec! [] 60}; 61 62if !messages. is_empty () { 63if let Err ( e) =unlink_message ( & mut conn, & origin). await { 64 tracing:: error!( "Failed to unlink origin message: {e}" ); 65} 66 67for messagein messages{ 68if service. delete_message ( & message). await { 69if let Err ( e) =unlink_message ( & mut conn, & message). await { 70 tracing:: error!( "Failed to unlink related message: {e}" ); 71} 72} 73} 74} 75} 76ChatEvent :: EditMessage ( prev_origin, message_edit) =>{ 77let messages =if let Ok ( message_stream) = 78get_linked_messages ( & mut conn, dyn_service, & prev_origin). await 79{ 80 message_stream 81. filter ( |r| future:: ready ( r. channel . service == service. tag ())) 82. collect ::< Vec < _ >>() 83. await 84} else { 85vec! [] 86}; 87 88let mut resulting_messages =vec! []; 89for messagein messages{ 90 resulting_messages. extend ( service. edit_message ( & message, & message_edit). await ) 91} 92 93if !resulting_messages. is_empty () { 94if let Err ( e) = 95link_messages ( & mut conn, & prev_origin, & resulting_messages). await 96{ 97 tracing:: error!( "Failed to link messages: {e}" ); 98} 99} 100} 101} 102} 103} 104 105# [ tokio :: main ] 106async fn main () ->Result <()> { 107 color_eyre:: install () ?; 108 109 tracing_subscriber:: fmt () 110. with_target ( true ) 111. with_env_filter ( EnvFilter :: from_default_env ()) 112. init (); 113 114let ( tx, _) = tokio:: sync:: broadcast:: channel ( 512 ); 115 116let db = phoebe:: open_core_db (). await ?; 117 118fn dyn_service ( service : & str ) ->&' static str { 119match service{ 120"discord" =>"discord" , 121"matrix" =>"matrix" , 122 _ =>panic! ( "Unsupported service: {}" , service), 123} 124} 125 126let services: Vec < Box < dyn Service +Send +Sync >> =vec! [ Box :: new ( 127 phoebe_discord:: setup ( db. clone (), tx. clone (), dyn_service). await ?, 128)]; 129 130let handles = services 131. into_iter () 132. map ( |srv| tokio:: spawn ( handle_events ( dyn_service, db. clone (), srv, tx. subscribe ()))); 133 134let _ = future:: join_all ( handles). await ; 135 136Ok (()) 137}