diff --git a/src/bot.rs b/src/bot.rs index 8217fabaa0deb886868dcf74f0ac71a9bafa6603..8b83d56ad4de1ff79e632c6ce94d6e8db3b8e667 100644 --- a/src/bot.rs +++ b/src/bot.rs @@ -22,13 +22,17 @@ use matrix_sdk::{ }, Client, Result, SyncSettings, }; -use std::{convert::TryFrom, process::abort, sync::Mutex}; +use std::{ + convert::TryFrom, + lazy::SyncLazy, + process::abort, + sync::{Arc, Mutex}, +}; use tokio::time::{sleep, Duration}; pub struct Bot { config: Config, client: Option<Client>, - packages: Mutex<Vec<CmdPackage>>, } async fn join_room(room: &Invited) { @@ -92,6 +96,39 @@ async fn startup_and_log_rooms(client: &Client) { join_all(list_to_wait_for).await; } +async fn on_msg_room_event( + ev: SyncMessageEvent<MessageEventContent>, + room: Room, + __info: Option<EncryptionInfo>, +) { + let sender_id = ev.sender.clone(); + return_if!(sender_id.as_str() == room.own_user_id().as_str(), ()); + if let (Room::Joined(joined), MessageType::Text(TextMessageEventContent { ref body, .. })) = + (room, ev.content.msgtype.clone()) + { + if body.starts_with("%") { + if let Some(stripped) = body.strip_prefix("%") { + let args = stripped.split(' ').collect::<Vec<&str>>(); + let mut res: String = format!("Command not found"); + if let Some(pkg) = GLOBAL_PKG + .lock() + .unwrap() + .iter() + .find(|x| x.has_command(&args)) + { + res = pkg.handle(&joined, &sender_id, args); + } + + let event = ev.into_full_event(joined.room_id().clone()); + let msg = AnyMessageEventContent::RoomMessage( + MessageEventContent::text_reply_html(res.clone(), res, &event), + ); + joined.send(msg, None).await.unwrap(); + } + } + }; +} + async fn on_msg_room_reaction( ev: SyncMessageEvent<ReactionEventContent>, room: Room, @@ -132,6 +169,9 @@ macro_rules! register_handler_if_enabled { }}; } +static GLOBAL_PKG: SyncLazy<Arc<Mutex<Vec<CmdPackage>>>> = + SyncLazy::new(|| Arc::new(Mutex::new(Vec::<CmdPackage>::new()))); + impl Bot { pub fn new(config_file: String) -> Bot { match config_from_file(&config_file) { @@ -147,12 +187,15 @@ impl Bot { Bot { config: config, client: None, - packages: Mutex::new(Vec::<CmdPackage>::new()), } } } } + pub fn get_configuration(&self) -> &Config { + &self.config + } + pub async fn connect(&mut self) -> Result<&mut Self> { let alice = UserId::try_from(self.config.user_name.clone())?; let client = Client::new(self.config.homeserver_url.clone())?; @@ -177,44 +220,6 @@ impl Bot { "state member" ); - let on_msg_room_event = |ev: SyncMessageEvent<MessageEventContent>, - room: Room, - __info: Option<EncryptionInfo>| async { - let sender_id = ev.sender.clone(); - return_if!(sender_id.as_str() == room.own_user_id().as_str(), ()); - - if let ( - Room::Joined(joined), - MessageType::Text(TextMessageEventContent { ref body, .. }), - ) = (room, ev.content.msgtype.clone()) - { - if body.starts_with("%") { - if let Some(stripped) = body.strip_prefix("%") { - let args = stripped.split(' ').collect::<Vec<&str>>(); - let mut res: String = format!("Command not found"); - if let Some(pkg) = self - .packages - .lock() - .unwrap() - .iter() - .find(|x| x.has_command(&args)) - { - res = pkg.handle(&joined, &sender_id, args); - } - - let event = ev.into_full_event(joined.room_id().clone()); - let msg = AnyMessageEventContent::RoomMessage( - MessageEventContent::text_reply_html(res.clone(), res, &event), - ); - joined.send(msg, None).await.unwrap(); - } - } - }; - }; - - client.register_event_handler(on_msg_room_event).await; - client.register_event_handler(on_msg_room_reaction).await; - self.client = Some(client); return Ok(self); } @@ -223,6 +228,9 @@ impl Bot { match &self.client { None => abort(), Some(client) => { + client.register_event_handler(on_msg_room_event).await; + client.register_event_handler(on_msg_room_reaction).await; + info!("Entering sync loop"); let token = client.sync_token().await.unwrap(); client.sync(SyncSettings::default().token(token)).await; @@ -231,14 +239,13 @@ impl Bot { } } - pub fn add_package(&mut self, name: String, cmds: Vec<Cmd>) -> &mut Self { - let pkg = match self.config.section(&name) { + pub fn add_package(config: &Config, name: String, cmds: Vec<Cmd>) { + let pkg = match config.section(&name) { Some(section) => CmdPackage::from_config(§ion, cmds), None => { abort(); } }; - self.packages.lock().unwrap().push(pkg); - self + GLOBAL_PKG.lock().unwrap().push(pkg); } } diff --git a/src/main.rs b/src/main.rs index b9ff40b1c548437d9e9719497524fedc4b296b51..1656faf4cf5906b376ca233310ee0a428caa2fa6 100644 --- a/src/main.rs +++ b/src/main.rs @@ -20,10 +20,7 @@ async fn main() -> matrix_sdk::Result<()> { Cmd::new_echo(format!("bot_name"), 0, |_x| format!("toto")), ]; - Bot::new(env::args().last().unwrap()) - .add_package(format!("basic"), basic_cmds) - .connect() - .await? - .listen() - .await + let mut bot = Bot::new(env::args().last().unwrap()); + Bot::add_package(bot.get_configuration(), format!("basic"), basic_cmds); + bot.connect().await?.listen().await }