diff options
Diffstat (limited to 'src/system/plugin/edit.rs')
-rw-r--r-- | src/system/plugin/edit.rs | 123 |
1 files changed, 123 insertions, 0 deletions
diff --git a/src/system/plugin/edit.rs b/src/system/plugin/edit.rs new file mode 100644 index 0000000..bbd5801 --- /dev/null +++ b/src/system/plugin/edit.rs @@ -0,0 +1,123 @@ +use async_trait::async_trait; +use regex::RegexBuilder; +use twilight_model::channel::message::MessageReference; +use twilight_model::id::{marker::ChannelMarker, Id}; +use twilight_model::channel::Message; +use crate::system::{log::Logger, types::{Response, System}}; + +use super::{PluginCommand, SeancePlugin}; + +pub struct Edit; + +impl Edit { + pub fn new() -> Self { + Self + } +} + +#[async_trait] +impl<'system> SeancePlugin<'system> for Edit { + fn get_commands(&self) -> Vec<PluginCommand> { + vec![ + PluginCommand::Long("edit"), + PluginCommand::Short("s"), + ] + } + + async fn handle_command<'message>(&self, logger: &'system Logger, system: &'system System, message: &'message Message, command: PluginCommand, args: Vec<&'message str>) { + let most_recent_message = system.get_most_recent_message(message.channel_id).await; + + if let Some((edit_target, update_most_recent)) = match message.kind { + twilight_model::channel::message::MessageType::Regular => most_recent_message.map(|(message, _)| (message, true)), + twilight_model::channel::message::MessageType::Reply => async {Some(( + message.referenced_message.as_ref()?.as_ref().clone(), + message.referenced_message.as_ref()?.id == most_recent_message?.0.id + ))}.await, + _ => todo!(), + } { + if let Some(authoring_member) = system.get_member_by_id(edit_target.author.id).await { + if let Some(edit_contents) = match command { + PluginCommand::Long("edit") => Some(args.join(" ")), + PluginCommand::Short("s") => async { + let replacement_command = args.join(" "); + let separator = replacement_command.chars().nth(1).unwrap(); + let parts: Vec<&str> = replacement_command.split(separator).collect(); + + if parts.len() != 3 && parts.len() != 4 { + 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);}, + other => { + logger.log_err(Some(authoring_member.discord_token.clone()), format!("Unknown regex flag {other}")).await; + None? + }, + }}; + + let valid_regex = regex.build(); + let original_content = edit_target.content; + + // If the regex parses, replace with that + let result = if let Ok(regex) = valid_regex { + if global { + regex.replace_all(original_content.as_str(), *replacement).to_string() + } else { + regex.replace(original_content.as_str(), *replacement).to_string() + } + + // Else attempt replace as string + } else { + original_content.replace(pattern, replacement) + }; + Some(result) + }.await, + _ => unreachable!("Unknown command"), + } { + let result = {authoring_member.client.lock().await.update_message(edit_target.channel_id, edit_target.id) + .content(Some(edit_contents.as_str())) + .expect("Invalid edit contents") + .await + .expect("Could not edit") + .model() + .await + .expect("Could not parse response")}; + + if update_most_recent { + system.cache_most_recent_message(result.channel_id, result, authoring_member.clone()).await; + } + + let _ = {authoring_member.client.lock().await.delete_message(message.channel_id, message.id).await}; + } else { + logger.log_err(None, format!("Could not determine edit contents")).await; + } + } else { + logger.log_err(None, format!("Cannot edit message not sent by system member")).await; + } + + } else { + logger.log_err(None, format!("Cannot find edit target")).await; + } + } + + async fn handle_message<'message>(&self, _logger: &'system Logger, _system: &'system System, _message: &'message Message, _response: &'message mut Response) { + // noop + } + + async fn post_response<'message>(&self, _logger: &'system Logger, _system: &'system System, _message: &'message Message, _channel: Id<ChannelMarker>, _response: &'message Response) { + // noop + } +} |