Merge pull request 'allowList + break off behaviours to own file' (#4) from allowList into main
Reviewed-on: #4 Reviewed-by: Sarah Jamie Lewis <sarah@openprivacy.ca>
This commit is contained in:
commit
4327bfe839
|
@ -6,6 +6,6 @@ edition = "2021"
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
libcwtch = "0.3.0"
|
libcwtch = "0.3.2"
|
||||||
serde_json = "1.0"
|
serde_json = "1.0"
|
||||||
chrono = "0.4.19"
|
chrono = "0.4.19"
|
|
@ -0,0 +1,109 @@
|
||||||
|
|
||||||
|
/// defines a locked list of allowed peers and groups the bot may communicate with
|
||||||
|
/// others will be blocked, and peers listed here will be peered with actively
|
||||||
|
pub struct AllowListMembers {
|
||||||
|
/// list of peers to allow by handle
|
||||||
|
pub peers: Vec<String>,
|
||||||
|
/// list of groups to join and listen for peers in peer list from
|
||||||
|
pub groups: Vec<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AllowListMembers {
|
||||||
|
/// constructs a new AllowListMembers struct
|
||||||
|
pub fn new(peers: Vec<String>, groups: Vec<String>) -> Self {
|
||||||
|
AllowListMembers {peers: peers, groups: groups}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// How new contacts should be treated
|
||||||
|
pub enum NewContactPolicy {
|
||||||
|
/// Do not react, leave it for the custom event handler
|
||||||
|
Ignore,
|
||||||
|
/// Block all new contacts
|
||||||
|
Block,
|
||||||
|
/// Accept all new contacts
|
||||||
|
Accept,
|
||||||
|
/// AllowList is a list of handles that connections will be allowed from and connected to, and will be accepted
|
||||||
|
/// everything else will be ignored
|
||||||
|
AllowList(AllowListMembers)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Settings for the bot on how it should automatically behave
|
||||||
|
pub struct Behaviour {
|
||||||
|
/// The bot will enable experimental feautres (required for any experiments to be used)
|
||||||
|
pub proto_experiments: bool,
|
||||||
|
|
||||||
|
/// The bot will enable the file sharing experiment
|
||||||
|
pub proto_experiment_fileshare: bool,
|
||||||
|
|
||||||
|
/// The bot will enable the groups experiment
|
||||||
|
pub proto_experiment_groups: bool,
|
||||||
|
|
||||||
|
/// The profile name the bot will share with accepted conversations
|
||||||
|
pub profile_name: String,
|
||||||
|
/// The profile pic the bot with share with accepted conversations IF the file share exoeriment is enabled
|
||||||
|
pub profile_pic_path: Option<String>,
|
||||||
|
|
||||||
|
/// Policy dictacting how the bot should automatically handle ContactCreated events
|
||||||
|
pub new_contant_policy: NewContactPolicy,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// intermediary struct for building a Behaviour using builder patern
|
||||||
|
pub struct BehaviourBuilder {
|
||||||
|
behaviour: Behaviour,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BehaviourBuilder {
|
||||||
|
/// Returns a new empty default off for features behaviour builder
|
||||||
|
pub fn new() -> Self {
|
||||||
|
return BehaviourBuilder {
|
||||||
|
behaviour: Behaviour {
|
||||||
|
proto_experiments: false,
|
||||||
|
proto_experiment_fileshare: false,
|
||||||
|
proto_experiment_groups: false,
|
||||||
|
new_contant_policy: NewContactPolicy::Ignore,
|
||||||
|
profile_name: "".to_string(),
|
||||||
|
profile_pic_path: None,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Build the defined behaviours into a Behaviour struct
|
||||||
|
pub fn build(self) -> Behaviour {
|
||||||
|
self.behaviour
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Control if the Behaviour of the bot should include groups (enabling experiments and the group experiment)
|
||||||
|
pub fn groups(mut self, val: bool) -> Self {
|
||||||
|
self.behaviour.proto_experiment_groups = val;
|
||||||
|
self.behaviour.proto_experiments = true;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Control if the Behaviour of the bot should include filesharing (enabling experiments and the filesharing experiment)
|
||||||
|
pub fn fileshare(mut self, val: bool) -> Self {
|
||||||
|
self.behaviour.proto_experiment_fileshare = val;
|
||||||
|
self.behaviour.proto_experiments = true;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Set a profile pic for the bot and enable the filesharing experiment
|
||||||
|
pub fn profile_pic_path(mut self, val: String) -> Self {
|
||||||
|
self.behaviour.profile_pic_path = Some(val);
|
||||||
|
self.behaviour.proto_experiment_fileshare = true;
|
||||||
|
self.behaviour.proto_experiments = true;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Set a name for the behaviour
|
||||||
|
pub fn name(mut self, val: String) -> Self {
|
||||||
|
self.behaviour.profile_name = val;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Set a new contact policy for the behaviour
|
||||||
|
pub fn new_contact_policy(mut self, val: NewContactPolicy) -> Self {
|
||||||
|
self.behaviour.new_contant_policy = val;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
152
src/imp.rs
152
src/imp.rs
|
@ -3,98 +3,18 @@ use libcwtch::structs::*;
|
||||||
use libcwtch::CwtchLib;
|
use libcwtch::CwtchLib;
|
||||||
|
|
||||||
use serde_json;
|
use serde_json;
|
||||||
|
use crate::behaviour::{Behaviour, NewContactPolicy};
|
||||||
/// How new contacts should be treated
|
use crate::behaviour::NewContactPolicy::AllowList;
|
||||||
pub enum NewContactPolicy {
|
|
||||||
/// Do not react, leave it for the custom event handler
|
|
||||||
Ignore,
|
|
||||||
/// Block all new contacts
|
|
||||||
Block,
|
|
||||||
/// Accept all new contacts
|
|
||||||
Accept,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Settings for the bot on how it should automatically behave
|
|
||||||
pub struct Behaviour {
|
|
||||||
/// The bot will enable experimental feautres (required for any experiments to be used)
|
|
||||||
pub proto_experiments: bool,
|
|
||||||
|
|
||||||
/// The bot will enable the file sharing experiment
|
|
||||||
pub proto_experiment_fileshare: bool,
|
|
||||||
|
|
||||||
/// The bot will enable the groups experiment
|
|
||||||
pub proto_experiment_groups: bool,
|
|
||||||
|
|
||||||
/// The profile name the bot will share with accepted conversations
|
|
||||||
pub profile_name: String,
|
|
||||||
/// The profile pic the bot with share with accepted conversations IF the file share exoeriment is enabled
|
|
||||||
pub profile_pic_path: Option<String>,
|
|
||||||
|
|
||||||
/// Policy dictacting how the bot should automatically handle ContactCreated events
|
|
||||||
pub new_contant_policy: NewContactPolicy,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct BehaviourBuilder {
|
|
||||||
behaviour: Behaviour,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl BehaviourBuilder {
|
|
||||||
pub fn new() -> Self {
|
|
||||||
return BehaviourBuilder {
|
|
||||||
behaviour: Behaviour {
|
|
||||||
proto_experiments: false,
|
|
||||||
proto_experiment_fileshare: false,
|
|
||||||
proto_experiment_groups: false,
|
|
||||||
new_contant_policy: NewContactPolicy::Ignore,
|
|
||||||
profile_name: "".to_string(),
|
|
||||||
profile_pic_path: None,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn build(self) -> Behaviour {
|
|
||||||
self.behaviour
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn groups(mut self, val: bool) -> Self {
|
|
||||||
self.behaviour.proto_experiment_groups = val;
|
|
||||||
self.behaviour.proto_experiments = true;
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn fileshare(mut self, val: bool) -> Self {
|
|
||||||
self.behaviour.proto_experiment_fileshare = val;
|
|
||||||
self.behaviour.proto_experiments = true;
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn profile_pic_path(mut self, val: String) -> Self {
|
|
||||||
self.behaviour.profile_pic_path = Some(val);
|
|
||||||
self.behaviour.proto_experiment_fileshare = true;
|
|
||||||
self.behaviour.proto_experiments = true;
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn name(mut self, val: String) -> Self {
|
|
||||||
self.behaviour.profile_name = val;
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn new_contact_policy(mut self, val: NewContactPolicy) -> Self {
|
|
||||||
self.behaviour.new_contant_policy = val;
|
|
||||||
self
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Trait to be used by implementors of imp bots to supply their custom event handling
|
/// Trait to be used by implementors of imp bots to supply their custom event handling
|
||||||
/// the handle function is called after the default imp automatic event handling has run on each new event
|
/// the handle function is called after the default imp automatic event handling has run on each new event
|
||||||
pub trait EventHandler {
|
pub trait EventHandler {
|
||||||
fn handle(&mut self, cwtch: &dyn CwtchLib, profile: Option<&Profile>, event: Event);
|
fn handle(&mut self, cwtch: &dyn libcwtch::CwtchLib, profile: Option<&Profile>, event: Event);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Cwtch bot
|
/// Cwtch bot
|
||||||
pub struct Imp {
|
pub struct Imp {
|
||||||
cwtch: Box<dyn CwtchLib>,
|
cwtch: Box<dyn libcwtch::CwtchLib>,
|
||||||
behaviour: Behaviour,
|
behaviour: Behaviour,
|
||||||
password: String,
|
password: String,
|
||||||
home_dir: String,
|
home_dir: String,
|
||||||
|
@ -213,22 +133,22 @@ impl Imp {
|
||||||
);
|
);
|
||||||
|
|
||||||
for (_id, conversation) in &profile.conversations {
|
for (_id, conversation) in &profile.conversations {
|
||||||
match self.behaviour.new_contant_policy {
|
self.process_contact(conversation.identifier);
|
||||||
NewContactPolicy::Accept => {
|
}
|
||||||
self.cwtch
|
|
||||||
.accept_conversation(&profile.handle.clone(), conversation.identifier);
|
// Allow list should add all people in the list
|
||||||
|
if let AllowList(allow_list) = &self.behaviour.new_contant_policy {
|
||||||
|
for handle in &allow_list.peers {
|
||||||
|
if let None = profile.find_conversation_id_by_handle(handle.clone()) {
|
||||||
|
self.cwtch.import_bundle(&profile.handle.clone(), &handle.clone());
|
||||||
}
|
}
|
||||||
NewContactPolicy::Block => self
|
|
||||||
.cwtch
|
|
||||||
.block_contact(&profile.handle.clone(), conversation.identifier),
|
|
||||||
NewContactPolicy::Ignore => (),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self.profile = Some(profile);
|
self.profile = Some(profile);
|
||||||
}
|
}
|
||||||
Event::AppError { data } => {
|
Event::AppError { data } => {
|
||||||
if initialized && data["Error"] == "Loaded 0 profiles" {
|
if initialized && data.contains_key("Error") && data["Error"] == "Loaded 0 profiles" {
|
||||||
self.cwtch
|
self.cwtch
|
||||||
.create_profile(&self.behaviour.profile_name, &self.password);
|
.create_profile(&self.behaviour.profile_name, &self.password);
|
||||||
}
|
}
|
||||||
|
@ -236,7 +156,6 @@ impl Imp {
|
||||||
Event::ContactCreated { data } => {
|
Event::ContactCreated { data } => {
|
||||||
println!("Contact Created");
|
println!("Contact Created");
|
||||||
let convo_handle = data["RemotePeer"].to_string();
|
let convo_handle = data["RemotePeer"].to_string();
|
||||||
let convo_id = data["ConversationID"].parse::<i32>().unwrap();
|
|
||||||
|
|
||||||
let acl: ACL = serde_json::from_str(&data["accessControlList"]).expect("Error parsing conversation");
|
let acl: ACL = serde_json::from_str(&data["accessControlList"]).expect("Error parsing conversation");
|
||||||
|
|
||||||
|
@ -251,20 +170,13 @@ impl Imp {
|
||||||
is_group: false, // by definition
|
is_group: false, // by definition
|
||||||
};
|
};
|
||||||
|
|
||||||
|
self.process_contact(conversation.identifier);
|
||||||
|
|
||||||
match self.profile.as_mut() {
|
match self.profile.as_mut() {
|
||||||
Some(profile) => {
|
Some(profile) => {
|
||||||
profile
|
profile
|
||||||
.conversations
|
.conversations
|
||||||
.insert(data["RemotePeer"].to_string(), conversation);
|
.insert(conversation.identifier, conversation);
|
||||||
|
|
||||||
match self.behaviour.new_contant_policy {
|
|
||||||
NewContactPolicy::Accept => {
|
|
||||||
self.cwtch
|
|
||||||
.accept_conversation(&profile.handle.clone(), convo_id);
|
|
||||||
}
|
|
||||||
NewContactPolicy::Block => self.cwtch.block_contact(&profile.handle.clone(), convo_id),
|
|
||||||
NewContactPolicy::Ignore => (),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
None => (),
|
None => (),
|
||||||
};
|
};
|
||||||
|
@ -277,4 +189,36 @@ impl Imp {
|
||||||
handler.handle(self.cwtch.as_ref(), self.profile.as_ref(), event);
|
handler.handle(self.cwtch.as_ref(), self.profile.as_ref(), event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn process_contact(&self, conversation_id: i32) {
|
||||||
|
match &self.profile {
|
||||||
|
Some(profile) => {
|
||||||
|
let profile_handle = profile.handle.clone();
|
||||||
|
|
||||||
|
|
||||||
|
match &self.behaviour.new_contant_policy {
|
||||||
|
NewContactPolicy::Accept => {
|
||||||
|
self.cwtch
|
||||||
|
.accept_conversation(&profile_handle.clone(), conversation_id);
|
||||||
|
}
|
||||||
|
NewContactPolicy::Block => self.cwtch.block_contact(&profile_handle.clone(), conversation_id),
|
||||||
|
NewContactPolicy::AllowList(allow_list) => {
|
||||||
|
match profile.conversations.get(&conversation_id) {
|
||||||
|
Some(conversation) => {
|
||||||
|
if allow_list.peers.contains(&conversation.handle) {
|
||||||
|
self.cwtch
|
||||||
|
.accept_conversation(&profile_handle.clone(), conversation_id);
|
||||||
|
} else {
|
||||||
|
self.cwtch.block_contact(&profile_handle.clone(), conversation_id);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
None => {},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
NewContactPolicy::Ignore => (),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
None => {},
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,2 +1,3 @@
|
||||||
pub mod event;
|
pub mod event;
|
||||||
pub mod imp;
|
pub mod imp;
|
||||||
|
pub mod behaviour;
|
||||||
|
|
Loading…
Reference in New Issue