1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
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
}
}
|