From 96372b83fde6b30dbfb975c5f0c7186d5b4358a9 Mon Sep 17 00:00:00 2001 From: David Date: Sat, 10 Dec 2022 21:31:02 +0100 Subject: [PATCH] Completed logic to login bot --- src/bot.rs | 136 ++++++++++++++++++++++++++++++------------- src/config_reader.rs | 11 ++-- src/utils.rs | 17 +++++- tests/test_creds.ini | 3 + 4 files changed, 120 insertions(+), 47 deletions(-) diff --git a/src/bot.rs b/src/bot.rs index 51f085e..2201e99 100644 --- a/src/bot.rs +++ b/src/bot.rs @@ -1,68 +1,120 @@ #[allow(clippy::module_inception)] pub mod bot { - use crate::config_reader::config_reader::BotUserCreds; - use anyhow; - use log::info; + use crate::{config_reader::config_reader::BotUserInfo, utils}; + use log::{info, debug}; use matrix_sdk::{ - config::SyncSettings, + config::{SyncSettings, RequestConfig}, event_handler::Ctx, room::{Joined, Room, RoomMember}, ruma::{ - events::room::message::SyncRoomMessageEvent, user_id, OriginalSyncRoomMessageEvent, + UserId, ServerName, + events::room::message::{OriginalSyncRoomMessageEvent, + RoomMessageEventContent}, + user_id, RoomId, }, Client, }; + use crate::utils::utils::*; #[allow(dead_code)] #[derive(Clone)] pub struct Bot { client: Client, + joined_room: Joined, } - pub async fn bot_login(creds: BotUserCreds) -> anyhow::Result { - let user_id = creds.user_id.as_str(); - let password = creds.password.as_str(); - let homeserver = creds.homeserver.as_str(); - let client = Client::builder().homeserver_url(homeserver).build().await?; + impl Bot { + pub async fn bot_login(creds: BotUserInfo) { + let user_id = creds.user_id.as_str(); + let password = creds.password.as_str(); + // let homeserver = creds.homeserver.as_str(); + let room = RoomId::parse(creds.room.as_str()).unwrap(); + // let client = Client::builder().homeserver_url(homeserver).build().await.unwrap(); - info!("Logging in…"); - let response = client - .login_username(user_id, password) - .initial_device_display_name("matrix-modbot") - .send() - .await - .expect("Unable to login"); + let user = UserId::parse(user_id).expect("Unable to parse bot user id"); + let server_name = ServerName::parse(user.server_name()).unwrap(); + let request_config = RequestConfig::new().force_auth(); + let client = Client::builder() + .server_name(&server_name) + .request_config(request_config) + .build() + .await. + unwrap(); - info!("Doing the initial sync…"); - client - .sync_once(SyncSettings::new()) - .await - .expect("Unable to sync"); + info!("Logging in…"); + let response = client + .login_username(user.localpart(), password) + .initial_device_display_name("Matrix-Modbot") + .send() + .await + .expect("Unable to login"); - info!( - "Logged in as {}, got device_id {}", - response.user_id, response.device_id - ); + info!("Doing the initial sync…"); + client + .sync_once(SyncSettings::new()) + .await + .expect("Unable to sync"); - Ok(Bot { client }) - } - pub async fn message_handler(bot: Bot) { - // Setup event handlers - // bot.client.add_event_handler(on_room_message); - // bot.client.add_event_handler(on_room_reaction); - // bot.client.add_event_handler(on_room_redaction); - } + info!( + "Logged in as {}, got device_id {}", + response.user_id, response.device_id + ); + + // Code snippet from hebbot https://github.com/haecker-felix/hebbot + // Try to accept room invite, if any + if let Some(invited_room) = client.get_invited_room(&room) { + invited_room + .accept_invitation() + .await + .expect("Matrix-Modbot could not join the invited room"); + } - async fn on_room_message(event: OriginalSyncRoomMessageEvent, room: Room, Ctx(bot): Ctx) { - if let Room::Joined(_joined) = &room { - // Standard text message - if let Some(text) = utils::get_message_event_text(&event) { - let member = room.get_member(&event.sender).await.unwrap().unwrap(); - let id = &event.event_id; + // Need to do another sync to make sure bot knows the newly joined rooms + client + .sync_once(SyncSettings::new()) + .await + .expect("Unable to sync"); + + let joined_room = client + .get_joined_room(&room) + .expect("Cannot get joined room"); + + let bot = Bot { + client, + joined_room + }; + + bot.send_message("Sucessfully started Matrix-Modbot").await; + + bot.client.add_event_handler_context(bot.clone()); + bot.client.add_event_handler(Self::on_room_message); + + info!("Started syncing"); + bot.client.sync(SyncSettings::new()).await.unwrap(); + } + + pub async fn on_room_message(event: OriginalSyncRoomMessageEvent, + room: Room, Ctx(bot): Ctx) { + if let Room::Joined(_joined) = &room { + // Standard text message + if let Some(text) = get_message_event_text(&event) { + let member = room.get_member(&event.sender).await.unwrap().unwrap(); + let id = &event.event_id; + } + // Message edit + if let Some((edited_msg_event_id, text)) = get_edited_message_event_text(&event) {} } } + + pub async fn send_message(&self, message: &str) { + debug!("Send message ({:?}): {}", &self.joined_room, message); + let content = RoomMessageEventContent::text_plain(message); + &self.joined_room.send(content, None) + .await + .expect("Unable to send message"); + + } + } - pub async fn on_room_reaction() {} - pub async fn on_room_redaction() {} } diff --git a/src/config_reader.rs b/src/config_reader.rs index 4809fd6..20f6a0f 100644 --- a/src/config_reader.rs +++ b/src/config_reader.rs @@ -5,23 +5,26 @@ pub mod config_reader { #[derive(Debug)] #[allow(dead_code)] - pub struct BotUserCreds { + pub struct BotUserInfo { pub user_id: String, pub password: String, pub homeserver: String, + pub room: String } - impl BotUserCreds { - pub fn new(config_file_path: &str) -> Result> { + impl BotUserInfo { + pub fn get_info(config_file_path: &str) -> Result> { let mut config = Ini::new(); let _map = config.load(config_file_path)?; let user_id = config.get("credentials", "user_id").unwrap(); let password = config.get("credentials", "password").unwrap(); let homeserver = config.get("credentials", "homeserver").unwrap(); - Ok(BotUserCreds { + let room = config.get("room", "room").unwrap(); + Ok(BotUserInfo { user_id, password, homeserver, + room }) } } diff --git a/src/utils.rs b/src/utils.rs index e0df7d2..ee49a31 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -1,8 +1,10 @@ +// Snippet from https://github.com/haecker-felix/hebbot, licensed under AGPL, License terms apply #[allow(clippy::module_inception)] pub mod utils { use matrix_sdk::ruma::events::room::message::{ - MessageType, OriginalSyncRoomMessageEvent, TextMessageEventContent, + MessageType, OriginalSyncRoomMessageEvent, TextMessageEventContent, Relation, }; + use matrix_sdk::ruma::OwnedEventId; pub fn get_message_event_text(event: &OriginalSyncRoomMessageEvent) -> Option { if let MessageType::Text(TextMessageEventContent { body, .. }) = &event.content.msgtype { @@ -11,4 +13,17 @@ pub mod utils { None } } + + // A simplified way of getting an edited message + pub fn get_edited_message_event_text( + event: &OriginalSyncRoomMessageEvent, + ) -> Option<(OwnedEventId, String)> { + if let Some(Relation::Replacement(r)) = &event.content.relates_to { + if let MessageType::Text(TextMessageEventContent { body, .. }) = &r.new_content.msgtype { + return Some((r.event_id.clone(), body.to_owned())); + } + } + + None + } } diff --git a/tests/test_creds.ini b/tests/test_creds.ini index af4f84e..8fb7ee9 100644 --- a/tests/test_creds.ini +++ b/tests/test_creds.ini @@ -2,3 +2,6 @@ user_id = john homeserver = http://example.com password = correcthorsebatterystaple + +[room] +room = general