fix: handle reaction remove emoji, remove all events
All checks were successful
Build / Build (push) Successful in 44s
Build / docker (push) Successful in 16s

This commit is contained in:
파링 2026-01-07 16:05:18 +09:00
parent a48bb14509
commit e934da887f
Signed by: paring
SSH key fingerprint: SHA256:8uCHhCpn/gVOLEaTolmbub9kfM6XBxWkIWmHxUZoWWk

View file

@ -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<String, i64> = 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)