diff --git a/src/bot/handler.rs b/src/bot/handler.rs index 622668a..134f761 100644 --- a/src/bot/handler.rs +++ b/src/bot/handler.rs @@ -54,12 +54,12 @@ pub struct Handler { #[async_trait] impl EventHandler for Handler { - async fn dispatch(&self, context: &Context, event: &FullEvent) { + async fn dispatch(&self, ctx: &Context, event: &FullEvent) { match event { FullEvent::Ready { data_about_bot, .. } => { info!("Bot is ready as {}", data_about_bot.user.tag()); - if let Err(e) = context + if let Err(e) = ctx .http .create_global_commands(&vec![ commands::config_command(), @@ -71,15 +71,34 @@ impl EventHandler for Handler { } } FullEvent::ReactionAdd { add_reaction, .. } => { - self.process_reaction(context, add_reaction, false).await; + self.process_reaction(ctx, add_reaction, false).await; } FullEvent::ReactionRemove { removed_reaction, .. } => { - self.process_reaction(context, removed_reaction, true).await; + self.process_reaction(ctx, removed_reaction, true).await; + } + FullEvent::ReactionRemoveEmoji { removed_reactions } => { + self.process_reaction(ctx, removed_reactions, true).await; + } + FullEvent::ReactionRemoveAll { + guild_id, + channel_id, + removed_from_message_id, + } => { + if let Some(guild_id) = guild_id { + self.process_reaction_message( + ctx, + *channel_id, + *removed_from_message_id, + *guild_id, + true, + ) + .await; + } } FullEvent::InteractionCreate { interaction } => { - if let Err(e) = self.interaction_create(context, interaction).await { + if let Err(e) = self.interaction_create(ctx, interaction).await { error!("Error while processing interaction: {e:?}"); } } @@ -117,9 +136,31 @@ impl Handler { } async fn process_reaction(&self, ctx: &Context, reaction: &Reaction, is_remove: bool) { + let Some(guild_id) = reaction.guild_id else { + return; + }; + + self.process_reaction_message( + ctx, + reaction.channel_id, + reaction.message_id, + guild_id, + is_remove, + ) + .await; + } + + async fn process_reaction_message( + &self, + ctx: &Context, + channel_id: GenericChannelId, + message_id: MessageId, + guild_id: GuildId, + is_remove: bool, + ) { let semaphore = { self.message_lock - .entry(reaction.message_id) + .entry(message_id) .or_insert_with(|| Arc::new(Semaphore::new(1))) .value() .clone() @@ -130,28 +171,27 @@ impl Handler { Err(_) => return, }; - if let Err(e) = self.process_reaction_inner(ctx, reaction, is_remove).await { + if let Err(e) = self + .process_reaction_inner(ctx, channel_id, message_id, guild_id, is_remove) + .await + { error!("Error while processing reaction add event: {e:?}"); } if Arc::strong_count(&semaphore) <= 2 { self.message_lock - .remove_if(&reaction.message_id, |_, val| Arc::strong_count(val) <= 2); + .remove_if(&message_id, |_, val| Arc::strong_count(val) <= 2); } } async fn process_reaction_inner( &self, ctx: &Context, - reaction: &Reaction, + channel_id: GenericChannelId, + message_id: MessageId, + guild_id: GuildId, is_remove: bool, ) -> anyhow::Result<()> { - if reaction.user((ctx.cache(), ctx.http())).await?.bot() { - return Ok(()); - } - let Some(guild_id) = reaction.guild_id else { - return Ok(()); - }; let Some(guild) = get_guild(&self.db, guild_id).await? else { return Ok(()); }; @@ -159,13 +199,19 @@ impl Handler { return Ok(()); }; - let existing_message = get_message(&self.db, reaction.message_id).await?; + let existing_message = get_message(&self.db, message_id).await?; if is_remove && existing_message.is_none() { return Ok(()); } - let msg = reaction.message((ctx.cache(), ctx.http())).await?; + let msg = channel_id + .message((ctx.cache(), ctx.http()), message_id) + .await?; + + if msg.author.bot() { + return Ok(()); + } let reactions: HashMap = msg .reactions @@ -179,14 +225,16 @@ impl Handler { CloneBuilderMessage::from(msg.clone()) }; - let channel = reaction.channel((ctx.cache(), ctx.http())).await?; + let channel = channel_id + .to_channel((ctx.cache(), ctx.http()), Some(guild_id)) + .await?; debug!("channel: {channel:?}"); let Some(result) = paringboard::script::check( script, reactions, - reaction.channel_id.to_string(), + channel_id.to_string(), channel .guild() .and_then(|x| x.parent_id)