New filters implementation. "tags" are removed and replaced with an implementation that filters directly on the event, using an object/map instead of strings.
This commit is contained in:
parent
8cd8756722
commit
25d247f299
@ -18,50 +18,15 @@ pub enum Event {
|
|||||||
pub struct Envelope {
|
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: BTreeSet<String>
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Envelope {
|
impl Envelope {
|
||||||
pub fn new (event: Event) -> Envelope {
|
pub fn new (event: Event) -> Envelope {
|
||||||
let mut tags: BTreeSet<String> = BTreeSet::new();
|
|
||||||
|
|
||||||
match &event {
|
|
||||||
&Event::Message { ref message } => {
|
|
||||||
tags.insert(String::from("type:message"));
|
|
||||||
tags.insert(format!("user:{:}", message.author.name));
|
|
||||||
match message.channel {
|
|
||||||
Some(ref channel) => {
|
|
||||||
tags.insert(format!("channel:{:}", channel.name));
|
|
||||||
},
|
|
||||||
None => {}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
&Event::SelfJoin { ref channel } => {
|
|
||||||
tags.insert(String::from("type:selfjoin"));
|
|
||||||
tags.insert(format!("channel:{:}", channel.name));
|
|
||||||
},
|
|
||||||
&Event::SelfQuit { ref channel } => {
|
|
||||||
tags.insert(String::from("type:selfquit"));
|
|
||||||
tags.insert(format!("channel:{:}", channel.name));
|
|
||||||
},
|
|
||||||
&Event::UserJoin { ref channel, ref user } => {
|
|
||||||
tags.insert(String::from("type:userjoin"));
|
|
||||||
tags.insert(format!("channel:{:}", channel.name));
|
|
||||||
tags.insert(format!("user:{:}", user.name));
|
|
||||||
},
|
|
||||||
&Event::UserQuit { ref channel, ref user } => {
|
|
||||||
tags.insert(String::from("type:userquit"));
|
|
||||||
tags.insert(format!("channel:{:}", channel.name));
|
|
||||||
tags.insert(format!("user:{:}", user.name));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Envelope {
|
Envelope {
|
||||||
from: None,
|
from: None,
|
||||||
event: event,
|
event: event,
|
||||||
to: vec![],
|
to: vec![]
|
||||||
tags: tags
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
143
src/lib.rs
143
src/lib.rs
@ -19,6 +19,7 @@ use modules::Module;
|
|||||||
use modules::loader::{ModuleLoader, ModuleLoaderError};
|
use modules::loader::{ModuleLoader, ModuleLoaderError};
|
||||||
|
|
||||||
mod event;
|
mod event;
|
||||||
|
use event::Event;
|
||||||
use event::Envelope;
|
use event::Envelope;
|
||||||
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
@ -75,8 +76,7 @@ impl Tenquestionmarks {
|
|||||||
Envelope {
|
Envelope {
|
||||||
from: Some(from.clone()),
|
from: Some(from.clone()),
|
||||||
event: envelope.event,
|
event: envelope.event,
|
||||||
to: envelope.to,
|
to: envelope.to
|
||||||
tags: envelope.tags
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -171,21 +171,32 @@ pub trait MessageSender : Sync + Send + std::fmt::Debug {
|
|||||||
fn send_message (&self, _: &str) {}
|
fn send_message (&self, _: &str) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
trait EventFilter: Sync + Send {
|
||||||
|
fn accept (&self, envelope: &Envelope) -> bool;
|
||||||
|
}
|
||||||
|
|
||||||
struct Subscription {
|
struct Subscription {
|
||||||
pub module: Module,
|
pub module: Module,
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub filters: BTreeSet<String>
|
pub filters: Vec<Box<EventFilter>>
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Subscription {
|
impl Subscription {
|
||||||
pub fn new (name: String, module: Module) -> Subscription {
|
pub fn new (name: String, module: Module) -> Subscription {
|
||||||
let filters: BTreeSet<String> = module.config.get("filters")
|
let filters: Vec<Box<EventFilter>> = module.config.get("filters")
|
||||||
.and_then(|value| value.as_slice())
|
.and_then(|value| value.as_slice())
|
||||||
.map(|value| value.to_vec())
|
.map(|value| value.to_vec())
|
||||||
.unwrap_or(vec![])
|
.unwrap_or(vec![])
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|value| { String::from(value.as_str().unwrap()) })
|
.map(|value| {
|
||||||
.collect();
|
match value.as_table() {
|
||||||
|
Some(table) => Some(Box::new(AttributeEventFilter::new(table)) as Box<EventFilter>),
|
||||||
|
None => None
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.filter(|possible_filter| possible_filter.is_some())
|
||||||
|
.map(|possible_filter| possible_filter.unwrap())
|
||||||
|
.collect();
|
||||||
|
|
||||||
Subscription {
|
Subscription {
|
||||||
module: module,
|
module: module,
|
||||||
@ -208,7 +219,13 @@ impl Subscription {
|
|||||||
);
|
);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else if !(self.filters.is_empty() || self.filters.intersection(&envelope.tags).count() > 0) {
|
else if !self.filters.is_empty() {
|
||||||
|
for filter in &self.filters {
|
||||||
|
if filter.accept(envelope) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
debug!(
|
debug!(
|
||||||
"Refusing to transmit envelope from {:?} to {:?} since envelope was filtered out",
|
"Refusing to transmit envelope from {:?} to {:?} since envelope was filtered out",
|
||||||
envelope.from,
|
envelope.from,
|
||||||
@ -220,3 +237,107 @@ impl Subscription {
|
|||||||
true
|
true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct AttributeEventFilter {
|
||||||
|
// Attributes that can be filtered out
|
||||||
|
event_type: Option<String>,
|
||||||
|
username: Option<String>,
|
||||||
|
channel: Option<String>,
|
||||||
|
message: Option<String>
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AttributeEventFilter {
|
||||||
|
pub fn new (attributes: &Table) -> AttributeEventFilter {
|
||||||
|
AttributeEventFilter {
|
||||||
|
event_type: attributes.get("type").and_then(|value| value.as_str()).map(|value| String::from(value)),
|
||||||
|
message: attributes.get("message").and_then(|value| value.as_str()).map(|value| String::from(value)),
|
||||||
|
username: attributes.get("username").and_then(|value| value.as_str()).map(|value| String::from(value)),
|
||||||
|
channel: attributes.get("channel").and_then(|value| value.as_str()).map(|value| String::from(value)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl EventFilter for AttributeEventFilter {
|
||||||
|
fn accept (&self, envelope: &Envelope) -> bool {
|
||||||
|
let mut result = true;
|
||||||
|
match &envelope.event {
|
||||||
|
&Event::Message { ref message } => {
|
||||||
|
match self.event_type {
|
||||||
|
Some(ref event_type) => result = result && event_type == "message",
|
||||||
|
None => {}
|
||||||
|
}
|
||||||
|
|
||||||
|
match self.channel {
|
||||||
|
Some(ref channel_name) => {
|
||||||
|
match message.channel {
|
||||||
|
Some(ref channel) => result = result && channel_name == &channel.name,
|
||||||
|
None => result = false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
None => {}
|
||||||
|
}
|
||||||
|
|
||||||
|
match self.username {
|
||||||
|
Some(ref username) => result = result && &message.author.name == username,
|
||||||
|
None => {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
&Event::SelfJoin { ref channel } => {
|
||||||
|
match self.event_type {
|
||||||
|
Some(ref event_type) => result = result && event_type == "selfjoin",
|
||||||
|
None => {}
|
||||||
|
}
|
||||||
|
|
||||||
|
match self.channel {
|
||||||
|
Some(ref channel_name) => result = result && channel_name == &channel.name,
|
||||||
|
None => {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
&Event::SelfQuit { ref channel } => {
|
||||||
|
match self.event_type {
|
||||||
|
Some(ref event_type) => result = result && event_type == "selfquit",
|
||||||
|
None => {}
|
||||||
|
}
|
||||||
|
|
||||||
|
match self.channel {
|
||||||
|
Some(ref channel_name) => result = result && channel_name == &channel.name,
|
||||||
|
None => {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
&Event::UserJoin { ref channel, ref user } => {
|
||||||
|
match self.event_type {
|
||||||
|
Some(ref event_type) => result = result && event_type == "userjoin",
|
||||||
|
None => {}
|
||||||
|
}
|
||||||
|
|
||||||
|
match self.channel {
|
||||||
|
Some(ref channel_name) => result = result && channel_name == &channel.name,
|
||||||
|
None => {}
|
||||||
|
}
|
||||||
|
|
||||||
|
match self.username {
|
||||||
|
Some(ref username) => result = result && &user.name == username,
|
||||||
|
None => {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
&Event::UserQuit { ref channel, ref user } => {
|
||||||
|
match self.event_type {
|
||||||
|
Some(ref event_type) => result = result && event_type == "userquit",
|
||||||
|
None => {}
|
||||||
|
}
|
||||||
|
|
||||||
|
match self.channel {
|
||||||
|
Some(ref channel_name) => result = result && channel_name == &channel.name,
|
||||||
|
None => {}
|
||||||
|
}
|
||||||
|
|
||||||
|
match self.username {
|
||||||
|
Some(ref username) => result = result && &user.name == username,
|
||||||
|
None => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
result
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -73,7 +73,16 @@ end
|
|||||||
"""
|
"""
|
||||||
foo = "bar"
|
foo = "bar"
|
||||||
|
|
||||||
|
[lua2]
|
||||||
|
type = "lua"
|
||||||
|
filters = [{ username = "David" }]
|
||||||
|
code = """
|
||||||
|
function on_message (message, reply)
|
||||||
|
reply("Lua2 says: " .. message)
|
||||||
|
end
|
||||||
|
"""
|
||||||
|
|
||||||
[autolink]
|
[autolink]
|
||||||
|
|
||||||
[logger]
|
[logger]
|
||||||
filters = ["user:Dave"]
|
filters = [{ username = "Dave" }]
|
||||||
|
Loading…
x
Reference in New Issue
Block a user