diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/bot_config.rs | 6 | ||||
| -rw-r--r-- | src/main.rs | 96 |
2 files changed, 82 insertions, 20 deletions
diff --git a/src/bot_config.rs b/src/bot_config.rs index 2438c40..5fd2482 100644 --- a/src/bot_config.rs +++ b/src/bot_config.rs @@ -6,7 +6,7 @@ use config::{Config, ConfigError, File as ConfigFile}; /// Configuration struct of a bot pub struct BotConfig { - user: String, + username: String, password: String, homeserver_url: String, } @@ -25,14 +25,14 @@ impl BotConfig config.merge(ConfigFile::with_name("botconfig"))?; Ok(Self { - user: config.get_str("user")?, + username: config.get_str("username")?, password: config.get_str("password")?, homeserver_url: config.get_str("homeserver_url")?, }) } /// Get the username that should be used by the bot - pub fn user(&self) -> &String { &self.user } + pub fn username(&self) -> &String { &self.username } /// Get the password the bot should use to authenticate its user pub fn password(&self) -> &String { &self.password } /// Get the homeserver of the bot where it should send the login data to diff --git a/src/main.rs b/src/main.rs index a3b1f64..5e361cb 100644 --- a/src/main.rs +++ b/src/main.rs @@ -4,32 +4,94 @@ //! Slavoj Žižek in your life, this matrix bot can help you satisfying that //! need. -use std::sync::{Arc, Mutex}; - -use matrix_bot_api::MatrixBot; +use matrix_sdk::room::Room; +use matrix_sdk::events::room::member::MemberEventContent; +use matrix_sdk::events::StrippedStateEvent; +use matrix_sdk::{async_trait, Client, ClientConfig, EventHandler, SyncSettings}; +use tokio::time::{sleep, Duration}; +use url::Url; pub mod bot_config; -pub mod command_handler; pub mod zizek_db; use bot_config::BotConfig; -use command_handler::CommandHandler; use zizek_db::ZizekDb; -fn main() +struct AutoJoinBot +{ + client: Client, +} + +impl AutoJoinBot +{ + pub fn new(client: Client) -> Self { Self { client } } +} + +#[async_trait] +impl EventHandler for AutoJoinBot { + async fn on_stripped_state_member(&self, room: Room, room_member: &StrippedStateEvent<MemberEventContent>, _: Option<MemberEventContent>){ + /* If the event does not concern the bot user, ignore it */ + if room_member.state_key != self.client.user_id().await.unwrap() { + return; + } + + if let Room::Invited(room) = room { + println!("Autojoining room {}", room.room_id()); + let mut delay = 2; + + while let Err(err) = room.accept_invitation().await { + // retry autojoin due to synapse sending invites, before the + // invited user can join for more information see + // https://github.com/matrix-org/synapse/issues/4345 + eprintln!( + "Failed to join room {} ({:?}), retrying in {}s", + room.room_id(), + err, + delay + ); + + sleep(Duration::from_secs(delay)).await; + delay *= 2; + + if delay > 3600 { + eprintln!("Can't join room {} ({:?})", room.room_id(), err); + break; + } + } + println!("Successfully joined room {}", room.room_id()); + } + } +} + +async fn login_and_sync(homeserver_url: &str, username: &str, password: &str) -> Result<(), matrix_sdk::Error> { + let mut config_dir = dirs::home_dir().expect("No home directory found"); + config_dir.push("zizek_bot"); + let config = ClientConfig::new().store_path(config_dir); + + + let homeserver_url = Url::parse(&homeserver_url).expect("Couldn't parse the homeserver URL"); + let client = Client::new_with_config(homeserver_url, config).unwrap(); + + client.login(username, password, None, Some("Slavoj Žižek")).await?; + println!("logged in as {}", username); + + client.set_event_handler(Box::new(AutoJoinBot::new(client.clone()))).await; + + client.sync(SyncSettings::default()).await; + + Ok(()) +} + +#[tokio::main] +async fn main() -> Result<(), matrix_sdk::Error> { + tracing_subscriber::fmt::init(); + let bot_config = BotConfig::from_config_file().expect("Unable to read bot configuration file"); - let zizek_db = Arc::new(Mutex::new( - ZizekDb::from_file("zizek_quotes.db").expect("Unable to load zizek quote database"), - )); + let zizek_db = + ZizekDb::from_file("zizek_quotes.db").expect("Unable to load zizek quote database"); - /* The command handler is the handler with the highest priority, so it gets - * registered first */ - let bot = MatrixBot::new(CommandHandler::new(zizek_db.clone())); + login_and_sync(bot_config.homeserver_url(), bot_config.username(), bot_config.password()).await?; - bot.run( - bot_config.user(), - bot_config.password(), - bot_config.homeserver_url(), - ); + Ok(()) } |
