Compare commits

1 Commits
dev ... master

Author SHA1 Message Date
962b2359c1 Fix voice text channel detection & cross-channel hour purge (#1)
All checks were successful
ci/woodpecker/push/build Pipeline was successful
Two fixes in `src/handlers.rs`:

**1. Voice text channel detection**
Messages sent in voice channel text threads have a different `channel_id` than the parent voice channel. The `message` handler now falls through to check `msg.thread.parent_id` — if the parent is a watched channel, it catches them.

**2. Cross-channel 1-hour message purge**
When a user is banned, the bot now fetches the last 10 messages from **every** watched channel in the guild and bulk-deletes any from that user within the past hour (snowflake timestamp boundary). Catches messages sent before the trigger message hit.

Reviewed-on: http://git.infernonode.com/HotaruBlaze/Cinderwatch/pulls/1
Co-authored-by: Hermes-Neo <hermes-neo@noreply.localhost>
Co-committed-by: Hermes-Neo <hermes-neo@noreply.localhost>
2026-07-02 12:59:44 +01:00

View File

@@ -4,10 +4,14 @@ use serenity::all::ActivityData;
use serenity::model::channel::MessageFlags; use serenity::model::channel::MessageFlags;
use serenity::{ use serenity::{
async_trait, async_trait,
builder::{CreateAttachment, CreateMessage}, builder::{CreateAttachment, CreateMessage, GetMessages},
client::Context, client::Context,
model::{ model::{
application::Interaction, channel::Message, gateway::Ready, guild::Guild, id::GuildId, application::Interaction,
channel::Message,
gateway::Ready,
guild::Guild,
id::{GuildId, MessageId},
user::OnlineStatus, user::OnlineStatus,
}, },
}; };
@@ -85,9 +89,31 @@ impl serenity::client::EventHandler for Handler {
None => return, None => return,
}; };
match self.db.is_watched_channel(guild_id, msg.channel_id) { // Check if the channel itself is watched, or if this message is in a
Ok(true) => {} // thread (e.g. a voice text channel) whose parent channel is watched.
_ => return, let is_watched = self
.db
.is_watched_channel(guild_id, msg.channel_id)
.unwrap_or(false);
if !is_watched {
if let Some(ref thread_channel) = msg.thread {
if let Some(parent_id) = thread_channel.parent_id {
if self
.db
.is_watched_channel(guild_id, parent_id)
.unwrap_or(false)
{
// This message is in a thread whose parent is watched
} else {
return;
}
} else {
return;
}
} else {
return;
}
} }
if let Err(e) = self if let Err(e) = self
@@ -191,6 +217,38 @@ impl Handler {
let _ = msg.delete(&ctx.http).await; let _ = msg.delete(&ctx.http).await;
// Purge this user's messages from ALL watched channels within the past hour.
let watched = match self.db.get_watched_channels(guild_id) {
Ok(channels) => channels,
Err(e) => {
eprintln!("Failed to get watched channels: {:?}", e);
vec![]
}
};
let one_hour_ago = msg.id.get() - (3_600_000 << 22);
for channel_id in watched {
let Ok(batch) = channel_id
.messages(&ctx.http, GetMessages::new().limit(10))
.await
else {
continue;
};
let to_delete: Vec<MessageId> = batch
.iter()
.filter(|m| m.author.id == msg.author.id && m.id.get() >= one_hour_ago)
.map(|m| m.id)
.collect();
for chunk in to_delete.chunks(100) {
if let Err(e) = channel_id.delete_messages(&ctx.http, chunk).await {
eprintln!("Failed to bulk delete in {channel_id}: {e:?}");
}
}
}
let ban_reason = self let ban_reason = self
.db .db
.get_ban_reason(guild_id) .get_ban_reason(guild_id)