From 6facc03a637e0028c7faf179ce0193373e0b86ed Mon Sep 17 00:00:00 2001 From: Dan Ballard Date: Mon, 4 Apr 2022 18:12:51 -0700 Subject: [PATCH] adding responding to messages, parsing response, offering share file; adding greeting ability; adding accepting contacts and adding profile pic (when supported by libcwtch-rs --- Cargo.lock | 2 - Cargo.toml | 2 +- build_bot.png | Bin 0 -> 8679 bytes src/event.rs | 7 +++ src/main.rs | 147 +++++++++++++++++++++++++++++++++++++++++++++++--- 5 files changed, 147 insertions(+), 11 deletions(-) create mode 100644 build_bot.png diff --git a/Cargo.lock b/Cargo.lock index e42704e..4f2405d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -124,8 +124,6 @@ checksum = "1b03d17f364a3a042d5e5d46b053bbbf82c92c9430c592dd4c064dc6ee997125" [[package]] name = "libcwtch" version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a441fe0922d39eaa632dad730ad587c52d682e0a394c35be335e93a7f7ff557a" dependencies = [ "hex-literal", "libc", diff --git a/Cargo.toml b/Cargo.toml index 6163ce8..5e31d83 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,6 +6,6 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -libcwtch = "0.2.0" +libcwtch = {path = "../libcwtch-rs" } #"0.2.0" serde_json = "1.0" diff --git a/build_bot.png b/build_bot.png new file mode 100644 index 0000000000000000000000000000000000000000..316ff5a8c4ce106ee8a18713423800f0ed78e145 GIT binary patch literal 8679 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 AMgRZ+ literal 0 HcmV?d00001 diff --git a/src/event.rs b/src/event.rs index 812225d..a5c3e52 100644 --- a/src/event.rs +++ b/src/event.rs @@ -1,9 +1,13 @@ +#[derive(Debug)] pub enum Event { CwtchStarted, NewPeer, NewMessageFromPeer, AppError, + ContactCreated, + PeerStateChange, + UpdateGlobalSettings, ErrUnhandled(String), } @@ -15,6 +19,9 @@ impl Event { "NewPeer" => Event::NewPeer, "NewMessageFromPeer" => Event::NewMessageFromPeer, "AppError" => Event::AppError, + "ContactCreated" => Event::ContactCreated, + "PeerStateChange" => Event::PeerStateChange, + "UpdateGlobalSettings" => Event::UpdateGlobalSettings, _ => Event::ErrUnhandled(name.to_string()), } } diff --git a/src/main.rs b/src/main.rs index 647f264..7b6acfc 100644 --- a/src/main.rs +++ b/src/main.rs @@ -20,6 +20,7 @@ const BOT_HOME: &str = "~/.cwtch/bots/update_bot"; const PASSWORD: &str = "be gay do crime"; struct UpdateBot { + settings: Option, profile: Option, versions_dirs: Vec, } @@ -35,7 +36,7 @@ impl UpdateBot { version_dirs.push(path); } } - let bot = UpdateBot{ versions_dirs: version_dirs, profile: None}; + let bot = UpdateBot{ versions_dirs: version_dirs, profile: None, settings: None}; println!("versions: {:?}\n", bot.versions_dirs); return bot } @@ -58,7 +59,7 @@ fn main() { // approve all friends - // offer newst version if none or now newest (question about os followed by file strasfer) + // offer newest version if none or now newest (question about os followed by file strasfer) // for all friends, store offered version as attr // respond to simple commands, include links, help info @@ -86,6 +87,27 @@ fn main() { } } + Event::UpdateGlobalSettings => { + println!("Loading settings froms {}", &event.data["Data"]); + let mut settings: Settings = match serde_json::from_str(&event.data["Data"]) { + Ok(s) => s, + Err(e) => panic!("invalid json: {:?}", e), + }; + settings.ExperimentsEnabled = true; + settings.Experiments.insert(Experiments::FileSharingExperiment.to_key_string(),true); + settings.Experiments.insert(Experiments::ImagePreviewsExperiment.to_key_string(),true); + match settings.save(&cwtch) { + Ok(_) => (), + Err(e) => println!("ERROR: could not save settings: {}", e) + }; + match update_bot.profile.as_ref() { + Some(profile) => { + cwtch.share_file(&profile.onion, -1, "build_bot.png"); + }, + None => (), + }; + update_bot.settings = Some(settings); + } Event::NewPeer => { println!( "\n***** {} at {} *****\n", @@ -104,28 +126,137 @@ fn main() { Err(e) => panic!("error parsing profile: {}", e), }; print!("profile: {:?}", profile); + // Share profile image + match update_bot.settings.as_ref() { + Some(_settings) => { + cwtch.share_file(&profile.onion, -1, "build_bot.png"); + }, + None => (), + }; + + for (_id, contact) in &profile.contacts { + if contact.accepted != true { + cwtch.accept_conversation(profile.onion.as_str(), contact.identifier) + } + } update_bot.profile = Some(profile); } Event::AppError => { if initialized && event.data["Error"] == "Loaded 0 profiles" { - cwtch.create_profile("Echobot", PASSWORD); + cwtch.create_profile("Upgrade Bot", PASSWORD); + } + } + Event::ContactCreated => { + if event.data["ConnectionState"] == "Authenticated" { + let profile_onion = event.data["RemotePeer"].to_string(); + let convo_id = event.data["ConversationID"].parse::().unwrap(); + + let contact = Contact{ + onion: profile_onion.clone(), + identifier: event.data["ConversationID"].parse::().unwrap(), + name: event.data["nick"].to_string(), + status: ConnectionState::new(&event.data["status"]), + blocked: event.data["blocked"] == "true", + accepted: event.data["accepted"] == "true", + is_group: false, // by definition + }; + + if contact.accepted != true { + cwtch.accept_conversation(&contact.onion.clone(), convo_id) + } + + match update_bot.profile.as_mut() { + Some(profile) => { + profile.contacts.insert(event.data["RemotePeer"].to_string(), contact); + } + None => () + }; + + update_bot.greet(&cwtch, convo_id); + } + } + + Event::PeerStateChange => { + if event.data["ConnectionState"] == "Authenticated" { + match update_bot.profile.as_ref() { + Some(profile) => { + let contact = &profile.contacts[&event.data["RemotePeer"]]; + if contact.accepted != true { + cwtch.accept_conversation(profile.onion.as_str(), contact.identifier) + } + println!("Sending greeting as peer came online"); + update_bot.greet(&cwtch, contact.identifier); + } + None => () + }; } } Event::NewMessageFromPeer => { let to = &event.data["ProfileOnion"]; let conversation_id = event.data["ConversationID"].parse::().unwrap(); - let message: Message = + let message_wrapper: Message = serde_json::from_str(&event.data["Data"]).expect("Error parsing message"); - let response = Message { o: 1, d: message.d }; - let response_json = - serde_json::to_string(&response).expect("Error parsing json response"); - cwtch.send_message(&to, conversation_id, &response_json); + let latest_version = &update_bot.versions_dirs[update_bot.versions_dirs.len()-1]; + let version = latest_version.strip_prefix(DIST_DIR).unwrap().to_str().unwrap(); + + + let mut message = message_wrapper.d.clone(); + message.make_ascii_lowercase(); + + match message.as_str() { + "windows" => { + let mut windows_path = latest_version.clone(); + windows_path.push("cwtch-installer.exe"); + cwtch.share_file(&to, conversation_id, windows_path.to_str().unwrap()); + }, + "linux" => { + let mut linux_path = latest_version.clone(); + linux_path.push(format!("cwtch-{}.tar.gz", version)); + cwtch.share_file(&to, conversation_id, linux_path.to_str().unwrap()); + }, + "macos" => { + let mut mac_path = latest_version.clone(); + mac_path.push("Cwtch.dmg"); + cwtch.share_file(&to, conversation_id, mac_path.to_str().unwrap()); + }, + "android" => { + let mut android_path = latest_version.clone(); + android_path.push("app-release.apk"); + cwtch.share_file(&to, conversation_id, android_path.to_str().unwrap()); + } + _ => { + let resp_message = format!("Currently offering Cwtch {}\nPlease respond with the OS you would like a package for:\n- Windows\n- Android\n- MacOS\n- Linux", version); + let response = Message { o: 1, d: resp_message }; + let response_json = + serde_json::to_string(&response).expect("Error parsing json response"); + cwtch.send_message(&to, conversation_id, &response_json); + } + + } } Event::ErrUnhandled(err) => eprintln!("unhandled event: {}!", err), + _ => print!("unhandled event: {:?}!", event_type) }; } }); event_loop_handle.join().expect("Error running event loop"); } + +impl UpdateBot { + pub fn greet(&self, cwtch: &dyn CwtchLib, convo_id: i32) { + match self.profile.as_ref() { + Some(profile) => { + // TODO throttle as we seem to be able to get a bunch of Authenticated messages + // TODO getAttribute what was the last version we offered, if there is a newer, make the offer, update attr + println!("Sending greeting as peer came online"); + let greeting = Message { o: 1, d: "Hello".to_string() }; + let greeting_json = + serde_json::to_string(&greeting).expect("Error parsing json response"); + cwtch.send_message(profile.onion.as_ref(), convo_id, &greeting_json); + } + None => () + }; + } +}