diff options
author | Ashelyn Rose <git@ashen.earth> | 2024-10-06 15:25:01 -0600 |
---|---|---|
committer | Ashelyn Rose <git@ashen.earth> | 2024-10-06 15:25:01 -0600 |
commit | ec104a719f46d6812661c29355e7a9fea8418b49 (patch) | |
tree | 378eadd6183f5c9af997e52f89bdfa59570b0f7a /src/system | |
parent | 9e15bb9103ba054fa88501cbff2d5e121ffa8544 (diff) |
Actually carries out !edit and !s commands
Diffstat (limited to 'src/system')
-rw-r--r-- | src/system/bot/client.rs | 7 | ||||
-rw-r--r-- | src/system/bot/mod.rs | 4 | ||||
-rw-r--r-- | src/system/message_parser.rs | 83 | ||||
-rw-r--r-- | src/system/mod.rs | 16 |
4 files changed, 91 insertions, 19 deletions
diff --git a/src/system/bot/client.rs b/src/system/bot/client.rs index 61d7515..4d4f7bb 100644 --- a/src/system/bot/client.rs +++ b/src/system/bot/client.rs @@ -90,6 +90,13 @@ impl Client { return Ok(()) } + pub async fn edit_message(&self, channel_id: ChannelId, message_id: MessageId, new_content: String) -> Result<FullMessage, TwiError> { + Ok(self.client.lock().await.update_message(channel_id, message_id) + .content(Some(new_content.as_str())).expect("Invalid message contents") + .await.expect("Could not update message") + .model().await.unwrap()) + } + pub async fn duplicate_message(&self, message: &TwiMessage, content: &str) -> Result<TwiMessage, MessageDuplicateError> { let client = self.client.lock().await; diff --git a/src/system/bot/mod.rs b/src/system/bot/mod.rs index 2f38075..f0a2e45 100644 --- a/src/system/bot/mod.rs +++ b/src/system/bot/mod.rs @@ -74,6 +74,10 @@ impl Bot { self.client.resend_message(message_id, channel_id).await; } + pub async fn edit_message(&self, channel_id: ChannelId, message_id: MessageId, new_content: String) -> Result<FullMessage, TwiError> { + self.client.edit_message(channel_id, message_id, new_content).await + } + pub async fn delete_message(&self, channel_id: ChannelId, message_id: MessageId) -> Result<(), TwiError> { self.client.delete_message(channel_id, message_id).await } diff --git a/src/system/message_parser.rs b/src/system/message_parser.rs index 31747a8..d161483 100644 --- a/src/system/message_parser.rs +++ b/src/system/message_parser.rs @@ -1,11 +1,11 @@ use std::sync::LazyLock; -use regex::Regex; +use regex::{Regex, RegexBuilder}; use crate::config::System; use twilight_mention::ParseMention; use twilight_model::id::{marker::UserMarker, Id}; -use super::{FullMessage, MemberId, MessageId, Timestamp}; +use super::{FullMessage, MemberId, MessageId, Timestamp, UserId}; pub enum ParsedMessage { Command(Command), @@ -23,12 +23,13 @@ pub enum ParsedMessage { } pub enum Command { - Edit(MessageId, String), + Edit(MemberId, MessageId, String), Reproxy(MemberId, MessageId), Nick(MemberId, String), ReloadSystemConfig, ExitSéance, UnknownCommand, + InvalidCommand } pub struct MessageParser {} @@ -81,7 +82,10 @@ impl MessageParser { match first_word { Some(command_name) => match command_name { - "edit" => return Command::Edit(secondary_message.unwrap().id, words.remainder().unwrap().to_string()), + "edit" => { + let editing_member = Self::get_member_id_from_user_id(secondary_message.as_ref().unwrap().author.id, system_config).unwrap(); + return Command::Edit(editing_member, secondary_message.unwrap().id, words.remainder().unwrap().to_string()) + }, "nick" => { if let Some(member) = MessageParser::match_member(words.next(), system_config) { return Command::Nick(member, words.remainder().unwrap().to_string()); @@ -97,24 +101,48 @@ impl MessageParser { None => return Command::UnknownCommand, } - - // If unable to parse - Command::UnknownCommand - } + // Attempt matching !s + if message.content.chars().nth(1).unwrap() == 's' { + let separator = message.content.chars().nth(2).unwrap(); + let parts: Vec<&str> = message.content.split(separator).collect(); - fn match_member(maybe_mention: Option<&str>, system_config: &System) -> Option<MemberId> { - if let Some(maybe_mention) = maybe_mention { - if let Ok(mention) = Id::<UserMarker>::parse(maybe_mention) { - system_config.members.iter().enumerate() - .filter(|(_id, m)| m.user_id.is_some()) - .find(|(_id, m)| m.user_id.unwrap() == mention) - .map(|(id, _m)| id) - } else { - None + if parts.len() != 3 && parts.len() != 4 { + return Command::InvalidCommand } - } else { - None + + let pattern = parts.get(1).unwrap(); + let replacement = parts.get(2).unwrap(); + let flags = parts.get(3).unwrap_or(&""); + + let mut global = false; + let mut regex = RegexBuilder::new(pattern); + + for flag in flags.chars() {match flag { + 'i' => {regex.case_insensitive(true);}, + 'm' => {regex.multi_line(true);}, + 'g' => {global = true;}, + 'x' => {regex.ignore_whitespace(true);}, + 'R' => {regex.crlf(true);}, + 's' => {regex.dot_matches_new_line(true);}, + 'U' => {regex.swap_greed(true);}, + _ => {return Command::InvalidCommand;}, + }}; + + let regex = regex.build().unwrap(); + + let original_content = &secondary_message.as_ref().unwrap().content; + let new_content = if global { + regex.replace_all(original_content.as_str(), *replacement) + } else { + regex.replace(original_content.as_str(), *replacement) + }; + + let editing_member = Self::get_member_id_from_user_id(secondary_message.as_ref().unwrap().author.id, system_config).unwrap(); + return Command::Edit(editing_member, secondary_message.as_ref().unwrap().id, new_content.to_string()); } + + // If unable to parse + Command::UnknownCommand } fn check_correction(message: &FullMessage, secondary_message: Option<FullMessage>) -> Option<ParsedMessage> { @@ -148,6 +176,23 @@ impl MessageParser { None } } + + fn match_member(maybe_mention: Option<&str>, system_config: &System) -> Option<MemberId> { + if let Some(maybe_mention) = maybe_mention { + if let Ok(mention) = Id::<UserMarker>::parse(maybe_mention) { + return MessageParser::get_member_id_from_user_id(mention, system_config) + } + } + + None + } + + fn get_member_id_from_user_id(user_id: UserId, system_config: &System) -> Option<MemberId> { + system_config.members.iter().enumerate() + .filter(|(_id, m)| m.user_id.is_some()) + .find(|(_id, m)| m.user_id.unwrap() == user_id) + .map(|(id, _m)| id) + } } impl crate::config::Member { diff --git a/src/system/mod.rs b/src/system/mod.rs index 6c4d95f..b5cd1ab 100644 --- a/src/system/mod.rs +++ b/src/system/mod.rs @@ -206,6 +206,22 @@ impl Manager { } }, + message_parser::ParsedMessage::Command(Command::Edit(member_id, message_id, new_content)) => { + let bot = self.bots.get(&member_id).unwrap(); + + if let Ok(new_message) = bot.edit_message(message.channel_id, message_id, new_content).await { + + // If we just edited the most recently sent message in this channel, update + // cache for future edit commands + if self.send_cache.get(&new_message.channel_id).map_or(MessageId::new(1u64), |m| m.id) == message_id { + self.send_cache.put(new_message.channel_id, new_message); + } + + // Delete the command message + let _ = bot.delete_message(message.channel_id, message.id).await; + } + } + message_parser::ParsedMessage::Command(Command::UnknownCommand) => { let member_id = if let Some((member_id, _)) = self.latch_state { member_id |