Make ReactionHandler handle even reaction removals

This commit is contained in:
Natsu Kagami 2020-02-06 20:26:19 -05:00
parent d8305df52a
commit 472ebf9d2d
Signed by: nki
GPG key ID: 73376E117CD20735
2 changed files with 24 additions and 10 deletions

View file

@ -8,22 +8,24 @@ use std::sync::{Arc, Mutex};
pub trait ReactionHandler {
/// Handle a reaction. This is fired on EVERY reaction.
/// You do the filtering yourself.
fn handle_reaction(&mut self, reaction: &Reaction) -> CommandResult;
///
/// If `is_added` is false, the reaction was removed instead of added.
fn handle_reaction(&mut self, reaction: &Reaction, is_added: bool) -> CommandResult;
}
impl<T> ReactionHandler for T
where
T: FnMut(&Reaction) -> CommandResult,
T: FnMut(&Reaction, bool) -> CommandResult,
{
fn handle_reaction(&mut self, reaction: &Reaction) -> CommandResult {
self(reaction)
fn handle_reaction(&mut self, reaction: &Reaction, is_added: bool) -> CommandResult {
self(reaction, is_added)
}
}
/// The store for a set of dynamic reaction handlers.
#[derive(Debug, Clone)]
pub struct ReactionWatcher {
channels: Arc<Mutex<Vec<Sender<Arc<Reaction>>>>>,
channels: Arc<Mutex<Vec<Sender<(Arc<Reaction>, bool)>>>>,
}
impl TypeMapKey for ReactionWatcher {
@ -38,12 +40,13 @@ impl ReactionWatcher {
}
}
/// Send a reaction.
pub fn send(&self, r: Reaction) {
/// If `is_added` is false, the reaction was removed.
pub fn send(&self, r: Reaction, is_added: bool) {
let r = Arc::new(r);
self.channels
.lock()
.expect("Poisoned!")
.retain(|e| e.send(r.clone()).is_ok());
.retain(|e| e.send((r.clone(), is_added)).is_ok());
}
/// React! to a series of reaction
///
@ -60,7 +63,7 @@ impl ReactionWatcher {
let timeout = after(duration);
loop {
let r = select! {
recv(reactions) -> r => h.handle_reaction(&*r.unwrap()),
recv(reactions) -> r => { let (r, is_added) = r.unwrap(); h.handle_reaction(&*r, is_added) },
recv(timeout) -> _ => break,
};
if let Err(v) = r {

View file

@ -2,7 +2,10 @@ use dotenv;
use dotenv::var;
use serenity::{
framework::standard::{DispatchError, StandardFramework},
model::{channel::{Message, Reaction}, gateway},
model::{
channel::{Message, Reaction},
gateway,
},
};
use youmubot_prelude::*;
@ -27,7 +30,15 @@ impl EventHandler for Handler {
}
fn reaction_add(&self, ctx: Context, reaction: Reaction) {
ctx.data.get_cloned::<ReactionWatcher>().send(reaction);
ctx.data
.get_cloned::<ReactionWatcher>()
.send(reaction, true);
}
fn reaction_remove(&self, ctx: Context, reaction: Reaction) {
ctx.data
.get_cloned::<ReactionWatcher>()
.send(reaction, false);
}
}