use ahhhh::YellResponder; use all_caps::AllCapsResponder; use best_doctor::BestDoctorResponder; use desu::DesuResponder; use futures::future::BoxFuture; use rand::{rngs::OsRng, seq::IteratorRandom}; use reee::ReeeResponder; use serenity::async_trait; use serenity::model::channel::Message; use serenity::prelude::{Context, EventHandler}; mod ahhhh; mod all_caps; mod best_doctor; mod desu; mod reee; pub(crate) struct Handler { responders: Vec>, } impl Default for Handler { fn default() -> Self { Self { responders: vec![ Box::new(BestDoctorResponder), Box::new(DesuResponder), Box::new(YellResponder), Box::new(ReeeResponder), Box::new(AllCapsResponder), ], } } } #[async_trait] impl EventHandler for Handler { async fn message(&self, ctx: Context, message: Message) { let received_msg = message.content_safe(ctx.clone()).await; let valid_responses = self.responders.iter().filter_map(|responder| { responder.get_message(received_msg.clone(), ctx.clone(), message.clone()) }); if let Some(fut) = valid_responses.choose(&mut OsRng) { if let Err(err) = fut.await { log::warn!("Got an error while sending a passive response: {}", err); } } } } #[macro_export] macro_rules! simple_responder { // $phrase should be `expr`, see https://github.com/dtolnay/async-trait/issues/46 // above issue is blocked on rustc bug, see https://github.com/rust-lang/rust/issues/43081 ($name:tt, $regex:expr, $phrase:tt) => { lazy_static::lazy_static! { #[derive(Debug)] static ref REGEX: regex::Regex = regex::Regex::new($regex).unwrap(); } pub(crate) struct $name; impl crate::passive::PassiveResponder for $name { fn get_message( &self, received_msg: String, ctx: serenity::prelude::Context, message: serenity::model::channel::Message, ) -> Option> { if REGEX.is_match(&received_msg) { log::trace!("{} matched regex {:?}", received_msg, REGEX); Some(Box::pin(crate::util::debug_say_owned( message, ctx, $phrase, ))) } else { None } } } }; } type PassiveResponse<'a> = BoxFuture<'a, Result, serenity::Error>>; trait PassiveResponder { fn get_message( &self, received_msg: String, ctx: Context, message: Message, ) -> Option; }