nonebot_rs/matcher/matchers/
mod.rs1use crate::event::{Event, MessageEvent, MetaEvent, NoticeEvent, RequestEvent, SelfId};
2use crate::matcher::Matcher;
3use async_trait::async_trait;
4use colored::*;
5use std::collections::{BTreeMap, HashMap};
6use tokio::sync::broadcast;
7use tracing::{event, Level};
8
9mod action;
10
11pub type MatchersBTreeMap<E> = BTreeMap<i8, MatchersHashMap<E>>;
13pub type MatchersHashMap<E> = HashMap<String, Matcher<E>>;
15pub type ActionSender = broadcast::Sender<super::action::MatchersAction>;
17
18pub const PLUGIN_NAME: &'static str = "Matcher";
19
20#[derive(Clone, Debug)]
22pub struct Matchers {
23 pub message: MatchersBTreeMap<MessageEvent>,
25 pub notice: MatchersBTreeMap<NoticeEvent>,
27 pub request: MatchersBTreeMap<RequestEvent>,
29 pub meta: MatchersBTreeMap<MetaEvent>,
31 bot_getter: Option<crate::BotGetter>,
33 action_sender: ActionSender,
35 config: HashMap<String, HashMap<String, toml::Value>>,
37}
38
39impl Matchers {
40 async fn handle_events(&mut self, event: Event, bot: &crate::bot::Bot) {
41 match event {
42 Event::Message(e) => {
43 self.handle_event(self.message.clone(), e, bot.clone())
44 .await;
45 }
46 Event::Notice(e) => {
47 self.handle_event(self.notice.clone(), e, bot.clone()).await;
48 }
49 Event::Request(e) => {
50 self.handle_event(self.request.clone(), e, bot.clone())
51 .await;
52 }
53 Event::Meta(e) => {
54 self.handle_event(self.meta.clone(), e, bot.clone()).await;
55 }
56 Event::Nonebot(e) => match e {
57 crate::event::NbEvent::BotConnect { bot } => {
58 log_load_matchers(&self);
59 self.run_on_connect(bot, false).await;
60 }
61 crate::event::NbEvent::BotDisconnect { bot } => {
62 self.run_on_connect(bot, true).await;
63 }
64 },
65 }
66 }
67
68 async fn handle_event<E>(
70 &mut self,
71 mut matcherb: MatchersBTreeMap<E>,
72 event: E,
73 bot: crate::bot::Bot,
74 ) where
75 E: Clone + Send + 'static + std::fmt::Debug + SelfId,
76 {
77 event!(Level::TRACE, "handling event {:?}", event);
78 for (_, matcherh) in matcherb.iter_mut() {
80 if self
81 ._handler_event(matcherh, event.clone(), bot.clone())
82 .await
83 {
84 break;
85 };
86 }
87 }
88
89 #[doc(hidden)]
90 async fn _handler_event<E>(
91 &mut self,
92 matcherh: &mut MatchersHashMap<E>,
93 e: E,
94 bot: crate::bot::Bot,
95 ) -> bool
96 where
97 E: Clone + Send + 'static + std::fmt::Debug + SelfId,
98 {
99 event!(Level::TRACE, "handling event_ {:?}", e);
100 let mut get_block = false;
102 let config = bot.config.clone();
103 for (name, matcher) in matcherh.iter_mut() {
104 let matched = matcher
105 .build(bot.clone())
106 .match_(e.clone(), config.clone(), self)
107 .await;
108 if matched {
109 event!(Level::INFO, "Matched {}", name.blue());
110 if matcher.is_block() {
111 get_block = true;
112 }
113 if matcher.is_temp() {
114 event!(Level::INFO, "Remove matched temp matcher {}", name.blue());
115 self.remove_matcher(name);
116 }
117 }
118 }
119 get_block
120 }
121
122 async fn event_recv(mut self, mut event_receiver: crate::EventReceiver) {
123 let mut receiver = self.action_sender.subscribe();
124 while let Ok(event) = event_receiver.recv().await {
125
126 match receiver.try_recv() {
127 Ok(action) => self.handle_action(action),
128 Err(_) => {}
129 }
130
131 let bots = self.bot_getter.clone().unwrap().borrow().clone();
132 if let Some(bot) = bots.get(&event.get_self_id()) {
133 self.handle_events(event, bot).await;
134 }
135 }
136 }
137}
138
139#[async_trait]
140impl crate::Plugin for Matchers {
141 fn run(&self, event_receiver: crate::EventReceiver, bot_getter: crate::BotGetter) {
142 let mut m = self.clone();
143 m.bot_getter = Some(bot_getter.clone());
144 tokio::spawn(m.event_recv(event_receiver));
145 }
146
147 fn plugin_name(&self) -> &'static str {
148 PLUGIN_NAME
149 }
150
151 async fn load_config(&mut self, config: toml::Value) {
152 let config: HashMap<String, HashMap<String, toml::Value>> =
153 config.try_into().expect("Matchers get error config");
154 self.config = config;
155 self.load_all_matcher_config().await;
156 event!(Level::INFO, "Loaded Matchers config: {:?}", self.config);
157 }
158}
159
160fn log_load_matchers(matchers: &crate::Matchers) {
161 log_matcherb(&matchers.message);
162 log_matcherb(&matchers.notice);
163 log_matcherb(&matchers.request);
164 log_matcherb(&matchers.meta);
165}
166
167fn log_matcherb<E>(matcherb: &MatchersBTreeMap<E>)
168where
169 E: Clone,
170{
171 if matcherb.is_empty() {
172 return;
173 }
174 for (_, matcherh) in matcherb {
175 for (name, _) in matcherh {
176 event!(Level::INFO, "Matcher {} is Loaded", name.blue());
177 }
178 }
179}