diff --git a/src/discord_bot/guild_storage.rs b/src/discord_bot/guild_storage.rs index 7461012..a866001 100644 --- a/src/discord_bot/guild_storage.rs +++ b/src/discord_bot/guild_storage.rs @@ -1,4 +1,5 @@ use crate::discord_bot::chess::ChessState; +use crate::discord_bot::octal_counter::OctalCounterState; use crate::discord_bot::permanent_latest::PermanentLatestInfo; use crate::discord_bot::role::RoleData; use crate::discord_bot::roletoggle::RoleToggleInfo; @@ -44,6 +45,8 @@ pub struct GuildStorage { pub users_sent_to_support: HashSet, #[serde(default)] pub counters: HashMap, + #[serde(default)] + pub octal_counter_state: OctalCounterState, } impl Default for GuildStorage { @@ -61,6 +64,7 @@ impl Default for GuildStorage { send_to_support_leaderboard: HashMap::new(), users_sent_to_support: HashSet::new(), counters: HashMap::new(), + octal_counter_state: OctalCounterState::default(), } } } diff --git a/src/discord_bot/mod.rs b/src/discord_bot/mod.rs index e66b665..59e5d73 100644 --- a/src/discord_bot/mod.rs +++ b/src/discord_bot/mod.rs @@ -4,6 +4,7 @@ mod commands; mod counter; mod guild_storage; mod mood; +mod octal_counter; mod permanent_latest; mod reaction_role_toggle; mod role; @@ -167,12 +168,20 @@ impl EventHandler for Handler { enum MessageHandling<'a> { Command(&'a str), IncCounter(&'a str), + OctalCounter, PermanentLatest, SimpleWords, } let message_handling = { - if config::get().simple_words_channel == Some(new_message.channel_id) { + if GuildStorage::get(guild_id) + .await + .octal_counter_state + .octal_counter_channel + == Some(new_message.channel_id) + { + MessageHandling::OctalCounter + } else if config::get().simple_words_channel == Some(new_message.channel_id) { MessageHandling::SimpleWords } else if new_message.author.bot { return; @@ -208,6 +217,18 @@ impl EventHandler for Handler { MessageHandling::IncCounter(counter) => { counter::inc_counter(counter, guild_id, ctx, &new_message).await } + MessageHandling::OctalCounter => { + octal_counter::on_message( + guild_id, + ctx, + !new_message.attachments.is_empty(), + &new_message.content, + &new_message.author, + new_message.channel_id, + new_message.id, + ) + .await + } MessageHandling::PermanentLatest => { permanent_latest::on_message(guild_id, ctx, &new_message).await } @@ -238,32 +259,49 @@ impl EventHandler for Handler { _new: Option, event: MessageUpdateEvent, ) { - if config::get().simple_words_channel != Some(event.channel_id) { - return; + if config::get().simple_words_channel == Some(event.channel_id) { + let Some(content) = event.content else { return; }; + let Some(author) = event.author else { return; }; + tokio::runtime::Handle::current().spawn(async move { + if let Err(err) = simple_words::on_message( + ctx, + event + .attachments + .as_ref() + .map(|attachments| attachments.is_empty()) + == Some(false), + &content, + &author, + event.channel_id, + event.id, + ) + .await + { + warn!( + "Error processing message edit from \"{}\" (ID {}): {}", + author.name, author.id, err + ); + } + }); + } else if GuildStorage::get(match event.guild_id { + Some(i) => i, + None => return, + }) + .await + .octal_counter_state + .octal_counter_channel + == Some(event.channel_id) + { + let Some(author) = event.author else { return; }; + tokio::runtime::Handle::current().spawn(async move { + if let Err(err) = event.channel_id.delete_message(&ctx, event.id).await { + warn!( + "Error processing message edit from \"{}\" (ID {}): {}", + author.name, author.id, err + ); + } + }); } - let Some(content) = event.content else { return; }; - let Some(author) = event.author else { return; }; - tokio::runtime::Handle::current().spawn(async move { - if let Err(err) = simple_words::on_message( - ctx, - event - .attachments - .as_ref() - .map(|attachments| attachments.is_empty()) - == Some(false), - &content, - &author, - event.channel_id, - event.id, - ) - .await - { - warn!( - "Error processing message edit from \"{}\" (ID {}): {}", - author.name, author.id, err - ); - } - }); } async fn reaction_add(&self, ctx: Context, reaction: Reaction) { diff --git a/src/discord_bot/octal_counter.rs b/src/discord_bot/octal_counter.rs new file mode 100644 index 0000000..101b165 --- /dev/null +++ b/src/discord_bot/octal_counter.rs @@ -0,0 +1,49 @@ +use crate::discord_bot::guild_storage::GuildStorage; +use serde::{Deserialize, Serialize}; +use serenity::client::Context; +use serenity::model::id::{ChannelId, GuildId, MessageId, UserId}; +use serenity::model::user::User; + +pub(crate) async fn on_message( + guild_id: GuildId, + ctx: Context, + has_attachments: bool, + content: &str, + author: &User, + channel_id: ChannelId, + message_id: MessageId, +) -> Result<(), crate::Error> { + if has_attachments { + channel_id.delete_message(&ctx, message_id).await?; + return Ok(()); + } + + let Ok(next_counter) = i32::from_str_radix(content, 8) else { + channel_id.delete_message(&ctx, message_id).await?; + return Ok(()); + }; + + let mut storage = GuildStorage::get_mut(guild_id).await; + if storage.octal_counter_state.octal_counter_latest_user == Some(author.id) { + storage.discard(); + channel_id.delete_message(&ctx, message_id).await?; + return Ok(()); + } + if next_counter != storage.octal_counter_state.octal_counter + 1 { + storage.discard(); + channel_id.delete_message(&ctx, message_id).await?; + return Ok(()); + } + + storage.octal_counter_state.octal_counter = next_counter; + storage.octal_counter_state.octal_counter_latest_user = Some(author.id); + storage.save().await; + Ok(()) +} + +#[derive(Debug, Default, Deserialize, Serialize)] +pub struct OctalCounterState { + pub octal_counter_channel: Option, + pub octal_counter: i32, + pub octal_counter_latest_user: Option, +}