only responds one to multiple regex matches

master
Edward Shen 2020-05-13 21:55:09 -04:00
parent 4e6430ad27
commit b184361355
Signed by: edward
GPG Key ID: 19182661E818369F
4 changed files with 114 additions and 55 deletions

View File

@ -1,3 +1,5 @@
use super::{PassiveResponder, PassiveResponse};
use crate::util::debug_say_owned;
use futures::future::BoxFuture;
use lazy_static::lazy_static;
use log::trace;
@ -5,9 +7,8 @@ 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};
use serenity::prelude::Context;
lazy_static! {
#[derive(Debug)]
@ -18,34 +19,41 @@ lazy_static! {
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::<f32>() < 0.1;
impl PassiveResponder for DesuResponder {
fn get_message(
&self,
received_msg: String,
ctx: Context,
message: Message,
) -> Option<PassiveResponse<'_>> {
let fufufu_match = FUFUFU_REGEX.is_match(&received_msg);
let desu_match = DESU_REGEX.is_match(&received_msg) && thread_rng().gen::<f32>() < 0.1;
if fufufu_match || desu_match {
trace!(
"Responding to `{}` because one of the following matched: fufufu={}, desu={}",
content,
received_msg,
fufufu_match,
desu_match
);
let random_action =
DESU_ACTIONS.choose(&mut thread_rng()).unwrap().clone()(ctx, message);
random_action.await.unwrap();
Some(DESU_ACTIONS.choose(&mut thread_rng()).unwrap().clone()(
ctx, message,
))
} else {
None
}
}
}
type DesuAction<'r, T> = &'r (dyn Fn(Context, Message) -> T + Sync);
const DESU_ACTIONS: &[DesuAction<BoxFuture<Result<Message, serenity::Error>>>] = &[
&|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.")),
const DESU_ACTIONS: &[DesuAction<BoxFuture<Result<Option<Message>, serenity::Error>>>] = &[
&|ctx, msg| Box::pin(debug_say_owned(msg, ctx, "です。")),
&|ctx, msg| Box::pin(debug_say_owned(msg, ctx, "desu~")),
&|ctx, msg| Box::pin(debug_say_owned(msg, ctx, "desu.")),
&|ctx, msg| {
Box::pin(msg.channel_id.say(
Box::pin(debug_say_owned(
msg,
ctx,
r#"
```
@ -64,17 +72,24 @@ const DESU_ACTIONS: &[DesuAction<BoxFuture<Result<Message, serenity::Error>>>] =
&|ctx, msg| {
// https://imgur.com/a/yOb5n
// One day.
Box::pin(
msg.channel_id
.say(ctx, "https://www.youtube.com/watch?v=60mLvBWOMb4"),
)
Box::pin(debug_say_owned(
msg,
ctx,
"https://www.youtube.com/watch?v=60mLvBWOMb4",
))
},
&|ctx, msg| {
Box::pin(msg.channel_id.send_message(ctx, |m| {
&|ctx, msg| Box::pin(send_desu_image(ctx, msg)),
];
async fn send_desu_image(ctx: Context, msg: Message) -> Result<Option<Message>, serenity::Error> {
Ok(Some(
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(),
})
}))
},
];
})
.await?,
))
}

View File

@ -2,6 +2,8 @@ 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;
@ -14,7 +16,7 @@ mod desu;
mod reee;
pub(crate) struct Handler {
responders: Vec<Box<dyn EventHandler>>,
responders: Vec<Box<dyn PassiveResponder + Send + Sync>>,
}
impl Default for Handler {
@ -34,8 +36,15 @@ impl Default for Handler {
#[async_trait]
impl EventHandler for Handler {
async fn message(&self, ctx: Context, message: Message) {
for responder in self.responders.iter() {
responder.message(ctx.clone(), message.clone()).await;
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);
}
}
}
}
@ -52,19 +61,33 @@ macro_rules! simple_responder {
pub(crate) struct $name;
#[serenity::async_trait]
impl serenity::prelude::EventHandler for $name {
async fn message(
impl crate::passive::PassiveResponder for $name {
fn get_message(
&self,
received_msg: String,
ctx: serenity::prelude::Context,
message: serenity::model::channel::Message,
) {
let msg = message.content_safe(ctx.clone()).await;
if REGEX.is_match(&msg) {
log::trace!("{} matched regex {:?}", msg, REGEX);
message.channel_id.say(ctx, $phrase).await.unwrap();
) -> Option<crate::passive::PassiveResponse<'_>> {
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<Option<Message>, serenity::Error>>;
trait PassiveResponder {
fn get_message(
&self,
received_msg: String,
ctx: Context,
message: Message,
) -> Option<PassiveResponse>;
}

View File

@ -1,8 +1,9 @@
use super::{PassiveResponder, PassiveResponse};
use crate::util::debug_say_owned;
use lazy_static::lazy_static;
use regex::Regex;
use serenity::async_trait;
use serenity::model::channel::Message;
use serenity::prelude::{Context, EventHandler};
use serenity::prelude::Context;
lazy_static! {
static ref REGEX: Regex = Regex::new("RE{5,}").unwrap();
@ -10,19 +11,24 @@ lazy_static! {
pub(crate) struct ReeeResponder;
#[async_trait]
impl EventHandler for ReeeResponder {
async fn message(&self, ctx: Context, message: Message) {
if REGEX.is_match(&message.content_safe(ctx.clone()).await) {
if let Some(guild_id) = message.guild_id {
if guild_id == 679888177951277102 {
message
.channel_id
.say(ctx, "<:texaspat:680231475928498217>")
.await
.unwrap();
impl PassiveResponder for ReeeResponder {
fn get_message(
&self,
received_msg: String,
ctx: Context,
message: Message,
) -> Option<PassiveResponse<'_>> {
if REGEX.is_match(&received_msg) {
if let Some(guild_id) = &message.guild_id {
if guild_id == &679888177951277102 {
return Some(Box::pin(debug_say_owned(
message,
ctx,
"<:texaspat:680231475928498217>",
)));
}
}
}
None
}
}

View File

@ -1,10 +1,9 @@
use lazy_static::lazy_static;
use serenity::{
// builder::CreateMessage,
http::Http,
model::{channel::Message, id::ChannelId},
};
use std::env::var;
use std::{borrow::Cow, env::var};
pub mod db;
pub mod error;
pub mod operators;
@ -28,6 +27,22 @@ pub async fn debug_say(
msg: &Message,
ctx: impl AsRef<Http>,
resp: impl std::fmt::Display,
) -> Result<Option<Message>, serenity::Error> {
debug_say_cow(Cow::Borrowed(msg), ctx, resp).await
}
pub async fn debug_say_owned(
msg: Message,
ctx: impl AsRef<Http>,
resp: impl std::fmt::Display,
) -> Result<Option<Message>, serenity::Error> {
debug_say_cow(Cow::Owned(msg), ctx, resp).await
}
async fn debug_say_cow(
msg: Cow<'_, Message>,
ctx: impl AsRef<Http>,
resp: impl std::fmt::Display,
) -> Result<Option<Message>, serenity::Error> {
debug_channel_say(&msg.channel_id, *msg.author.id.as_u64(), ctx, resp).await
}