diff --git a/src/main.rs b/src/main.rs index 7b6acfc..08b0ff1 100644 --- a/src/main.rs +++ b/src/main.rs @@ -19,24 +19,34 @@ const DIST_DIR: &str = "cwtch_dist"; const BOT_HOME: &str = "~/.cwtch/bots/update_bot"; const PASSWORD: &str = "be gay do crime"; +const BOT_NAME: &str = "Update Bot"; + +const LAST_OFFERED_KEY: &str = "profile.last_version_offered"; + struct UpdateBot { settings: Option, profile: Option, versions_dirs: Vec, + latest_version: PathBuf, + version: String, } impl UpdateBot { pub fn new() -> Self { - let mut version_dirs = vec![]; + let mut versions_dirs = vec![]; for entry in read_dir(Path::new(DIST_DIR)).expect(&format!("could not open '{}' dir", DIST_DIR)) { let entry = entry.unwrap(); let path: PathBuf = entry.path(); if path.is_dir() { println!("version: {}", path.to_str().unwrap()); - version_dirs.push(path); + versions_dirs.push(path); } } - let bot = UpdateBot{ versions_dirs: version_dirs, profile: None, settings: None}; + versions_dirs.sort(); + println!("sorted vd: {:?}", versions_dirs); + let latest_version = versions_dirs[versions_dirs.len()-1].clone(); + let version: String = latest_version.strip_prefix(DIST_DIR).unwrap().to_str().unwrap().to_string(); + let bot = UpdateBot{ versions_dirs: versions_dirs, profile: None, settings: None, latest_version: latest_version, version: version}; println!("versions: {:?}\n", bot.versions_dirs); return bot } @@ -95,14 +105,15 @@ fn main() { }; settings.ExperimentsEnabled = true; settings.Experiments.insert(Experiments::FileSharingExperiment.to_key_string(),true); - settings.Experiments.insert(Experiments::ImagePreviewsExperiment.to_key_string(),true); + // TODO delete + settings.Experiments.insert(Experiments::ImagePreviewsExperiment.to_key_string(),false); 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"); + cwtch.share_file(&profile.handle, -1, "build_bot.png"); }, None => (), }; @@ -114,7 +125,7 @@ fn main() { event.data["name"], event.data["Identity"] ); - // process json for profile, contacts and servers...else { + // process json for profile, conversations and servers...else { let profile = match Profile::new( &event.data["Identity"], &event.data["name"], @@ -129,21 +140,22 @@ fn main() { // Share profile image match update_bot.settings.as_ref() { Some(_settings) => { - cwtch.share_file(&profile.onion, -1, "build_bot.png"); + cwtch.share_file(&profile.handle, -1, "build_bot.png"); }, None => (), }; - for (_id, contact) in &profile.contacts { - if contact.accepted != true { - cwtch.accept_conversation(profile.onion.as_str(), contact.identifier) + cwtch.set_profile_attribute(&profile.handle, "profile.name", BOT_NAME); + for (_id, conversation) in &profile.conversations { + if conversation.accepted != true { + cwtch.accept_conversation(profile.handle.as_str(), conversation.identifier) } } update_bot.profile = Some(profile); } Event::AppError => { if initialized && event.data["Error"] == "Loaded 0 profiles" { - cwtch.create_profile("Upgrade Bot", PASSWORD); + cwtch.create_profile(BOT_NAME, PASSWORD); } } Event::ContactCreated => { @@ -151,23 +163,26 @@ fn main() { let profile_onion = event.data["RemotePeer"].to_string(); let convo_id = event.data["ConversationID"].parse::().unwrap(); - let contact = Contact{ - onion: profile_onion.clone(), + let acl: ACL = serde_json::from_str(&event.data["accessControlList"]).expect("Error parsing conversation"); + + let conversation = Conversation { + handle: 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", + access_control_list: acl, is_group: false, // by definition }; - if contact.accepted != true { - cwtch.accept_conversation(&contact.onion.clone(), convo_id) + if conversation.accepted != true { + cwtch.accept_conversation(&conversation.handle.clone(), convo_id) } match update_bot.profile.as_mut() { Some(profile) => { - profile.contacts.insert(event.data["RemotePeer"].to_string(), contact); + profile.conversations.insert(event.data["RemotePeer"].to_string(), conversation); } None => () }; @@ -180,12 +195,11 @@ fn main() { 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) + let conversation = &profile.conversations[&event.data["RemotePeer"]]; + if conversation.accepted != true { + cwtch.accept_conversation(profile.handle.as_str(), conversation.identifier) } - println!("Sending greeting as peer came online"); - update_bot.greet(&cwtch, contact.identifier); + update_bot.greet(&cwtch, conversation.identifier); } None => () }; @@ -197,40 +211,32 @@ fn main() { let message_wrapper: Message = serde_json::from_str(&event.data["Data"]).expect("Error parsing message"); - 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(); + let mut windows_path = update_bot.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)); + let mut linux_path = update_bot.latest_version.clone(); + linux_path.push(format!("cwtch-{}.tar.gz", update_bot.version)); cwtch.share_file(&to, conversation_id, linux_path.to_str().unwrap()); }, "macos" => { - let mut mac_path = latest_version.clone(); + let mut mac_path = update_bot.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(); + let mut android_path = update_bot.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); + update_bot.offer(&cwtch, conversation_id); } } @@ -248,13 +254,33 @@ 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); + let do_offer = match cwtch.get_conversation_attribute(&profile.handle, convo_id, &format!("local.{}", LAST_OFFERED_KEY)) { + Ok(ret) => match ret { + Some(last_offered) => last_offered != self.version, + None => true, + }, + Err(e) => { + println!("Error parsing attribute: {}", e); + false + } + }; + if do_offer { + self.offer(cwtch, convo_id); + cwtch.set_conversation_attribute(&profile.handle, convo_id, LAST_OFFERED_KEY, &self.version); + } + } + None => () + }; + } + + pub fn offer(&self, cwtch: &dyn CwtchLib, convo_id: i32) { + match self.profile.as_ref() { + Some(profile) => { + 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", self.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(&profile.handle, convo_id, &response_json); } None => () };