split into proto bot framework and update bot specific impl
This commit is contained in:
parent
c42d73bb86
commit
4daa4b071e
|
@ -0,0 +1,193 @@
|
||||||
|
use libcwtch::structs::*;
|
||||||
|
use libcwtch::CwtchLib;
|
||||||
|
use crate::Event;
|
||||||
|
|
||||||
|
use serde_json;
|
||||||
|
use crate::bot::DefaultContactPolicy::Accept;
|
||||||
|
|
||||||
|
pub enum DefaultContactPolicy {
|
||||||
|
Ignore,
|
||||||
|
Block,
|
||||||
|
Accept,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Behaviour {
|
||||||
|
pub proto_experiments: bool,
|
||||||
|
pub proto_experiment_fileshare: bool,
|
||||||
|
|
||||||
|
pub profile_name: String,
|
||||||
|
pub profile_pic_path: Option<String>,
|
||||||
|
|
||||||
|
pub default_contant_policy: DefaultContactPolicy,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Behaviour {
|
||||||
|
pub fn new_default_acceptor(name: String, profile_pic_path: String) -> Self {
|
||||||
|
return Behaviour{
|
||||||
|
proto_experiments: true,
|
||||||
|
proto_experiment_fileshare: true,
|
||||||
|
default_contant_policy: Accept,
|
||||||
|
profile_name: name,
|
||||||
|
profile_pic_path: Some(profile_pic_path),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait EventHandler {
|
||||||
|
fn handle(&self, cwtch: &dyn CwtchLib, profile: Option<&Profile>, event: CwtchEvent);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Bot {
|
||||||
|
cwtch: Box<dyn CwtchLib>,
|
||||||
|
behaviour: Behaviour,
|
||||||
|
password: String,
|
||||||
|
home_dir: String,
|
||||||
|
|
||||||
|
settings: Option<Settings>,
|
||||||
|
profile: Option<Profile>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Bot {
|
||||||
|
pub fn new(behaviour: Behaviour, password: String, home_dir: String) -> Self {
|
||||||
|
let cwtch = libcwtch::new_cwtchlib_go();
|
||||||
|
println!("start_cwtch");
|
||||||
|
let ret = cwtch.start_cwtch(&home_dir, "");
|
||||||
|
println!("start_cwtch returned {}", ret);
|
||||||
|
|
||||||
|
return Bot{behaviour, cwtch: Box::new(cwtch), password, home_dir, profile: None, settings: None}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn event_loop(&mut self, handler: Box<dyn EventHandler>) {
|
||||||
|
let mut initialized: bool = false;
|
||||||
|
|
||||||
|
loop {
|
||||||
|
let event_str = self.cwtch.get_appbus_event();
|
||||||
|
println!("bot: event: {}", event_str);
|
||||||
|
|
||||||
|
let event: CwtchEvent =
|
||||||
|
serde_json::from_str(&event_str).expect("Error parsing Cwtch event");
|
||||||
|
let event_type = Event::new(event.event_type.as_str());
|
||||||
|
match event_type {
|
||||||
|
Event::CwtchStarted => {
|
||||||
|
println!("event CwtchStarted!");
|
||||||
|
initialized = true;
|
||||||
|
|
||||||
|
match self.profile {
|
||||||
|
None => {
|
||||||
|
println!("Creating bot");
|
||||||
|
self.cwtch.load_profiles(&self.password);
|
||||||
|
}
|
||||||
|
Some(_) => (),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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),
|
||||||
|
};
|
||||||
|
|
||||||
|
if self.behaviour.proto_experiments {
|
||||||
|
settings.ExperimentsEnabled = true;
|
||||||
|
}
|
||||||
|
if self.behaviour.proto_experiment_fileshare {
|
||||||
|
settings
|
||||||
|
.Experiments
|
||||||
|
.insert(Experiments::FileSharingExperiment.to_key_string(), true);
|
||||||
|
}
|
||||||
|
match settings.save(self.cwtch.as_ref()) {
|
||||||
|
Ok(_) => (),
|
||||||
|
Err(e) => println!("ERROR: could not save settings: {}", e),
|
||||||
|
};
|
||||||
|
|
||||||
|
match self.profile.as_ref() {
|
||||||
|
Some(profile) => {
|
||||||
|
if let Some(profile_pic_path) = &self.behaviour.profile_pic_path {
|
||||||
|
self.cwtch.share_file(&profile.handle, -1, profile_pic_path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None => (),
|
||||||
|
};
|
||||||
|
|
||||||
|
self.settings = Some(settings);
|
||||||
|
}
|
||||||
|
Event::NewPeer => {
|
||||||
|
println!(
|
||||||
|
"\n***** {} at {} *****\n",
|
||||||
|
event.data["name"], event.data["Identity"]
|
||||||
|
);
|
||||||
|
|
||||||
|
// process json for profile, conversations and servers...else {
|
||||||
|
let profile = match Profile::new(
|
||||||
|
&event.data["Identity"],
|
||||||
|
&event.data["name"],
|
||||||
|
&event.data["picture"],
|
||||||
|
&event.data["ContactsJson"],
|
||||||
|
&event.data["ServerList"],
|
||||||
|
) {
|
||||||
|
Ok(p) => p,
|
||||||
|
Err(e) => panic!("error parsing profile: {}", e),
|
||||||
|
};
|
||||||
|
print!("profile: {:?}", profile);
|
||||||
|
// Share profile image
|
||||||
|
match self.settings.as_ref() {
|
||||||
|
Some(_settings) => {
|
||||||
|
self.cwtch.share_file(&profile.handle, -1, "build_bot.png");
|
||||||
|
}
|
||||||
|
None => (),
|
||||||
|
};
|
||||||
|
|
||||||
|
self.cwtch.set_profile_attribute(&profile.handle, "profile.name", &self.behaviour.profile_name);
|
||||||
|
|
||||||
|
self.profile = Some(profile);
|
||||||
|
}
|
||||||
|
Event::AppError => {
|
||||||
|
if initialized && event.data["Error"] == "Loaded 0 profiles" {
|
||||||
|
self.cwtch.create_profile(&self.behaviour.profile_name, &self.password);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Event::ContactCreated => {
|
||||||
|
if event.data["ConnectionState"] == "Authenticated" {
|
||||||
|
let profile_onion = event.data["RemotePeer"].to_string();
|
||||||
|
let convo_id = event.data["ConversationID"].parse::<i32>().unwrap();
|
||||||
|
|
||||||
|
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::<i32>().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
|
||||||
|
};
|
||||||
|
|
||||||
|
match self.behaviour.default_contant_policy {
|
||||||
|
DefaultContactPolicy::Accept =>
|
||||||
|
self.cwtch.accept_conversation(&conversation.handle.clone(), convo_id),
|
||||||
|
DefaultContactPolicy::Block =>
|
||||||
|
self.cwtch.block_contact(&conversation.handle.clone(), convo_id),
|
||||||
|
DefaultContactPolicy::Ignore => (),
|
||||||
|
}
|
||||||
|
|
||||||
|
match self.profile.as_mut() {
|
||||||
|
Some(profile) => {
|
||||||
|
profile
|
||||||
|
.conversations
|
||||||
|
.insert(event.data["RemotePeer"].to_string(), conversation);
|
||||||
|
}
|
||||||
|
None => (),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Event::ErrUnhandled(err) => eprintln!("unhandled event: {}!", err),
|
||||||
|
_ => (),
|
||||||
|
};
|
||||||
|
|
||||||
|
handler.handle(self.cwtch.as_ref(), self.profile.as_ref(), event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
350
src/main.rs
350
src/main.rs
|
@ -1,4 +1,5 @@
|
||||||
mod event;
|
mod event;
|
||||||
|
mod bot;
|
||||||
|
|
||||||
extern crate core;
|
extern crate core;
|
||||||
|
|
||||||
|
@ -13,6 +14,7 @@ use serde_json;
|
||||||
use libcwtch;
|
use libcwtch;
|
||||||
use libcwtch::structs::*;
|
use libcwtch::structs::*;
|
||||||
use libcwtch::CwtchLib;
|
use libcwtch::CwtchLib;
|
||||||
|
use crate::bot::{Behaviour, Bot};
|
||||||
|
|
||||||
const DIST_DIR: &str = "cwtch_dist";
|
const DIST_DIR: &str = "cwtch_dist";
|
||||||
const BOT_HOME: &str = "~/.cwtch/bots/update_bot";
|
const BOT_HOME: &str = "~/.cwtch/bots/update_bot";
|
||||||
|
@ -23,8 +25,6 @@ const BOT_NAME: &str = "Update Bot";
|
||||||
const LAST_OFFERED_KEY: &str = "profile.last_version_offered";
|
const LAST_OFFERED_KEY: &str = "profile.last_version_offered";
|
||||||
|
|
||||||
struct UpdateBot {
|
struct UpdateBot {
|
||||||
settings: Option<Settings>,
|
|
||||||
profile: Option<Profile>,
|
|
||||||
versions_dirs: Vec<PathBuf>,
|
versions_dirs: Vec<PathBuf>,
|
||||||
latest_version: PathBuf,
|
latest_version: PathBuf,
|
||||||
version: String,
|
version: String,
|
||||||
|
@ -54,8 +54,6 @@ impl UpdateBot {
|
||||||
.to_string();
|
.to_string();
|
||||||
let bot = UpdateBot {
|
let bot = UpdateBot {
|
||||||
versions_dirs: versions_dirs,
|
versions_dirs: versions_dirs,
|
||||||
profile: None,
|
|
||||||
settings: None,
|
|
||||||
latest_version: latest_version,
|
latest_version: latest_version,
|
||||||
version: version,
|
version: version,
|
||||||
};
|
};
|
||||||
|
@ -65,261 +63,127 @@ impl UpdateBot {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
// load file, parse version
|
|
||||||
if !Path::new(DIST_DIR).exists() {
|
if !Path::new(DIST_DIR).exists() {
|
||||||
panic!("no '{}' directory with versions to distribute", DIST_DIR)
|
panic!("no '{}' directory with versions to distribute", DIST_DIR)
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut update_bot = UpdateBot::new();
|
let mut update_bot = UpdateBot::new();
|
||||||
|
let behaviour: Behaviour = Behaviour::new_default_acceptor(BOT_NAME.to_string(), "build_bot.png".to_string());
|
||||||
// make cwtch bot
|
|
||||||
let cwtch = libcwtch::new_cwtchlib_go();
|
|
||||||
println!("start_cwtch");
|
|
||||||
let ret = cwtch.start_cwtch(BOT_HOME, "");
|
|
||||||
println!("start_cwtch returned {}", ret);
|
|
||||||
|
|
||||||
// approve all friends
|
|
||||||
// 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
|
|
||||||
|
|
||||||
let event_loop_handle = thread::spawn(move || {
|
let event_loop_handle = thread::spawn(move || {
|
||||||
let mut initialized: bool = false;
|
let mut bot = Bot::new(behaviour, PASSWORD.to_string(), BOT_HOME.to_string());
|
||||||
|
|
||||||
loop {
|
bot.event_loop(Box::new(update_bot));
|
||||||
let event_str = cwtch.get_appbus_event();
|
|
||||||
println!("event: {}", event_str);
|
|
||||||
|
|
||||||
let event: CwtchEvent =
|
|
||||||
serde_json::from_str(&event_str).expect("Error parsing Cwtch event");
|
|
||||||
let event_type = Event::new(event.event_type.as_str());
|
|
||||||
match event_type {
|
|
||||||
Event::CwtchStarted => {
|
|
||||||
println!("event CwtchStarted!");
|
|
||||||
initialized = true;
|
|
||||||
|
|
||||||
match update_bot.profile {
|
|
||||||
None => {
|
|
||||||
println!("Creating bot");
|
|
||||||
cwtch.load_profiles(PASSWORD);
|
|
||||||
}
|
|
||||||
Some(_) => (),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
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);
|
|
||||||
// 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.handle, -1, "build_bot.png");
|
|
||||||
}
|
|
||||||
None => (),
|
|
||||||
};
|
|
||||||
update_bot.settings = Some(settings);
|
|
||||||
}
|
|
||||||
Event::NewPeer => {
|
|
||||||
println!(
|
|
||||||
"\n***** {} at {} *****\n",
|
|
||||||
event.data["name"], event.data["Identity"]
|
|
||||||
);
|
|
||||||
|
|
||||||
// process json for profile, conversations and servers...else {
|
|
||||||
let profile = match Profile::new(
|
|
||||||
&event.data["Identity"],
|
|
||||||
&event.data["name"],
|
|
||||||
&event.data["picture"],
|
|
||||||
&event.data["ContactsJson"],
|
|
||||||
&event.data["ServerList"],
|
|
||||||
) {
|
|
||||||
Ok(p) => p,
|
|
||||||
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.handle, -1, "build_bot.png");
|
|
||||||
}
|
|
||||||
None => (),
|
|
||||||
};
|
|
||||||
|
|
||||||
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(BOT_NAME, PASSWORD);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Event::ContactCreated => {
|
|
||||||
if event.data["ConnectionState"] == "Authenticated" {
|
|
||||||
let profile_onion = event.data["RemotePeer"].to_string();
|
|
||||||
let convo_id = event.data["ConversationID"].parse::<i32>().unwrap();
|
|
||||||
|
|
||||||
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::<i32>().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 conversation.accepted != true {
|
|
||||||
cwtch.accept_conversation(&conversation.handle.clone(), convo_id)
|
|
||||||
}
|
|
||||||
|
|
||||||
match update_bot.profile.as_mut() {
|
|
||||||
Some(profile) => {
|
|
||||||
profile
|
|
||||||
.conversations
|
|
||||||
.insert(event.data["RemotePeer"].to_string(), conversation);
|
|
||||||
}
|
|
||||||
None => (),
|
|
||||||
};
|
|
||||||
|
|
||||||
update_bot.greet(&cwtch, convo_id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Event::PeerStateChange => {
|
|
||||||
if event.data["ConnectionState"] == "Authenticated" {
|
|
||||||
match update_bot.profile.as_ref() {
|
|
||||||
Some(profile) => {
|
|
||||||
let conversation =
|
|
||||||
&profile.conversations[&event.data["RemotePeer"]];
|
|
||||||
if conversation.accepted != true {
|
|
||||||
cwtch.accept_conversation(
|
|
||||||
profile.handle.as_str(),
|
|
||||||
conversation.identifier,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
update_bot.greet(&cwtch, conversation.identifier);
|
|
||||||
}
|
|
||||||
None => (),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Event::NewMessageFromPeer => {
|
|
||||||
let to = &event.data["ProfileOnion"];
|
|
||||||
let conversation_id = event.data["ConversationID"].parse::<i32>().unwrap();
|
|
||||||
let message_wrapper: Message =
|
|
||||||
serde_json::from_str(&event.data["Data"]).expect("Error parsing message");
|
|
||||||
|
|
||||||
let mut message = message_wrapper.d.clone();
|
|
||||||
message.make_ascii_lowercase();
|
|
||||||
|
|
||||||
match message.as_str() {
|
|
||||||
"windows" => {
|
|
||||||
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 = 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 = 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 = update_bot.latest_version.clone();
|
|
||||||
android_path.push("app-release.apk");
|
|
||||||
cwtch.share_file(&to, conversation_id, android_path.to_str().unwrap());
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
update_bot.offer(&cwtch, conversation_id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Event::ErrUnhandled(err) => eprintln!("unhandled event: {}!", err),
|
|
||||||
_ => print!("unhandled event: {:?}!", event_type),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
event_loop_handle.join().expect("Error running event loop");
|
event_loop_handle.join().expect("Error running event loop");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
impl UpdateBot {
|
impl UpdateBot {
|
||||||
pub fn greet(&self, cwtch: &dyn CwtchLib, convo_id: i32) {
|
pub fn greet(&self, cwtch: &dyn CwtchLib, profile_opt: Option<&Profile>, convo_id: i32) {
|
||||||
match self.profile.as_ref() {
|
if let Some(profile) = profile_opt {
|
||||||
Some(profile) => {
|
let do_offer = match cwtch.get_conversation_attribute(
|
||||||
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, profile_opt, convo_id);
|
||||||
|
cwtch.set_conversation_attribute(
|
||||||
&profile.handle,
|
&profile.handle,
|
||||||
convo_id,
|
convo_id,
|
||||||
&format!("local.{}", LAST_OFFERED_KEY),
|
LAST_OFFERED_KEY,
|
||||||
) {
|
&self.version,
|
||||||
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 => (),
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
|
pub fn offer(&self, cwtch: &dyn CwtchLib, profile_opt: Option<&Profile>, convo_id: i32) {
|
||||||
|
if let Some(profile) = profile_opt {
|
||||||
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl bot::EventHandler for UpdateBot {
|
||||||
|
fn handle(&self, cwtch: &dyn CwtchLib, profile_opt: Option<&Profile>, event: CwtchEvent) {
|
||||||
|
let event_type = Event::new(event.event_type.as_str());
|
||||||
|
match event_type {
|
||||||
|
Event::ContactCreated => {
|
||||||
|
if event.data["ConnectionState"] == "Authenticated" {
|
||||||
|
let convo_id = event.data["ConversationID"].parse::<i32>().unwrap();
|
||||||
|
self.greet(cwtch, profile_opt, convo_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Event::PeerStateChange => {
|
||||||
|
if event.data["ConnectionState"] == "Authenticated" {
|
||||||
|
match profile_opt.as_ref() {
|
||||||
|
Some(profile) => {
|
||||||
|
let conversation =
|
||||||
|
&profile.conversations[&event.data["RemotePeer"]];
|
||||||
|
self.greet(cwtch, profile_opt, conversation.identifier);
|
||||||
|
}
|
||||||
|
None => (),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Event::NewMessageFromPeer => {
|
||||||
|
let to = &event.data["ProfileOnion"];
|
||||||
|
let conversation_id = event.data["ConversationID"].parse::<i32>().unwrap();
|
||||||
|
let message_wrapper: Message =
|
||||||
|
serde_json::from_str(&event.data["Data"]).expect("Error parsing message");
|
||||||
|
let mut message = message_wrapper.d.clone();
|
||||||
|
message.make_ascii_lowercase();
|
||||||
|
|
||||||
|
match message.as_str() {
|
||||||
|
"windows" => {
|
||||||
|
let mut windows_path = self.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 = self.latest_version.clone();
|
||||||
|
linux_path.push(format!("cwtch-{}.tar.gz", self.version));
|
||||||
|
cwtch.share_file(&to, conversation_id, linux_path.to_str().unwrap());
|
||||||
|
}
|
||||||
|
"macos" => {
|
||||||
|
let mut mac_path = self.latest_version.clone();
|
||||||
|
mac_path.push("Cwtch.dmg");
|
||||||
|
cwtch.share_file(&to, conversation_id, mac_path.to_str().unwrap());
|
||||||
|
}
|
||||||
|
"android" => {
|
||||||
|
let mut android_path = self.latest_version.clone();
|
||||||
|
android_path.push("app-release.apk");
|
||||||
|
cwtch.share_file(&to, conversation_id, android_path.to_str().unwrap());
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
self.offer( cwtch, profile_opt, conversation_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Event::ErrUnhandled(err) => eprintln!("unhandled event: {}!", err),
|
||||||
|
_ => ()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue