remove reactions from messages older than n days

This commit is contained in:
seth 2024-04-02 19:23:15 -04:00
parent a8d6a2b8d7
commit 94b12a1069
No known key found for this signature in database
GPG key ID: D31BD0D494BBEE86
9 changed files with 86 additions and 18 deletions

View file

@ -1,5 +1,6 @@
use std::str::FromStr;
use eyre::{Context, Result};
use log::{info, warn};
use poise::serenity_prelude::ChannelId;
@ -12,6 +13,7 @@ pub struct RefractionChannels {
#[derive(Clone, Debug, Default)]
pub struct Config {
pub channels: RefractionChannels,
pub days_to_delete_reaction: i64,
}
impl RefractionChannels {
@ -22,15 +24,15 @@ impl RefractionChannels {
}
}
pub fn new_from_env() -> Self {
let log_channel_id = Self::get_channel_from_env("DISCORD_LOG_CHANNEL_ID");
pub fn from_env() -> Self {
let log_channel_id = Self::channel_from_env("DISCORD_LOG_CHANNEL_ID");
if let Some(channel_id) = log_channel_id {
info!("Log channel is {channel_id}");
} else {
warn!("DISCORD_LOG_CHANNEL_ID is empty; this will disable logging in your server.");
}
let welcome_channel_id = Self::get_channel_from_env("DISCORD_WELCOME_CHANNEL_ID");
let welcome_channel_id = Self::channel_from_env("DISCORD_WELCOME_CHANNEL_ID");
if let Some(channel_id) = welcome_channel_id {
info!("Welcome channel is {channel_id}");
} else {
@ -40,7 +42,7 @@ impl RefractionChannels {
Self::new(log_channel_id, welcome_channel_id)
}
fn get_channel_from_env(var: &str) -> Option<ChannelId> {
fn channel_from_env(var: &str) -> Option<ChannelId> {
std::env::var(var)
.ok()
.and_then(|env_var| ChannelId::from_str(&env_var).ok())
@ -48,13 +50,22 @@ impl RefractionChannels {
}
impl Config {
pub fn new(channels: RefractionChannels) -> Self {
Self { channels }
pub fn new(channels: RefractionChannels, days_to_delete_reaction: i64) -> Self {
Self {
channels,
days_to_delete_reaction,
}
}
pub fn from_env() -> Self {
let channels = RefractionChannels::new_from_env();
pub fn from_env() -> Result<Self> {
let channels = RefractionChannels::from_env();
let days_to_delete_reaction = std::env::var("DISCORD_DAYS_TO_DELETE_REACTION")
.wrap_err("DISCORD_DAYS_TO_DELETE_REACTION is empty! This variable is required.")?
.parse()
.wrap_err("DISCORD_DAYS_TO_DELETE_REACTION is not a number!")?;
Self::new(channels)
info!("Reactions will be deleted on messages older than {days_to_delete_reaction} days");
Ok(Self::new(channels, days_to_delete_reaction))
}
}

View file

@ -1,3 +1,5 @@
use eyre::Result;
mod bot;
mod discord;
@ -15,10 +17,10 @@ impl Config {
}
}
pub fn new_from_env() -> Self {
pub fn from_env() -> Result<Self> {
let bot = bot::Config::from_env();
let discord = discord::Config::from_env();
let discord = discord::Config::from_env()?;
Self::new(bot, discord)
Ok(Self::new(bot, discord))
}
}

View file

@ -0,0 +1,39 @@
use crate::Data;
use chrono::Duration;
use eyre::{Context as _, Result};
use log::{debug, trace};
use poise::serenity_prelude::{Context, Reaction, Timestamp};
pub async fn handle(ctx: &Context, reaction: &Reaction, data: &Data) -> Result<()> {
let reaction_type = reaction.emoji.clone();
let reactor = reaction.user_id;
let message = reaction.message(ctx).await.wrap_err_with(|| {
format!(
"Couldn't get message {} from reaction! We won't be able to check if it's old",
reaction.message_id
)
})?;
let time_sent = message.timestamp.to_utc();
let age = Timestamp::now().signed_duration_since(time_sent);
let max_days = Duration::days(data.config.discord.days_to_delete_reaction);
if age >= max_days {
// NOTE: if we for some reason **didn't** get the user_id associated with the reaction,
// this will clear **all** reactions of this type. this is intentional as older reactions
// being removed > harmful reactions being kept
debug!(
"Removing reaction {reaction_type} from message {}",
message.id
);
message.delete_reaction(ctx, reactor, reaction_type).await?;
} else {
trace!(
"Keeping reaction {reaction_type} for message {}",
message.id
);
}
Ok(())
}

View file

@ -5,6 +5,7 @@ use poise::serenity_prelude::{ActivityData, Context, FullEvent, OnlineStatus};
use poise::FrameworkContext;
mod analyze_logs;
mod block_reaction;
mod delete_on_reaction;
mod eta;
mod expand_link;
@ -71,6 +72,8 @@ pub async fn handle(
add_reaction.message_id.to_string(),
add_reaction.user_id.unwrap_or_default().to_string()
);
block_reaction::handle(ctx, add_reaction, data).await?;
delete_on_reaction::handle(ctx, add_reaction).await?;
}

View file

@ -37,7 +37,7 @@ async fn setup(
_: &serenity::Ready,
framework: &Framework<Data, Error>,
) -> Result<Data, Error> {
let config = Config::new_from_env();
let config = Config::from_env()?;
let storage = if let Some(url) = &config.bot.redis_url {
Some(Storage::from_url(url)?)