use std::collections::*; use std::path::PathBuf; use std::sync::Arc; use tokio::io::{AsyncRead, AsyncReadExt}; use tokio::sync::mpsc; use futures::prelude::*; //use ruma_client::Client; //use ruma_client_api::r0::message as rumamessage; //use ruma_events::{self, room::message::*}; use matrix_sdk::events::{ room::message::{MessageEventContent, TextMessageEventContent}, AnyMessageEventContent, }; use matrix_sdk::identifiers::RoomId; use matrix_sdk::uuid::Uuid; use crate::config::*; #[derive(Debug)] pub enum Error { BadUrl, UnknownRoom(RoomId), Matrix(matrix_sdk::Error), } pub struct Message { dest_room: RoomId, text: String, delay_secs: u32, } pub type MatrixClient = matrix_sdk::Client; impl Message { pub fn new(dest_room: RoomId, msg: String) -> Self { Self::new_delay(dest_room, msg, 0) } pub fn new_delay(dest_room: RoomId, text: String, delay_secs: u32) -> Self { Self { dest_room, text, delay_secs, } } } pub async fn create_and_auth_client(acct: Account) -> Result, Error> { let hs_url = url::Url::parse(&acct.homeserver).map_err(|_| Error::BadUrl)?; let cc = matrix_sdk::ClientConfig::new() .user_agent("mtxspooler") .unwrap(); let c = matrix_sdk::Client::new_with_config(hs_url, cc).map_err(Error::Matrix)?; // Now log in. match acct.auth { Auth::UsernamePass(un, pw) => { let didref = acct.device_id.as_deref(); c.login(&un, &pw, didref, didref) .map_err(Error::Matrix) .await?; } } Ok(Arc::new(c)) } pub async fn submit_messages(cli: Arc, mut recv: mpsc::Receiver) { while let Some(msg) = recv.recv().await { if let Err(e) = do_submit_msg(&msg, &cli).await { panic!("[client] error handling message submission: {:?}", e); } } } async fn do_submit_msg(msg: &Message, cli: &Arc) -> Result<(), Error> { let jroom = get_room_try_join(cli, &msg.dest_room).await?; let mec = MessageEventContent::text_plain(&msg.text); let ec = AnyMessageEventContent::RoomMessage(mec); jroom.send(ec, None).map_err(Error::Matrix).await?; Ok(()) } pub async fn get_room_try_join( cli: &Arc, rid: &RoomId, ) -> Result { use matrix_sdk::room::*; match cli .get_room(rid) .ok_or_else(|| Error::UnknownRoom(rid.clone()))? { Room::Joined(j) => Ok(j), Room::Invited(i) => { i.accept_invitation().map_err(Error::Matrix).await?; Ok(cli.get_joined_room(rid).expect("client: get invited room")) } Room::Left(l) => { l.join().map_err(Error::Matrix).await?; Ok(cli.get_joined_room(rid).expect("client: get room joined")) } } } fn gen_device_id(un: &str, pw: &str) -> String { use sha2::Digest; let mut hasher = sha2::Sha256::new(); hasher.update(un.as_bytes()); hasher.update("\0"); hasher.update(pw.as_bytes()); hasher.update("\0_mtxspooler_salt"); let h: [u8; 32] = hasher.finalize().into(); hex::encode(h) }