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
124
125
126
|
use std::sync::LazyLock;
use regex::Regex;
use crate::config::{self, System};
use super::{FullMessage, MemberId, MessageId, Timestamp};
pub enum ParsedMessage {
Command(Command),
ProxiedMessage {
member_id: MemberId,
message_content: String,
latch: bool,
},
UnproxiedMessage,
LatchClear(MemberId),
// TODO: Figure out how to represent emotes
EmoteAdd(MemberId, MessageId, ()),
EmoteRemove(MemberId, MessageId, ()),
}
pub enum Command {
Edit(MessageId, String),
Reproxy(MessageId, MemberId),
Nick(MemberId, String),
ReloadSystemConfig,
ExitSéance,
UnknownCommand,
}
pub struct MessageParser {}
static CORRECTION_REGEX: LazyLock<Regex> = LazyLock::new(|| {
Regex::new(r"^\*\B+$").unwrap()
});
impl MessageParser {
pub fn parse(message: &FullMessage, secondary_message: Option<&FullMessage>, system_config: &System, latch_state: Option<(MemberId, Timestamp)>) -> ParsedMessage {
if message.content == r"\\" {
return ParsedMessage::LatchClear(if let Some((member_id, _)) = latch_state {
member_id
} else {
0
})
}
if message.content.starts_with(r"\") {
return ParsedMessage::UnproxiedMessage
}
if message.content.starts_with(r"!") {
return ParsedMessage::Command(
MessageParser::parse_command(message, secondary_message, system_config, latch_state)
);
}
if CORRECTION_REGEX.is_match(message.content.as_str()) {
if let Some(parse) = MessageParser::check_correction(message, secondary_message) {
return parse
}
}
if let Some(parse) = MessageParser::check_member_patterns(message, system_config) {
return parse
}
if let Some(parse) = MessageParser::check_autoproxy(message, latch_state) {
return parse
}
// If nothing else
ParsedMessage::UnproxiedMessage
}
fn parse_command(message: &FullMessage, secondary_message: Option<&FullMessage>, system_config: &System, latch_state: Option<(MemberId, Timestamp)>) -> Command {
// If unable to parse
Command::UnknownCommand
}
fn check_correction(message: &FullMessage, secondary_message: Option<&FullMessage>) -> Option<ParsedMessage> {
None
}
fn check_member_patterns(message: &FullMessage, system_config: &System) -> Option<ParsedMessage> {
let matches_prefix = system_config.members.iter().enumerate().find_map(|(member_id, member)|
Some((member_id, member.matches_proxy_prefix(&message)?))
);
if let Some((member_id, matched_content)) = matches_prefix {
Some(ParsedMessage::ProxiedMessage {
member_id,
message_content: matched_content.to_string(),
latch: true,
})
} else {
None
}
}
fn check_autoproxy(message: &FullMessage, latch_state: Option<(MemberId, Timestamp)>) -> Option<ParsedMessage> {
if let Some((member_id, _)) = latch_state {
Some(ParsedMessage::ProxiedMessage {
member_id,
message_content: message.content.clone(),
latch: true,
})
} else {
None
}
}
}
impl crate::config::Member {
pub fn matches_proxy_prefix<'a>(&self, message: &'a FullMessage) -> Option<&'a str> {
match self.message_pattern.captures(message.content.as_str()) {
None => None,
Some(captures) => match captures.name("content") {
None => None,
Some(matched_content) => Some(matched_content.as_str()),
},
}
}
}
|