use futures::future::BoxFuture; use lazy_static::lazy_static; use log::trace; use rand::seq::SliceRandom; use rand::thread_rng; use rand::Rng; use regex::Regex; use serenity::async_trait; use serenity::model::channel::Message; use serenity::prelude::{Context, EventHandler}; lazy_static! { #[derive(Debug)] static ref FUFUFU_REGEX: Regex = Regex::new("(?i:fu){3,}").unwrap(); #[derive(Debug)] static ref DESU_REGEX: Regex = Regex::new("(?i:desu)|(?:です)").unwrap(); } pub(crate) struct DesuResponder; #[async_trait] impl EventHandler for DesuResponder { async fn message(&self, ctx: Context, message: Message) { let content = message.content_safe(ctx.clone()).await; let fufufu_match = FUFUFU_REGEX.is_match(&content); let desu_match = DESU_REGEX.is_match(&content) && thread_rng().gen::() < 0.1; if fufufu_match || desu_match { trace!( "Responding to `{}` because one of the following matched: fufufu={}, desu={}", content, fufufu_match, desu_match ); let random_action = DESU_ACTIONS.choose(&mut thread_rng()).unwrap().clone()(ctx, message); random_action.await.unwrap(); } } } type DesuAction<'r, T> = &'r (dyn Fn(Context, Message) -> T + Sync); const DESU_ACTIONS: &[DesuAction>>] = &[ &|ctx, msg| Box::pin(msg.channel_id.say(ctx, "です。")), &|ctx, msg| Box::pin(msg.channel_id.say(ctx, "desu~")), &|ctx, msg| Box::pin(msg.channel_id.say(ctx, "desu.")), &|ctx, msg| { Box::pin(msg.channel_id.say( ctx, r#" ``` ででででででででででで      すす      ででで     すすすすすすすすす     でで  でで      すす    でで   でで     すすす   でで           す す   でで           すすす    でで           すす     でで          すす      でで        すす ```"#, )) }, &|ctx, msg| { // https://imgur.com/a/yOb5n // One day. Box::pin( msg.channel_id .say(ctx, "https://www.youtube.com/watch?v=60mLvBWOMb4"), ) }, &|ctx, msg| { Box::pin(msg.channel_id.send_message(ctx, |m| { m.add_file(serenity::http::AttachmentType::Bytes { data: std::borrow::Cow::from(&include_bytes!("../../res/desu.jpg")[..]), filename: "desu.jpg".to_string(), }) })) }, ];