only responds one to multiple regex matches
This commit is contained in:
parent
4e6430ad27
commit
b184361355
4 changed files with 114 additions and 55 deletions
|
@ -1,3 +1,5 @@
|
||||||
|
use super::{PassiveResponder, PassiveResponse};
|
||||||
|
use crate::util::debug_say_owned;
|
||||||
use futures::future::BoxFuture;
|
use futures::future::BoxFuture;
|
||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
use log::trace;
|
use log::trace;
|
||||||
|
@ -5,9 +7,8 @@ use rand::seq::SliceRandom;
|
||||||
use rand::thread_rng;
|
use rand::thread_rng;
|
||||||
use rand::Rng;
|
use rand::Rng;
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
use serenity::async_trait;
|
|
||||||
use serenity::model::channel::Message;
|
use serenity::model::channel::Message;
|
||||||
use serenity::prelude::{Context, EventHandler};
|
use serenity::prelude::Context;
|
||||||
|
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -18,34 +19,41 @@ lazy_static! {
|
||||||
|
|
||||||
pub(crate) struct DesuResponder;
|
pub(crate) struct DesuResponder;
|
||||||
|
|
||||||
#[async_trait]
|
impl PassiveResponder for DesuResponder {
|
||||||
impl EventHandler for DesuResponder {
|
fn get_message(
|
||||||
async fn message(&self, ctx: Context, message: Message) {
|
&self,
|
||||||
let content = message.content_safe(ctx.clone()).await;
|
received_msg: String,
|
||||||
let fufufu_match = FUFUFU_REGEX.is_match(&content);
|
ctx: Context,
|
||||||
let desu_match = DESU_REGEX.is_match(&content) && thread_rng().gen::<f32>() < 0.1;
|
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 {
|
if fufufu_match || desu_match {
|
||||||
trace!(
|
trace!(
|
||||||
"Responding to `{}` because one of the following matched: fufufu={}, desu={}",
|
"Responding to `{}` because one of the following matched: fufufu={}, desu={}",
|
||||||
content,
|
received_msg,
|
||||||
fufufu_match,
|
fufufu_match,
|
||||||
desu_match
|
desu_match
|
||||||
);
|
);
|
||||||
let random_action =
|
|
||||||
DESU_ACTIONS.choose(&mut thread_rng()).unwrap().clone()(ctx, message);
|
Some(DESU_ACTIONS.choose(&mut thread_rng()).unwrap().clone()(
|
||||||
random_action.await.unwrap();
|
ctx, message,
|
||||||
|
))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type DesuAction<'r, T> = &'r (dyn Fn(Context, Message) -> T + Sync);
|
type DesuAction<'r, T> = &'r (dyn Fn(Context, Message) -> T + Sync);
|
||||||
|
|
||||||
const DESU_ACTIONS: &[DesuAction<BoxFuture<Result<Message, serenity::Error>>>] = &[
|
const DESU_ACTIONS: &[DesuAction<BoxFuture<Result<Option<Message>, serenity::Error>>>] = &[
|
||||||
&|ctx, msg| Box::pin(msg.channel_id.say(ctx, "です。")),
|
&|ctx, msg| Box::pin(debug_say_owned(msg, ctx, "です。")),
|
||||||
&|ctx, msg| Box::pin(msg.channel_id.say(ctx, "desu~")),
|
&|ctx, msg| Box::pin(debug_say_owned(msg, ctx, "desu~")),
|
||||||
&|ctx, msg| Box::pin(msg.channel_id.say(ctx, "desu.")),
|
&|ctx, msg| Box::pin(debug_say_owned(msg, ctx, "desu.")),
|
||||||
&|ctx, msg| {
|
&|ctx, msg| {
|
||||||
Box::pin(msg.channel_id.say(
|
Box::pin(debug_say_owned(
|
||||||
|
msg,
|
||||||
ctx,
|
ctx,
|
||||||
r#"
|
r#"
|
||||||
```
|
```
|
||||||
|
@ -64,17 +72,24 @@ const DESU_ACTIONS: &[DesuAction<BoxFuture<Result<Message, serenity::Error>>>] =
|
||||||
&|ctx, msg| {
|
&|ctx, msg| {
|
||||||
// https://imgur.com/a/yOb5n
|
// https://imgur.com/a/yOb5n
|
||||||
// One day.
|
// One day.
|
||||||
Box::pin(
|
Box::pin(debug_say_owned(
|
||||||
msg.channel_id
|
msg,
|
||||||
.say(ctx, "https://www.youtube.com/watch?v=60mLvBWOMb4"),
|
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(),
|
|
||||||
})
|
|
||||||
}))
|
|
||||||
},
|
},
|
||||||
|
&|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?,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
|
@ -2,6 +2,8 @@ use ahhhh::YellResponder;
|
||||||
use all_caps::AllCapsResponder;
|
use all_caps::AllCapsResponder;
|
||||||
use best_doctor::BestDoctorResponder;
|
use best_doctor::BestDoctorResponder;
|
||||||
use desu::DesuResponder;
|
use desu::DesuResponder;
|
||||||
|
use futures::future::BoxFuture;
|
||||||
|
use rand::{rngs::OsRng, seq::IteratorRandom};
|
||||||
use reee::ReeeResponder;
|
use reee::ReeeResponder;
|
||||||
use serenity::async_trait;
|
use serenity::async_trait;
|
||||||
use serenity::model::channel::Message;
|
use serenity::model::channel::Message;
|
||||||
|
@ -14,7 +16,7 @@ mod desu;
|
||||||
mod reee;
|
mod reee;
|
||||||
|
|
||||||
pub(crate) struct Handler {
|
pub(crate) struct Handler {
|
||||||
responders: Vec<Box<dyn EventHandler>>,
|
responders: Vec<Box<dyn PassiveResponder + Send + Sync>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Handler {
|
impl Default for Handler {
|
||||||
|
@ -34,8 +36,15 @@ impl Default for Handler {
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl EventHandler for Handler {
|
impl EventHandler for Handler {
|
||||||
async fn message(&self, ctx: Context, message: Message) {
|
async fn message(&self, ctx: Context, message: Message) {
|
||||||
for responder in self.responders.iter() {
|
let received_msg = message.content_safe(ctx.clone()).await;
|
||||||
responder.message(ctx.clone(), message.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;
|
pub(crate) struct $name;
|
||||||
|
|
||||||
#[serenity::async_trait]
|
impl crate::passive::PassiveResponder for $name {
|
||||||
impl serenity::prelude::EventHandler for $name {
|
fn get_message(
|
||||||
async fn message(
|
|
||||||
&self,
|
&self,
|
||||||
|
received_msg: String,
|
||||||
ctx: serenity::prelude::Context,
|
ctx: serenity::prelude::Context,
|
||||||
message: serenity::model::channel::Message,
|
message: serenity::model::channel::Message,
|
||||||
) {
|
) -> Option<crate::passive::PassiveResponse<'_>> {
|
||||||
let msg = message.content_safe(ctx.clone()).await;
|
if REGEX.is_match(&received_msg) {
|
||||||
if REGEX.is_match(&msg) {
|
log::trace!("{} matched regex {:?}", received_msg, REGEX);
|
||||||
log::trace!("{} matched regex {:?}", msg, REGEX);
|
Some(Box::pin(crate::util::debug_say_owned(
|
||||||
message.channel_id.say(ctx, $phrase).await.unwrap();
|
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>;
|
||||||
|
}
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
|
use super::{PassiveResponder, PassiveResponse};
|
||||||
|
use crate::util::debug_say_owned;
|
||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
use serenity::async_trait;
|
|
||||||
use serenity::model::channel::Message;
|
use serenity::model::channel::Message;
|
||||||
use serenity::prelude::{Context, EventHandler};
|
use serenity::prelude::Context;
|
||||||
|
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
static ref REGEX: Regex = Regex::new("RE{5,}").unwrap();
|
static ref REGEX: Regex = Regex::new("RE{5,}").unwrap();
|
||||||
|
@ -10,19 +11,24 @@ lazy_static! {
|
||||||
|
|
||||||
pub(crate) struct ReeeResponder;
|
pub(crate) struct ReeeResponder;
|
||||||
|
|
||||||
#[async_trait]
|
impl PassiveResponder for ReeeResponder {
|
||||||
impl EventHandler for ReeeResponder {
|
fn get_message(
|
||||||
async fn message(&self, ctx: Context, message: Message) {
|
&self,
|
||||||
if REGEX.is_match(&message.content_safe(ctx.clone()).await) {
|
received_msg: String,
|
||||||
if let Some(guild_id) = message.guild_id {
|
ctx: Context,
|
||||||
if guild_id == 679888177951277102 {
|
message: Message,
|
||||||
message
|
) -> Option<PassiveResponse<'_>> {
|
||||||
.channel_id
|
if REGEX.is_match(&received_msg) {
|
||||||
.say(ctx, "<:texaspat:680231475928498217>")
|
if let Some(guild_id) = &message.guild_id {
|
||||||
.await
|
if guild_id == &679888177951277102 {
|
||||||
.unwrap();
|
return Some(Box::pin(debug_say_owned(
|
||||||
|
message,
|
||||||
|
ctx,
|
||||||
|
"<:texaspat:680231475928498217>",
|
||||||
|
)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,9 @@
|
||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
use serenity::{
|
use serenity::{
|
||||||
// builder::CreateMessage,
|
|
||||||
http::Http,
|
http::Http,
|
||||||
model::{channel::Message, id::ChannelId},
|
model::{channel::Message, id::ChannelId},
|
||||||
};
|
};
|
||||||
use std::env::var;
|
use std::{borrow::Cow, env::var};
|
||||||
pub mod db;
|
pub mod db;
|
||||||
pub mod error;
|
pub mod error;
|
||||||
pub mod operators;
|
pub mod operators;
|
||||||
|
@ -28,6 +27,22 @@ pub async fn debug_say(
|
||||||
msg: &Message,
|
msg: &Message,
|
||||||
ctx: impl AsRef<Http>,
|
ctx: impl AsRef<Http>,
|
||||||
resp: impl std::fmt::Display,
|
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> {
|
) -> Result<Option<Message>, serenity::Error> {
|
||||||
debug_channel_say(&msg.channel_id, *msg.author.id.as_u64(), ctx, resp).await
|
debug_channel_say(&msg.channel_id, *msg.author.id.as_u64(), ctx, resp).await
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue