mirror of
https://github.com/natsukagami/youmubot.git
synced 2025-04-19 16:58:55 +00:00
Prelude/Main: rework hook system
This commit is contained in:
parent
b819509244
commit
238e44a64c
5 changed files with 96 additions and 47 deletions
|
@ -25,7 +25,11 @@ lazy_static! {
|
||||||
).unwrap();
|
).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn hook(ctx: &Context, msg: &Message) -> Result<()> {
|
pub fn hook<'a>(
|
||||||
|
ctx: &'a Context,
|
||||||
|
msg: &'a Message,
|
||||||
|
) -> std::pin::Pin<Box<dyn future::Future<Output = Result<()>> + Send + 'a>> {
|
||||||
|
Box::pin(async move {
|
||||||
if msg.author.bot {
|
if msg.author.bot {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
@ -68,6 +72,7 @@ pub async fn hook(ctx: &Context, msg: &Message) -> Result<()> {
|
||||||
super::cache::save_beatmap(&*ctx.data.read().await, msg.channel_id, &t)?;
|
super::cache::save_beatmap(&*ctx.data.read().await, msg.channel_id, &t)?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
enum EmbedType {
|
enum EmbedType {
|
||||||
|
|
|
@ -49,7 +49,7 @@ impl TypeMapKey for OsuClient {
|
||||||
/// - Commands on the "osu" prefix
|
/// - Commands on the "osu" prefix
|
||||||
/// - Hooks. Hooks are completely opt-in.
|
/// - Hooks. Hooks are completely opt-in.
|
||||||
///
|
///
|
||||||
pub async fn setup(
|
pub fn setup(
|
||||||
path: &std::path::Path,
|
path: &std::path::Path,
|
||||||
data: &mut TypeMap,
|
data: &mut TypeMap,
|
||||||
announcers: &mut AnnouncerHandler,
|
announcers: &mut AnnouncerHandler,
|
||||||
|
|
24
youmubot-prelude/src/hook.rs
Normal file
24
youmubot-prelude/src/hook.rs
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
use crate::{async_trait, future, Context, Result};
|
||||||
|
use serenity::model::channel::Message;
|
||||||
|
|
||||||
|
/// Hook represents the asynchronous hook that is run on every message.
|
||||||
|
#[async_trait]
|
||||||
|
pub trait Hook: Send + Sync {
|
||||||
|
async fn call(&mut self, ctx: &Context, message: &Message) -> Result<()>;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
|
impl<T> Hook for T
|
||||||
|
where
|
||||||
|
T: for<'a> FnMut(
|
||||||
|
&'a Context,
|
||||||
|
&'a Message,
|
||||||
|
)
|
||||||
|
-> std::pin::Pin<Box<dyn future::Future<Output = Result<()>> + 'a + Send>>
|
||||||
|
+ Send
|
||||||
|
+ Sync,
|
||||||
|
{
|
||||||
|
async fn call(&mut self, ctx: &Context, message: &Message) -> Result<()> {
|
||||||
|
self(ctx, message).await
|
||||||
|
}
|
||||||
|
}
|
|
@ -5,11 +5,13 @@ use std::sync::Arc;
|
||||||
|
|
||||||
pub mod announcer;
|
pub mod announcer;
|
||||||
pub mod args;
|
pub mod args;
|
||||||
|
pub mod hook;
|
||||||
pub mod pagination;
|
pub mod pagination;
|
||||||
pub mod setup;
|
pub mod setup;
|
||||||
|
|
||||||
pub use announcer::{Announcer, AnnouncerHandler};
|
pub use announcer::{Announcer, AnnouncerHandler};
|
||||||
pub use args::{Duration, UsernameArg};
|
pub use args::{Duration, UsernameArg};
|
||||||
|
pub use hook::Hook;
|
||||||
pub use pagination::paginate;
|
pub use pagination::paginate;
|
||||||
|
|
||||||
/// Re-exporting async_trait helps with implementing Announcer.
|
/// Re-exporting async_trait helps with implementing Announcer.
|
||||||
|
|
|
@ -13,13 +13,17 @@ use serenity::{
|
||||||
use youmubot_prelude::*;
|
use youmubot_prelude::*;
|
||||||
|
|
||||||
struct Handler {
|
struct Handler {
|
||||||
hooks: Vec<fn(&mut Context, &Message) -> ()>,
|
hooks: Vec<RwLock<Box<dyn Hook>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Handler {
|
impl Handler {
|
||||||
fn new() -> Handler {
|
fn new() -> Handler {
|
||||||
Handler { hooks: vec![] }
|
Handler { hooks: vec![] }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn push_hook<T: Hook + 'static>(&mut self, f: T) {
|
||||||
|
self.hooks.push(RwLock::new(Box::new(f)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
|
@ -28,8 +32,22 @@ impl EventHandler for Handler {
|
||||||
println!("{} is connected!", ready.user.name);
|
println!("{} is connected!", ready.user.name);
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn message(&self, mut ctx: Context, message: Message) {
|
async fn message(&self, ctx: Context, message: Message) {
|
||||||
self.hooks.iter().for_each(|f| f(&mut ctx, &message));
|
self.hooks
|
||||||
|
.iter()
|
||||||
|
.map(|hook| {
|
||||||
|
let ctx = ctx.clone();
|
||||||
|
let message = message.clone();
|
||||||
|
hook.write()
|
||||||
|
.then(|mut h| async move { h.call(&ctx, &message).await })
|
||||||
|
})
|
||||||
|
.collect::<stream::FuturesUnordered<_>>()
|
||||||
|
.for_each(|v| async move {
|
||||||
|
if let Err(e) = v {
|
||||||
|
eprintln!("{}", e)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.await;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,12 +71,12 @@ async fn main() {
|
||||||
println!("Loaded dotenv from {:?}", path);
|
println!("Loaded dotenv from {:?}", path);
|
||||||
}
|
}
|
||||||
|
|
||||||
let handler = Handler::new();
|
let mut handler = Handler::new();
|
||||||
// Set up hooks
|
// Set up hooks
|
||||||
#[cfg(feature = "osu")]
|
#[cfg(feature = "osu")]
|
||||||
handler.hooks.push(youmubot_osu::discord::hook);
|
handler.push_hook(youmubot_osu::discord::hook);
|
||||||
#[cfg(feature = "codeforces")]
|
#[cfg(feature = "codeforces")]
|
||||||
handler.hooks.push(youmubot_cf::codeforces_info_hook);
|
handler.push_hook(youmubot_cf::codeforces_info_hook);
|
||||||
|
|
||||||
// Collect the token
|
// Collect the token
|
||||||
let token = var("TOKEN").expect("Please set TOKEN as the Discord Bot's token to be used.");
|
let token = var("TOKEN").expect("Please set TOKEN as the Discord Bot's token to be used.");
|
||||||
|
|
Loading…
Add table
Reference in a new issue