add behaviours: ContactInteractionPolicy, GroupInteractionPolicy; move allow_list to Behaviour

This commit is contained in:
Dan Ballard 2024-02-21 17:53:54 -08:00
parent 76fa84bd66
commit d2abf3af24
3 changed files with 110 additions and 26 deletions

View File

@ -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 # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies] [dependencies]
libcwtch = "0.7.0" libcwtch = {path = "./../libcwtch-rs"} # "0.7.0"
chrono = "0.4.19" chrono = "0.4.19"

View File

@ -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 /// 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 /// others will be blocked, and peers listed here will be peered with actively
pub struct AllowListMembers { pub struct AllowListMembers {
/// list of peers to allow by handle /// list of peers to allow by handle
pub peers: Vec<ContactIdentity>, pub peers: Vec<ContactIdentity>,
/// list of groups to join and listen for peers in peer list from
pub groups: Vec<GroupID>,
} }
impl AllowListMembers { impl AllowListMembers {
/// constructs a new AllowListMembers struct /// constructs a new AllowListMembers struct
pub fn new(peers: Vec<ContactIdentity>, groups: Vec<GroupID>) -> Self { pub fn new(peers: Vec<ContactIdentity>) -> Self {
AllowListMembers {peers: peers, groups: groups} AllowListMembers {peers: peers}
} }
} }
@ -26,16 +24,43 @@ pub enum NewContactPolicy {
Accept, Accept,
/// AllowList is a list of handles that connections will be allowed from and connected to, and will be accepted /// AllowList is a list of handles that connections will be allowed from and connected to, and will be accepted
/// everything else will be ignored /// 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 { pub enum GroupInvitePolicy {
/// Ignore all group invites /// Ignore all group invites
IgnoreAll, Ignore,
/// Accept all group invites /// Accept all group invites
AcceptAll, Accept,
/// Only accept group invites from contacts. Pairs strongly with NewContactPolicy of AllowList /// Only accept group invites from contacts. Pairs strongly with NewContactPolicy of AllowList
AcceptFromContact, 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 /// 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 /// Policy dictacting how the bot should automatically handle ContactCreated events
pub new_contant_policy: NewContactPolicy, 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 /// Policy dictating how the bot should handle Group Invites
pub group_invite_policy: GroupInvitePolicy, 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 /// intermediary struct for building a Behaviour using builder patern
@ -75,9 +108,12 @@ impl BehaviourBuilder {
proto_experiment_fileshare: false, proto_experiment_fileshare: false,
proto_experiment_groups: false, proto_experiment_groups: false,
new_contant_policy: NewContactPolicy::Ignore, 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_name: "".to_string(),
profile_pic_path: None, profile_pic_path: None,
allow_list: AllowListMembers::new(vec!()),
}, },
}; };
} }
@ -121,8 +157,23 @@ impl BehaviourBuilder {
self 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 { pub fn group_invite_policy(mut self, val: GroupInvitePolicy) -> Self {
self.behaviour.group_invite_policy = val; self.behaviour.group_invite_policy = val;
self 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
}
} }

View File

@ -4,8 +4,7 @@ use libcwtch::CwtchLib;
use libcwtch::event::{ContactIdentity, ConversationID, Event}; use libcwtch::event::{ContactIdentity, ConversationID, Event};
use libcwtch::structs::MessageType::InviteGroup; use libcwtch::structs::MessageType::InviteGroup;
use crate::behaviour::{Behaviour, GroupInvitePolicy, NewContactPolicy}; use crate::behaviour::{Behaviour, ContactInteractionPolicy, GroupInteractionPolicy, GroupInvitePolicy, NewContactPolicy};
use crate::behaviour::GroupInvitePolicy::AcceptAll;
use crate::behaviour::NewContactPolicy::AllowList; use crate::behaviour::NewContactPolicy::AllowList;
/// 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
@ -125,8 +124,8 @@ impl Imp {
} }
// Allow list should add all people in the list // Allow list should add all people in the list
if let AllowList(allow_list) = &self.behaviour.new_contant_policy { if let AllowList = &self.behaviour.new_contant_policy {
for contact_id in &allow_list.peers { for contact_id in &self.behaviour.allow_list.peers {
if let None = ok_profile.find_conversation_id_by_handle(contact_id.clone()) { if let None = ok_profile.find_conversation_id_by_handle(contact_id.clone()) {
self.cwtch.import_bundle(&profile_id, contact_id.clone().as_str()); 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 } => { Event::NewMessageFromPeer {profile_id, conversation_id,contact_id, nick, timestamp_received, message, notification, picture } => {
if message.o == InviteGroup { if message.o == InviteGroup {
if let Some(profile) = self.profile.as_ref() { if let Some(profile) = self.profile.as_ref() {
match self.behaviour.group_invite_policy { match &self.behaviour.group_invite_policy {
GroupInvitePolicy::IgnoreAll => (), GroupInvitePolicy::Ignore => (),
GroupInvitePolicy::AcceptAll => self.cwtch.import_bundle(profile_id, message.d.as_str()), GroupInvitePolicy::Accept => self.cwtch.import_bundle(profile_id, message.d.as_str()),
GroupInvitePolicy::AcceptFromContact=> { GroupInvitePolicy::AcceptFromContact=> {
if profile.conversations[conversation_id].accepted { if profile.conversations[conversation_id].accepted {
self.cwtch.import_bundle(profile_id, message.d.as_str()) 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 { } else {
match self.profile.as_ref() { if let Some(profile) = 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()), match &self.behaviour.contact_interaction_policy {
None => {}, 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, } => { Event::NewMessageFromGroup { profile_id, conversation_id, timestamp_sent, contact_id, index, message, content_hash, picture, notification, } => {
if let Some(profile )= self.profile.as_ref() { 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()) 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), Event::ErrUnhandled { name, data } => eprintln!("unhandled event: {}!", name),
@ -219,18 +254,16 @@ impl Imp {
match &self.profile { match &self.profile {
Some(profile) => { Some(profile) => {
let profile_handle = profile.profile_id.clone(); let profile_handle = profile.profile_id.clone();
match &self.behaviour.new_contant_policy { match &self.behaviour.new_contant_policy {
NewContactPolicy::Accept => { NewContactPolicy::Accept => {
self.cwtch self.cwtch
.accept_conversation(&profile.profile_id, conversation_id); .accept_conversation(&profile.profile_id, conversation_id);
} }
NewContactPolicy::Block => self.cwtch.block_conversation(&profile_handle.clone(), 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) { match profile.conversations.get(&conversation_id) {
Some(conversation) => { Some(conversation) => {
if allow_list.peers.contains(&conversation.contact_id) { if self.behaviour.allow_list.peers.contains(&conversation.contact_id) {
self.cwtch self.cwtch
.accept_conversation(&profile_handle.clone(), conversation_id); .accept_conversation(&profile_handle.clone(), conversation_id);
} else { } else {