From cb1f90f240694eec4f171b73e9625315a02f65a1 Mon Sep 17 00:00:00 2001 From: Ryan Voots Date: Fri, 28 Aug 2020 11:32:27 -0700 Subject: [PATCH] Final code bits, now to clippy --- src/main.rs | 112 +++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 106 insertions(+), 6 deletions(-) diff --git a/src/main.rs b/src/main.rs index 68ea4c3..aeb3717 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,13 +1,16 @@ +#![feature(async_closure)] use async_trait::async_trait; use matrix_sdk::{ self, events::{ - room::message::{MessageEventContent, TextMessageEventContent}, - AnyMessageEventContent, SyncMessageEvent, + room::{ + member::MemberEventContent, + message::{MessageEventContent, TextMessageEventContent}, + }, + AnyMessageEventContent, AnyToDeviceEvent, StrippedStateEvent, SyncMessageEvent, }, - identifiers::RoomId, locks::RwLock, - Client, ClientConfig, EventEmitter, JsonStore, Room, SyncRoom, SyncSettings, + Client, ClientConfig, EventEmitter, JsonStore, Room, Sas, SyncRoom, SyncSettings, }; use reqwest; use serde_json; @@ -15,6 +18,7 @@ use std::{collections::HashMap, env, process::exit, sync::Arc}; use url::Url; + // { // "saidobj": { // "raw_body": "hi", @@ -139,6 +143,25 @@ impl CommandBot { } } +async fn wait_for_confirmation(sas: Sas) { + println!("Emoji: {:?}", sas.emoji()); + + // TODO make this verify things somehow, I can't do it interactively so I think send them in a + // message? maybe render them into an image and send that, so it's less interceptable + sas.confirm().await.unwrap(); +} + +fn print_result(sas: Sas) { + let device = sas.other_device(); + + println!( + "Successfully verified device {} {} {:?}", + device.user_id(), + device.device_id(), + device.trust_state() + ); +} + #[async_trait] impl EventEmitter for CommandBot { async fn on_room_message(&self, room: SyncRoom, event: &SyncMessageEvent) { @@ -154,7 +177,13 @@ impl EventEmitter for CommandBot { let user_id = format!("{}:{}", &user_name, &user_server); // construct a canonical user_id for them let myself = self.client.user_id().await.unwrap(); - println!("Checking message: {} {} {} {:?}", msg_body, sender.localpart(), sender.server_name(), sender); + println!( + "Checking message: {} {} {} {:?}", + msg_body, + sender.localpart(), + sender.server_name(), + sender + ); if (myself.localpart() == user_name && myself.server_name() == user_server) { println!("Saw my own message, ignoring it"); @@ -170,6 +199,32 @@ impl EventEmitter for CommandBot { } } } + + async fn on_stripped_state_member( + &self, + room: SyncRoom, + room_member: &StrippedStateEvent, + event: Option, + ) + { + println!("STRIPPED: {:?}", event); + + if room_member.state_key != self.client.user_id().await.unwrap() { + return; + } + + if let SyncRoom::Invited(room) = room { + let room = room.read().await; + + println!("Autojoining room {}", room.display_name()); + + self + .client + .join_room_by_id(&room.room_id) + .await + .expect("Can't join room"); + } + } } async fn login_and_sync(homeserver_url: String, username: String, password: String) -> Result<(), matrix_sdk::Error> { @@ -203,8 +258,53 @@ async fn login_and_sync(homeserver_url: String, username: String, password: Stri // since we called sync before we `sync_forever` we must pass that sync token to // `sync_forever` let settings = SyncSettings::default().token(client.sync_token().await.unwrap()); + + let client_ref = &client; // this keeps state from the server streaming in to CommandBot via the EventEmitter trait - client.sync_forever(settings, |_| async {}).await; + client + .sync_forever(settings, async move |response| { + let client = &client_ref; + + for event in &response.to_device.events { + let e_maybe = event.deserialize(); + + match e_maybe { + Ok(AnyToDeviceEvent::KeyVerificationStart(e)) => { + let sas = client + .get_verification(&e.content.transaction_id) + .await + .expect("Sas object wasn't created"); + + sas.accept().await.unwrap(); + } + + Ok(AnyToDeviceEvent::KeyVerificationKey(e)) => { + let sas = client + .get_verification(&e.content.transaction_id) + .await + .expect("Sas object wasn't created"); + + tokio::spawn(wait_for_confirmation(sas)); + } + + Ok(AnyToDeviceEvent::KeyVerificationMac(e)) => { + let sas = client + .get_verification(&e.content.transaction_id) + .await + .expect("Sas object wasn't created"); + + if sas.is_done() { + print_result(sas); + } + } + Ok(_) => (), // Unknown or unhandled event + Err(error) => { + eprintln!("Couldn't deserialize to to-device event: {:?} from {:?}", error, event); + } + } + } + }) + .await; Ok(()) }