diff --git a/Cargo.toml b/Cargo.toml index fcf0bd5..99efc8c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,5 +12,5 @@ documentation = "https://docs.rs/cwtch-imp/" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -libcwtch = "0.7.0" +libcwtch = {path = "./../libcwtch-rs"} # "0.7.0" chrono = "0.4.19" diff --git a/src/behaviour.rs b/src/behaviour.rs index c7bc65f..0d3188e 100644 --- a/src/behaviour.rs +++ b/src/behaviour.rs @@ -1,18 +1,16 @@ -use libcwtch::event::{ContactIdentity, GroupID}; +use libcwtch::event::{ContactIdentity}; /// 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, - /// list of groups to join and listen for peers in peer list from - pub groups: Vec, } impl AllowListMembers { /// constructs a new AllowListMembers struct - pub fn new(peers: Vec, groups: Vec) -> Self { - AllowListMembers {peers: peers, groups: groups} + pub fn new(peers: Vec) -> Self { + AllowListMembers {peers: peers} } } @@ -26,16 +24,43 @@ pub enum NewContactPolicy { 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) + AllowList +} + +pub enum ContactInteractionPolicy { + /// Do not react, leave it for the custom event handler + Ignore, + /// Accept all messages + Accept, + /// Only accept messages from contacts. Pairs strongly with NewContactPolicy of AllowList + AcceptFromContact, + /// 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 } pub enum GroupInvitePolicy { /// Ignore all group invites - IgnoreAll, + Ignore, /// Accept all group invites - AcceptAll, + Accept, /// Only accept group invites from contacts. Pairs strongly with NewContactPolicy of AllowList AcceptFromContact, + /// AllowList is a list of handles that group invites will be allowed from and connected to, + /// and will be accepted. Everything else will be ignored + AllowList, +} + +pub enum GroupInteractionPolicy { + /// Do not react, leave it for the custom event handler + Ignore, + /// Accept all messages + Accept, + /// Only accept messages from contacts. Pairs strongly with NewContactPolicy of AllowList + AcceptFromContact, + /// 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 } /// Settings for the bot on how it should automatically behave @@ -57,8 +82,16 @@ pub struct Behaviour { /// Policy dictacting how the bot should automatically handle ContactCreated events pub new_contant_policy: NewContactPolicy, + /// Policy dictating how the bot should handle messages from p2p contacts + pub contact_interaction_policy: ContactInteractionPolicy, + /// Policy dictating how the bot should handle Group Invites pub group_invite_policy: GroupInvitePolicy, + + /// Policy dictacting how the bot should respond to @ messages in groups + pub group_interaction_policy: GroupInteractionPolicy, + + pub allow_list: AllowListMembers, } /// intermediary struct for building a Behaviour using builder patern @@ -75,9 +108,12 @@ impl BehaviourBuilder { proto_experiment_fileshare: false, proto_experiment_groups: false, new_contant_policy: NewContactPolicy::Ignore, - group_invite_policy: GroupInvitePolicy::IgnoreAll, + contact_interaction_policy: ContactInteractionPolicy::Ignore, + group_invite_policy: GroupInvitePolicy::Ignore, + group_interaction_policy: GroupInteractionPolicy::Ignore, profile_name: "".to_string(), profile_pic_path: None, + allow_list: AllowListMembers::new(vec!()), }, }; } @@ -121,8 +157,23 @@ impl BehaviourBuilder { self } + pub fn contact_interaction_policy(mut self, val: ContactInteractionPolicy) -> Self { + self.behaviour.contact_interaction_policy = val; + self + } + pub fn group_invite_policy(mut self, val: GroupInvitePolicy) -> Self { self.behaviour.group_invite_policy = val; self } + + pub fn group_interaction_policy(mut self, val: GroupInteractionPolicy) -> Self { + self.behaviour.group_interaction_policy = val; + self + } + + pub fn allow_list(mut self, val: AllowListMembers) -> Self { + self.behaviour.allow_list = val; + self + } } diff --git a/src/imp.rs b/src/imp.rs index cde0106..be19f0d 100644 --- a/src/imp.rs +++ b/src/imp.rs @@ -4,8 +4,7 @@ use libcwtch::CwtchLib; use libcwtch::event::{ContactIdentity, ConversationID, Event}; use libcwtch::structs::MessageType::InviteGroup; -use crate::behaviour::{Behaviour, GroupInvitePolicy, NewContactPolicy}; -use crate::behaviour::GroupInvitePolicy::AcceptAll; +use crate::behaviour::{Behaviour, ContactInteractionPolicy, GroupInteractionPolicy, GroupInvitePolicy, NewContactPolicy}; use crate::behaviour::NewContactPolicy::AllowList; /// Trait to be used by implementors of imp bots to supply their custom event handling @@ -125,8 +124,8 @@ impl Imp { } // Allow list should add all people in the list - if let AllowList(allow_list) = &self.behaviour.new_contant_policy { - for contact_id in &allow_list.peers { + if let AllowList = &self.behaviour.new_contant_policy { + for contact_id in &self.behaviour.allow_list.peers { if let None = ok_profile.find_conversation_id_by_handle(contact_id.clone()) { self.cwtch.import_bundle(&profile_id, contact_id.clone().as_str()); } @@ -185,26 +184,62 @@ impl Imp { Event::NewMessageFromPeer {profile_id, conversation_id,contact_id, nick, timestamp_received, message, notification, picture } => { if message.o == InviteGroup { if let Some(profile) = self.profile.as_ref() { - match self.behaviour.group_invite_policy { - GroupInvitePolicy::IgnoreAll => (), - GroupInvitePolicy::AcceptAll => self.cwtch.import_bundle(profile_id, message.d.as_str()), + match &self.behaviour.group_invite_policy { + GroupInvitePolicy::Ignore => (), + GroupInvitePolicy::Accept => self.cwtch.import_bundle(profile_id, message.d.as_str()), GroupInvitePolicy::AcceptFromContact=> { if profile.conversations[conversation_id].accepted { self.cwtch.import_bundle(profile_id, message.d.as_str()) } } + GroupInvitePolicy::AllowList => { + if let Some(conversation) = profile.conversations.get(&conversation_id) { + if self.behaviour.allow_list.peers.contains(&conversation.contact_id) { + self.cwtch.import_bundle(profile_id, message.d.as_str()) + } + } + } } } } else { - match self.profile.as_ref() { - Some(profile) => handler.on_new_message_from_contact(self.cwtch.as_ref(), profile, conversation_id.clone(), nick.clone(), timestamp_received.clone(), message.clone()), - None => {}, + if let Some(profile) = self.profile.as_ref() { + match &self.behaviour.contact_interaction_policy { + ContactInteractionPolicy::Ignore => (), + ContactInteractionPolicy::Accept => handler.on_new_message_from_contact(self.cwtch.as_ref(), profile, conversation_id.clone(), nick.clone(), timestamp_received.clone(), message.clone()), + ContactInteractionPolicy::AcceptFromContact=> { + if profile.conversations[conversation_id].accepted { + handler.on_new_message_from_contact(self.cwtch.as_ref(), profile, conversation_id.clone(), nick.clone(), timestamp_received.clone(), message.clone()); + } + }, + ContactInteractionPolicy::AllowList => { + if let Some(conversation) = profile.conversations.get(&conversation_id) { + if self.behaviour.allow_list.peers.contains(&conversation.contact_id) { + handler.on_new_message_from_contact(self.cwtch.as_ref(), profile, conversation_id.clone(), nick.clone(), timestamp_received.clone(), message.clone()); + } + } + } + } } } } Event::NewMessageFromGroup { profile_id, conversation_id, timestamp_sent, contact_id, index, message, content_hash, picture, notification, } => { - if let Some(profile )= self.profile.as_ref() { - handler.on_new_message_from_group(self.cwtch.as_ref(), profile, conversation_id.clone(), contact_id.clone(), timestamp_sent.clone(), message.clone()) + if let Some(profile) = self.profile.as_ref() { + match &self.behaviour.group_interaction_policy { + GroupInteractionPolicy::Ignore => (), + GroupInteractionPolicy::Accept => handler.on_new_message_from_group(self.cwtch.as_ref(), profile, conversation_id.clone(), contact_id.clone(), timestamp_sent.clone(), message.clone()), + GroupInteractionPolicy::AcceptFromContact=> { + if let Some(contact_convo_id) = profile.find_conversation_id_by_handle(contact_id.clone()) { + if profile.conversations[&contact_convo_id].accepted { + handler.on_new_message_from_group(self.cwtch.as_ref(), profile, conversation_id.clone(), contact_id.clone(), timestamp_sent.clone(), message.clone()) + } + } + }, + GroupInteractionPolicy::AllowList => { + if self.behaviour.allow_list.peers.contains(&contact_id) { + handler.on_new_message_from_group(self.cwtch.as_ref(), profile, conversation_id.clone(), contact_id.clone(), timestamp_sent.clone(), message.clone()) + } + } + } } } Event::ErrUnhandled { name, data } => eprintln!("unhandled event: {}!", name), @@ -219,18 +254,16 @@ impl Imp { match &self.profile { Some(profile) => { let profile_handle = profile.profile_id.clone(); - - match &self.behaviour.new_contant_policy { NewContactPolicy::Accept => { self.cwtch .accept_conversation(&profile.profile_id, conversation_id); } NewContactPolicy::Block => self.cwtch.block_conversation(&profile_handle.clone(), conversation_id), - NewContactPolicy::AllowList(allow_list) => { + NewContactPolicy::AllowList => { match profile.conversations.get(&conversation_id) { Some(conversation) => { - if allow_list.peers.contains(&conversation.contact_id) { + if self.behaviour.allow_list.peers.contains(&conversation.contact_id) { self.cwtch .accept_conversation(&profile_handle.clone(), conversation_id); } else {