use super::{Matchers, MatchersBTreeMap, MatchersHashMap};
use crate::event::{MessageEvent, MetaEvent, NoticeEvent, RequestEvent};
use crate::matcher::{action::MatchersAction, Matcher};
use std::collections::{BTreeMap, HashMap};
use tokio::sync::broadcast;
impl Matchers {
pub fn new(
message: Option<MatchersBTreeMap<MessageEvent>>,
notice: Option<MatchersBTreeMap<NoticeEvent>>,
request: Option<MatchersBTreeMap<RequestEvent>>,
meta: Option<MatchersBTreeMap<MetaEvent>>,
) -> Matchers {
let (sender, _) = broadcast::channel(32);
Matchers {
message: unoptionb(&message),
notice: unoptionb(¬ice),
request: unoptionb(&request),
meta: unoptionb(&meta),
bot_getter: None,
action_sender: sender,
config: HashMap::new(),
}
}
pub fn new_empty() -> Matchers {
Matchers::new(None, None, None, None)
}
pub fn get(&mut self, m: &Matchers) {
self.message = m.message.clone();
self.notice = m.notice.clone();
self.request = m.request.clone();
self.meta = m.meta.clone();
}
pub async fn run_on_connect(&self, bot: crate::bot::Bot, disconnect: bool) {
async fn run_on_connect_<E>(
matcherb: &MatchersBTreeMap<E>,
bot: crate::bot::Bot,
disconnect: bool,
) where
E: Clone,
{
for (_, matcherh) in matcherb {
for (_, matcher) in matcherh {
let built_matcher = matcher.build(bot.clone());
let handler = built_matcher.get_handler();
let lock_handler = handler.read().await;
if disconnect {
lock_handler.on_bot_disconnect(matcher.clone());
} else {
lock_handler.on_bot_connect(matcher.clone());
}
}
}
}
run_on_connect_(&self.message, bot.clone(), disconnect).await;
run_on_connect_(&self.notice, bot.clone(), disconnect).await;
run_on_connect_(&self.request, bot.clone(), disconnect).await;
run_on_connect_(&self.meta, bot.clone(), disconnect).await;
}
pub async fn load_all_matcher_config(&self) {
async fn f<E>(
matcherb: &MatchersBTreeMap<E>,
config: &HashMap<String, HashMap<String, toml::Value>>,
) where
E: Clone,
{
for (_, matcherh) in matcherb {
for (matcher_name, matcher) in matcherh {
if let Some(data) = config.get(&matcher_name.to_lowercase()) {
let handler = matcher.get_handler();
let mut lock_handler = handler.write().await;
lock_handler.load_config(data.clone());
}
}
}
}
f(&self.message, &self.config).await;
f(&self.notice, &self.config).await;
f(&self.request, &self.config).await;
f(&self.meta, &self.config).await;
}
#[doc(hidden)]
fn add_matcher<E>(
matcherb: &mut MatchersBTreeMap<E>,
mut matcher: Matcher<E>,
action_sender: broadcast::Sender<MatchersAction>,
) where
E: Clone,
{
matcher.set_action_sender(action_sender);
match matcherb.get_mut(&matcher.priority) {
Some(h) => {
h.insert(matcher.name.clone(), matcher);
}
None => {
let mut hashmap: MatchersHashMap<E> = HashMap::new();
hashmap.insert(matcher.name.clone(), matcher.clone());
matcherb.insert(matcher.priority, hashmap);
}
}
}
pub fn add_message_matcher(&mut self, matcher: Matcher<MessageEvent>) -> &mut Self {
Matchers::add_matcher(&mut self.message, matcher, self.action_sender.clone());
self
}
pub fn add_message_matchers(&mut self, matchers: Vec<Matcher<MessageEvent>>) -> &mut Self {
for m in matchers {
self.add_message_matcher(m);
}
self
}
pub fn add_notice_matcher(&mut self, matcher: Matcher<NoticeEvent>) -> &mut Self {
Matchers::add_matcher(&mut self.notice, matcher, self.action_sender.clone());
self
}
pub fn add_request_matcher(&mut self, matcher: Matcher<RequestEvent>) -> &mut Self {
Matchers::add_matcher(&mut self.request, matcher, self.action_sender.clone());
self
}
pub fn add_meta_matcher(&mut self, matcher: Matcher<MetaEvent>) -> &mut Self {
Matchers::add_matcher(&mut self.meta, matcher, self.action_sender.clone());
self
}
pub fn remove_matcher(&mut self, name: &str) {
fn remove_matcher_<E>(matcherb: &mut MatchersBTreeMap<E>, name: &str)
where
E: Clone,
{
for (_, matcherh) in matcherb.iter_mut() {
if let Some(_) = matcherh.remove(name) {
return;
}
}
}
remove_matcher_(&mut self.message, name);
remove_matcher_(&mut self.notice, name);
remove_matcher_(&mut self.request, name);
remove_matcher_(&mut self.meta, name);
}
pub fn disable_matcher(&mut self, name: &str, disable: bool) {
fn disable_matcher_<E>(matcherb: &mut MatchersBTreeMap<E>, name: &str, disable: bool)
where
E: Clone,
{
for (_, matcherh) in matcherb.iter_mut() {
if let Some(matcher) = matcherh.get_mut(name) {
matcher.set_disable(disable);
}
}
}
disable_matcher_(&mut self.message, name, disable);
disable_matcher_(&mut self.notice, name, disable);
disable_matcher_(&mut self.request, name, disable);
disable_matcher_(&mut self.meta, name, disable);
}
}
#[doc(hidden)]
fn unoptionb<K, D>(input: &Option<BTreeMap<K, D>>) -> BTreeMap<K, D>
where
K: Clone + std::cmp::Ord,
D: Clone,
{
match input {
Some(t) => t.clone(),
None => BTreeMap::new(),
}
}