use color_eyre::Result; use matrix_sdk::{ config::{ClientConfig, SyncSettings}, room::Room, ruma::{ api::client::r0::uiaa, assign, events::{ room::message::{MessageType, RoomMessageEventContent, TextMessageEventContent}, SyncMessageEvent, }, UserId, }, Client, }; use serde::{Deserialize, Serialize}; use std::{env, path::PathBuf}; #[derive(Debug, Clone, Deserialize, Serialize)] pub struct Config { username: Box, password: String, #[serde(rename = "clientID")] client_id: String, #[serde(rename = "keysPath")] key_path: PathBuf, #[serde(rename = "storePath")] store_path: PathBuf, } pub const APPLICATION_NAME: &str = concat!(env!("CARGO_PKG_NAME"), "/", env!("CARGO_PKG_VERSION"),); #[tokio::main] async fn main() -> Result<()> { tracing_subscriber::fmt::init(); color_eyre::install()?; let cfg: Config = serde_dhall::from_file(env::var("CONFIG_PATH").unwrap_or("./config.dhall".to_string())) .parse()?; let ccfg = ClientConfig::new() .store_path(cfg.store_path) .user_agent(APPLICATION_NAME)?; let client = Client::new_from_user_id_with_config(&cfg.username, ccfg).await?; // First we need to log in. client .login(cfg.username.localpart(), &cfg.password, None, None) .await?; // Ignore old messages client.sync_once(SyncSettings::default()).await?; client.register_event_handler(on_room_message).await; // Syncing is important to synchronize the client state with the server. // This method will never return. client.sync(SyncSettings::default()).await; Ok(()) } async fn unfuck_crypto(client: Client, cfg: &Config) { if let Err(e) = client.bootstrap_cross_signing(None).await { if let Some(response) = e.uiaa_response() { let auth_data = uiaa::AuthData::Password(assign!( uiaa::Password::new(uiaa::UserIdentifier::MatrixId(&*cfg.username.as_str()), &cfg.password), { session: response.session.as_deref() } )); client .bootstrap_cross_signing(Some(auth_data)) .await .expect("Couldn't bootstrap cross signing") } else { panic!("Error durign cross signing bootstrap {:#?}", e); } } } async fn on_room_message(event: SyncMessageEvent, room: Room) { if let Room::Joined(room) = room { let msg_body = match event.content.msgtype { MessageType::Text(TextMessageEventContent { body, .. }) => body, _ => return, }; if msg_body.contains("!party") { let content = RoomMessageEventContent::text_plain("🎉🎊🥳 let's PARTY!! 🥳🎊🎉"); println!("sending"); // send our message to the room we found the "!party" command in // the last parameter is an optional transaction id which we don't // care about. room.send(content, None).await.unwrap(); println!("message sent"); } } }