use matrix_sdk::{Client, ruma::{UserId, RoomId, events::{room::message::RoomMessageEventContent}}, Session, room::Room, config::SyncSettings}; use ruma::OwnedRoomAliasId; use postbus::command::Mailbox; use crate::config::{Mapping, Config}; pub async fn get_clients(config: &mut Config) -> Vec { let mut clients: Vec = vec![]; let mut room_aliases_resolved = false; // Try to build a matrix_sdk::Client object for each configured client for conf in &mut config.clients { let user_id = match UserId::parse(&conf.mxid) { Ok(id) => id, Err(_e) => continue, }; let client = match Client::builder().user_id(&user_id).build().await { Ok(c) => c, Err(_e) => continue, }; // Attempt to restore a previous login if let Some(token) = &conf.access_token { if let Some(dev_id) = &conf.device_id { match client.restore_login(Session { access_token: token.to_string(), user_id: (&user_id).to_owned(), device_id: dev_id.as_str().into()}).await { Ok(_) => (), Err(_e) => continue, }; } } // If login restoration did not work, log in using the password if !client.logged_in().await { match conf.password.len() { 0 => continue, _ => match client.login( user_id, &conf.password, (&conf).device_id.as_deref(), Some("matrixmailer") ).await { Ok(_) => (), Err(_) => continue, } } } // If client is logged in, update the config to persist the session if let Some(session) = client.session().await { conf.access_token = Some(session.access_token); conf.device_id = Some(session.device_id.to_string()); } // If room aliases are supplied as room_id in the config file, resolve them and store the pairs properly if !room_aliases_resolved && client.logged_in().await { for mapping in &mut config.mappings { if mapping.room_id.as_str().chars().nth(0).unwrap() == '#' || mapping.room_id.len() == 0 { // TODO: Clean this up once matrix-rust-sdk 0.6.0 is available let alias: OwnedRoomAliasId = match OwnedRoomAliasId::try_from(mapping.room_id.as_str()) { Ok(a) => a, Err(_e) => continue, }; let resolve_request = matrix_sdk::ruma::api::client::alias::get_alias::v3::Request::new(&alias); match client.send(resolve_request, None).await { Ok(result) => { let matrix_sdk::ruma::api::client::alias::get_alias::v3::Response{room_id, ..} = result; mapping.room_alias = Some(mapping.room_id.clone()); mapping.room_id = room_id.to_string(); }, Err(_e) => (), }; }let a = ruma::RoomAliasId::parse(&String::from("abc")); } room_aliases_resolved = true; } clients.push(client.clone()); } clients } async fn client_from_mxid(mxid: &str, clients: &Vec) -> Option { for client in clients { if client.user_id().await.unwrap().as_str() == mxid { return Some(client.to_owned()); } } None } pub async fn send(from_mail: &Option, recipient: &Mailbox, plain_content: &str, html_content: &str, clients: &Vec, mappings: &Vec) { for mapping in mappings { let mut applies = true; if let Some(from) = &mapping.from { if let Some(mailbox) = from_mail { if from != &format!("{}@{}", mailbox.local, mailbox.domain.0) { applies = false; } } } if let Some(to) = &mapping.to { if to != &format!("{}@{}", recipient.local, recipient.domain.0) { applies = false; } } if applies { let local = &recipient.local; let domain = &recipient.domain.0; let sender_mxid = match &mapping.mxid_sender { Some(s) => s.to_owned(), None => { format!("@{}:{}", local, domain) }, }; if let Some(c) = client_from_mxid(&sender_mxid, clients).await { if let Ok(roomid) = RoomId::parse(&mapping.room_id) { match c.sync_once(SyncSettings::default()).await { Ok(_) => (), Err(_e) => (), }; let room = match c.get_room(&roomid) { Some(Room::Joined(room)) => room, Some(Room::Invited(room)) => { match room.accept_invitation().await { Ok(_) => (), Err(_e) => println!("Could not accept invitation"), }; // Continuously check whether the room has been joined. // Joins can be significantly delayed, depending on the room and the server let mut joined = false; let mut counter = 0; while !joined && counter < 10{ match c.get_room(&roomid) { Some(Room::Joined(_)) => joined = true, _ => (), } match c.sync_once(SyncSettings::default()).await { Ok(_) => (), Err(_e) => (), }; std::thread::sleep(std::time::Duration::from_millis(u64::pow(2, counter) * 100)); counter += 1; } if let Some(Room::Joined(joined)) = c.get_room(&roomid) { joined } else { println!("Joining room timed out."); continue; } }, _ => { println!("Room either left or unfound."); continue; } }; match room.send(RoomMessageEventContent::text_html(plain_content, html_content), None).await { Ok(_) => (), Err(_e) => println!("Sending message failed"), }; } } } } }