diff --git a/src/matrix.rs b/src/bot.rs similarity index 65% rename from src/matrix.rs rename to src/bot.rs index 2b031f1259f680cafa3c530f322d09be9f7aa069..8217fabaa0deb886868dcf74f0ac71a9bafa6603 100644 --- a/src/matrix.rs +++ b/src/bot.rs @@ -22,9 +22,15 @@ use matrix_sdk::{ }, Client, Result, SyncSettings, }; -use std::{convert::TryFrom, lazy::SyncLazy, process::abort, sync::Arc, sync::Mutex}; +use std::{convert::TryFrom, process::abort, sync::Mutex}; use tokio::time::{sleep, Duration}; +pub struct Bot { + config: Config, + client: Option<Client>, + packages: Mutex<Vec<CmdPackage>>, +} + async fn join_room(room: &Invited) { info!("Autojoining room {}", room.room_id()); let mut delay = 2; // seconds @@ -86,40 +92,6 @@ 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, @@ -149,9 +121,6 @@ async fn on_msg_room_reaction( }; } -static GLOBAL_PKG: SyncLazy<Arc<Mutex<Vec<CmdPackage>>>> = - SyncLazy::new(|| Arc::new(Mutex::new(Vec::<CmdPackage>::new()))); - macro_rules! register_handler_if_enabled { ($client: expr, $config: expr, $handler: expr, $handler_name: expr) => {{ if ($config) { @@ -163,11 +132,6 @@ macro_rules! register_handler_if_enabled { }}; } -pub struct Bot { - config: Config, - client: Option<Client>, -} - impl Bot { pub fn new(config_file: String) -> Bot { match config_from_file(&config_file) { @@ -183,6 +147,7 @@ impl Bot { Bot { config: config, client: None, + packages: Mutex::new(Vec::<CmdPackage>::new()), } } } @@ -212,6 +177,41 @@ 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; @@ -231,60 +231,14 @@ impl Bot { } } - pub fn add_package(&self, name: String, cmds: Vec<Cmd>) -> &Self { + pub fn add_package(&mut self, name: String, cmds: Vec<Cmd>) -> &mut Self { let pkg = match self.config.section(&name) { Some(section) => CmdPackage::from_config(§ion, cmds), None => { abort(); } }; - GLOBAL_PKG.lock().unwrap().push(pkg); - &self - } - - pub async fn connect_and_handle(config: Config) -> Result<()> { - // TODO: Refactor - let pkg_commands_vec = vec![ - Cmd::new_simple(format!("ping"), 0, |_x| true), - Cmd::new_echo(format!("bot_name"), 0, |_x| format!("toto")), - ]; - let pkg = match config.section("basic") { - Some(section) => CmdPackage::from_config(§ion, pkg_commands_vec), - None => { - abort(); - } - }; - GLOBAL_PKG.lock().unwrap().push(pkg); - - let alice = UserId::try_from(config.user_name)?; - let client = Client::new(config.homeserver_url)?; - - client - .login( - alice.localpart(), - config.user_password.as_str(), - None, - Some(config.display_name.as_str()), - ) - .await?; - info!("Logged as: {}", alice); - - client.sync_once(SyncSettings::default()).await?; - startup_and_log_rooms(&client).await; - register_handler_if_enabled!( - client, - config.handle_state_member, - on_state_member, - "state member" - ); - - 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(); - let settings = SyncSettings::default().token(token); - client.sync(settings).await; - Ok(()) + self.packages.lock().unwrap().push(pkg); + self } } diff --git a/src/cmd/acl.rs b/src/cmd/acl.rs index 405b0e9c3eaf9785748278cbb665e5844f78c083..d27de8ee0c2fdde29f2210f4eaae4db06d25463b 100644 --- a/src/cmd/acl.rs +++ b/src/cmd/acl.rs @@ -1,10 +1,11 @@ +#![allow(dead_code)] + use crate::bool_to_result; use log::{error, warn}; use matrix_sdk::{room::Joined as JoinedRoom, ruma::UserId}; use std::fmt; use std::{process::abort, result::Result}; -#[allow(dead_code)] #[derive(Clone)] pub enum CmdAcl { Any, @@ -13,7 +14,6 @@ pub enum CmdAcl { List(Vec<CmdAcl>), } -#[allow(dead_code)] #[derive(Clone)] pub struct CmdAdminRegister { admins: Vec<UserId>, @@ -42,14 +42,12 @@ impl CmdAdminRegister { return self.admins.iter().position(|x| *x == user_id).is_some(); } - #[allow(dead_code)] pub fn add_admin(&mut self, user_id: UserId) { if !self.is_admin(user_id.clone()) { self.admins.push(user_id); } } - #[allow(dead_code)] pub fn revoke_admin(&mut self, user_id: UserId) -> Result<(), String> { match self.admins.iter().position(|x| *x == user_id) { Some(index) => { @@ -60,7 +58,6 @@ impl CmdAdminRegister { } } - #[allow(dead_code)] pub fn from_vec(admins_vec: Vec<UserId>) -> CmdAdminRegister { CmdAdminRegister { admins: admins_vec } } @@ -91,7 +88,6 @@ impl fmt::Display for CmdAcl { } impl CmdAcl { - #[allow(dead_code)] pub fn action_permited( cmd_admin_register: &CmdAdminRegister, acls: &CmdAcl, @@ -147,7 +143,6 @@ impl CmdAcl { } } - #[allow(dead_code)] pub fn from_string(string: String) -> CmdAcl { let acl_list = string .split(",") diff --git a/src/cmd/package.rs b/src/cmd/package.rs index 206611a1969631068be6f59af06ad323eef07ffa..ce9199e312d3090eef067ff5a23b2c3b9cd6d7c4 100644 --- a/src/cmd/package.rs +++ b/src/cmd/package.rs @@ -1,3 +1,5 @@ +#![allow(dead_code)] + use crate::cmd::{ acl::{CmdAcl, CmdAdminRegister}, Cmd, @@ -10,12 +12,10 @@ pub struct CmdPackage { name: String, acl: CmdAcl, admin_register: CmdAdminRegister, - commands: Vec<Cmd>, } impl CmdPackage { - #[allow(dead_code)] pub fn has_command(&self, user_cmd: &Vec<&str>) -> bool { match user_cmd.split_first() { None => false, @@ -30,7 +30,6 @@ impl CmdPackage { } } - #[allow(dead_code)] pub fn handle(&self, room: &JoinedRoom, user_id: &UserId, user_cmd: Vec<&str>) -> String { match CmdAcl::action_permited(&self.admin_register, &self.acl, room, user_id) { Err(string) => "Action not permited: ".to_string() + &string, @@ -48,7 +47,6 @@ impl CmdPackage { } } - #[allow(dead_code)] pub fn from_config(section: &IniSection, commands: Vec<Cmd>) -> CmdPackage { CmdPackage { name: section.get("name").unwrap().to_string(), diff --git a/src/main.rs b/src/main.rs index 12fc6106caca25c20a7699d2e09c635d9aa6585b..b9ff40b1c548437d9e9719497524fedc4b296b51 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,10 +1,11 @@ #![feature(new_uninit, once_cell, trait_alias)] +mod bot; mod cmd; mod config; -mod matrix; mod utils; +use crate::bot::Bot; use crate::cmd::Cmd; use matrix_sdk; use std::env; @@ -19,10 +20,10 @@ async fn main() -> matrix_sdk::Result<()> { Cmd::new_echo(format!("bot_name"), 0, |_x| format!("toto")), ]; - matrix::Bot::new(env::args().last().unwrap()) + Bot::new(env::args().last().unwrap()) + .add_package(format!("basic"), basic_cmds) .connect() .await? - .add_package(format!("basic"), basic_cmds) .listen() .await }