Add tag filters. This is a primitive way to screen out events that do not match a certain criteria (e.g. from user Dave)

This commit is contained in:
Adrian Malacoda 2017-05-10 00:17:22 -05:00
parent 6dda3e227f
commit 7c26e0294a
4 changed files with 61 additions and 26 deletions

View File

@ -1,6 +1,7 @@
use {Message, Channel, User}; use {Message, Channel, User};
use std::sync::Arc; use std::sync::Arc;
use std::collections::btree_set::BTreeSet;
#[derive(Debug)] #[derive(Debug)]
pub enum Event { pub enum Event {
@ -18,36 +19,36 @@ pub struct Envelope {
pub from: Option<String>, pub from: Option<String>,
pub event: Event, pub event: Event,
pub to: Vec<String>, pub to: Vec<String>,
pub tags: Vec<String> pub tags: BTreeSet<String>
} }
impl Envelope { impl Envelope {
pub fn new (event: Event) -> Envelope { pub fn new (event: Event) -> Envelope {
let mut tags: Vec<String> = vec![]; let mut tags: BTreeSet<String> = BTreeSet::new();
match &event { match &event {
&Event::Message { ref message } => { &Event::Message { ref message } => {
tags.push(format!("user:{:}", message.author.name)); tags.insert(format!("user:{:}", message.author.name));
match message.channel { match message.channel {
Some(ref channel) => { Some(ref channel) => {
tags.push(format!("channel:{:}", channel.name)); tags.insert(format!("channel:{:}", channel.name));
}, },
None => {} None => {}
} }
}, },
&Event::SelfJoin { ref channel } => { &Event::SelfJoin { ref channel } => {
tags.push(format!("channel:{:}", channel.name)); tags.insert(format!("channel:{:}", channel.name));
}, },
&Event::SelfQuit { ref channel } => { &Event::SelfQuit { ref channel } => {
tags.push(format!("channel:{:}", channel.name)); tags.insert(format!("channel:{:}", channel.name));
}, },
&Event::UserJoin { ref channel, ref user } => { &Event::UserJoin { ref channel, ref user } => {
tags.push(format!("channel:{:}", channel.name)); tags.insert(format!("channel:{:}", channel.name));
tags.push(format!("user:{:}", user.name)); tags.insert(format!("user:{:}", user.name));
}, },
&Event::UserQuit { ref channel, ref user } => { &Event::UserQuit { ref channel, ref user } => {
tags.push(format!("channel:{:}", channel.name)); tags.insert(format!("channel:{:}", channel.name));
tags.push(format!("user:{:}", user.name)); tags.insert(format!("user:{:}", user.name));
} }
} }

View File

@ -101,6 +101,8 @@ impl Tenquestionmarks {
let arc_envelope = Arc::new(envelope); let arc_envelope = Arc::new(envelope);
for (key, sender) in &module_senders { for (key, sender) in &module_senders {
let from_this = String::from(*key); let from_this = String::from(*key);
match self.modules.get::<String>(&from_this) {
Some(module) => {
if Some(from_this.clone()) == arc_envelope.from { if Some(from_this.clone()) == arc_envelope.from {
debug!("Refusing to transmit event to its originator ({:?})", from_this); debug!("Refusing to transmit event to its originator ({:?})", from_this);
continue; continue;
@ -114,11 +116,22 @@ impl Tenquestionmarks {
); );
continue; continue;
} }
else if !module.can_handle_event(&arc_envelope) {
debug!(
"Refusing to transmit envelope from {:?} to {:?} since envelope was filtered out",
arc_envelope.from,
from_this
);
continue;
}
match sender.send(arc_envelope.clone()) { match sender.send(arc_envelope.clone()) {
Err(err) => debug!("Failed to dispatch event to module \"{}\": {:?}", key, err), Err(err) => debug!("Failed to dispatch event to module \"{}\": {:?}", key, err),
Ok(_) => {} Ok(_) => {}
} }
},
None => debug!("Failed to dispatch event to module \"{}\": No such module found!", key)
}
} }
}, },
Err(err) => { error!("Failed to receive event in main event loop: {:?}", err); } Err(err) => { error!("Failed to receive event in main event loop: {:?}", err); }

View File

@ -19,6 +19,8 @@ use transformable_channels::mpsc::ExtSender;
use toml::Table; use toml::Table;
use std::collections::btree_set::BTreeSet;
pub struct Module { pub struct Module {
event_loop: Box<EventLoop>, event_loop: Box<EventLoop>,
module_type: String, module_type: String,
@ -29,6 +31,22 @@ impl Module {
pub fn run (&self, sender: Box<ExtSender<Envelope>>, receiver: Receiver<Arc<Envelope>>) { pub fn run (&self, sender: Box<ExtSender<Envelope>>, receiver: Receiver<Arc<Envelope>>) {
self.event_loop.run(sender, receiver); self.event_loop.run(sender, receiver);
} }
pub fn can_handle_event (&self, envelope: &Envelope) -> bool {
let filters: BTreeSet<String> = self.config.get("filters")
.and_then(|value| value.as_slice())
.map(|value| value.to_vec())
.unwrap_or(vec![])
.into_iter()
.map(|value| { String::from(value.as_str().unwrap()) })
.collect();
if filters.is_empty() {
return true;
}
filters.intersection(&envelope.tags).count() > 0
}
} }
pub trait EventLoop : Sync { pub trait EventLoop : Sync {

View File

@ -74,3 +74,6 @@ end
foo = "bar" foo = "bar"
[autolink] [autolink]
[logger]
filters = ["user:Dave"]