Completed logic to login bot

main
David 2022-12-10 21:31:02 +01:00
parent 4aa0de124d
commit 96372b83fd
4 changed files with 120 additions and 47 deletions

View File

@ -1,68 +1,120 @@
#[allow(clippy::module_inception)] #[allow(clippy::module_inception)]
pub mod bot { pub mod bot {
use crate::config_reader::config_reader::BotUserCreds; use crate::{config_reader::config_reader::BotUserInfo, utils};
use anyhow; use log::{info, debug};
use log::info;
use matrix_sdk::{ use matrix_sdk::{
config::SyncSettings, config::{SyncSettings, RequestConfig},
event_handler::Ctx, event_handler::Ctx,
room::{Joined, Room, RoomMember}, room::{Joined, Room, RoomMember},
ruma::{ ruma::{
events::room::message::SyncRoomMessageEvent, user_id, OriginalSyncRoomMessageEvent, UserId, ServerName,
events::room::message::{OriginalSyncRoomMessageEvent,
RoomMessageEventContent},
user_id, RoomId,
}, },
Client, Client,
}; };
use crate::utils::utils::*;
#[allow(dead_code)] #[allow(dead_code)]
#[derive(Clone)] #[derive(Clone)]
pub struct Bot { pub struct Bot {
client: Client, client: Client,
joined_room: Joined,
} }
pub async fn bot_login(creds: BotUserCreds) -> anyhow::Result<Bot> { impl Bot {
let user_id = creds.user_id.as_str(); pub async fn bot_login(creds: BotUserInfo) {
let password = creds.password.as_str(); let user_id = creds.user_id.as_str();
let homeserver = creds.homeserver.as_str(); let password = creds.password.as_str();
let client = Client::builder().homeserver_url(homeserver).build().await?; // 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 user = UserId::parse(user_id).expect("Unable to parse bot user id");
let response = client let server_name = ServerName::parse(user.server_name()).unwrap();
.login_username(user_id, password) let request_config = RequestConfig::new().force_auth();
.initial_device_display_name("matrix-modbot") let client = Client::builder()
.send() .server_name(&server_name)
.await .request_config(request_config)
.expect("Unable to login"); .build()
.await.
unwrap();
info!("Doing the initial sync…"); info!("Logging in…");
client let response = client
.sync_once(SyncSettings::new()) .login_username(user.localpart(), password)
.await .initial_device_display_name("Matrix-Modbot")
.expect("Unable to sync"); .send()
.await
.expect("Unable to login");
info!( info!("Doing the initial sync…");
"Logged in as {}, got device_id {}", client
response.user_id, response.device_id .sync_once(SyncSettings::new())
); .await
.expect("Unable to sync");
Ok(Bot { client }) info!(
} "Logged in as {}, got device_id {}",
pub async fn message_handler(bot: Bot) { response.user_id, response.device_id
// 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);
}
async fn on_room_message(event: OriginalSyncRoomMessageEvent, room: Room, Ctx(bot): Ctx<Bot>) { // Code snippet from hebbot https://github.com/haecker-felix/hebbot
if let Room::Joined(_joined) = &room { // Try to accept room invite, if any
// Standard text message if let Some(invited_room) = client.get_invited_room(&room) {
if let Some(text) = utils::get_message_event_text(&event) { invited_room
let member = room.get_member(&event.sender).await.unwrap().unwrap(); .accept_invitation()
let id = &event.event_id; .await
.expect("Matrix-Modbot could not join the invited room");
}
// 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<Bot>) {
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() {}
} }

View File

@ -5,23 +5,26 @@ pub mod config_reader {
#[derive(Debug)] #[derive(Debug)]
#[allow(dead_code)] #[allow(dead_code)]
pub struct BotUserCreds { pub struct BotUserInfo {
pub user_id: String, pub user_id: String,
pub password: String, pub password: String,
pub homeserver: String, pub homeserver: String,
pub room: String
} }
impl BotUserCreds { impl BotUserInfo {
pub fn new(config_file_path: &str) -> Result<Self, Box<dyn Error>> { pub fn get_info(config_file_path: &str) -> Result<Self, Box<dyn Error>> {
let mut config = Ini::new(); let mut config = Ini::new();
let _map = config.load(config_file_path)?; let _map = config.load(config_file_path)?;
let user_id = config.get("credentials", "user_id").unwrap(); let user_id = config.get("credentials", "user_id").unwrap();
let password = config.get("credentials", "password").unwrap(); let password = config.get("credentials", "password").unwrap();
let homeserver = config.get("credentials", "homeserver").unwrap(); let homeserver = config.get("credentials", "homeserver").unwrap();
Ok(BotUserCreds { let room = config.get("room", "room").unwrap();
Ok(BotUserInfo {
user_id, user_id,
password, password,
homeserver, homeserver,
room
}) })
} }
} }

View File

@ -1,8 +1,10 @@
// Snippet from https://github.com/haecker-felix/hebbot, licensed under AGPL, License terms apply
#[allow(clippy::module_inception)] #[allow(clippy::module_inception)]
pub mod utils { pub mod utils {
use matrix_sdk::ruma::events::room::message::{ 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<String> { pub fn get_message_event_text(event: &OriginalSyncRoomMessageEvent) -> Option<String> {
if let MessageType::Text(TextMessageEventContent { body, .. }) = &event.content.msgtype { if let MessageType::Text(TextMessageEventContent { body, .. }) = &event.content.msgtype {
@ -11,4 +13,17 @@ pub mod utils {
None 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
}
} }

View File

@ -2,3 +2,6 @@
user_id = john user_id = john
homeserver = http://example.com homeserver = http://example.com
password = correcthorsebatterystaple password = correcthorsebatterystaple
[room]
room = general