mirror of
https://github.com/stoatchat/stoatchat.git
synced 2026-07-14 13:36:59 +00:00
feat: parse message push notification content and replace internal formatting (#693)
* parse message push notification content and replace internal formatting Signed-off-by: IAmTomahawkx <iamtomahawkx@gmail.com> * fix: don't unwrap the error I was using for db debugging Signed-off-by: IAmTomahawkx <iamtomahawkx@gmail.com> * fix: emojis & remove compiler warning Signed-off-by: IAmTomahawkx <iamtomahawkx@gmail.com> * fix: emojis in pushd Signed-off-by: IAmTomahawkx <iamtomahawkx@gmail.com> * feat: report errors in the render function to sentry Signed-off-by: IAmTomahawkx <iamtomahawkx@gmail.com> --------- Signed-off-by: IAmTomahawkx <iamtomahawkx@gmail.com>
This commit is contained in:
@@ -16,23 +16,29 @@ pub enum MessageToken<'a> {
|
||||
UserMention(&'a str),
|
||||
#[regex("<%(?&id)>", |lex| &lex.slice()[2..lex.slice().len() - 1],)]
|
||||
RoleMention(&'a str),
|
||||
#[regex("<#(?&id)>", |lex| &lex.slice()[2..lex.slice().len() - 1],)]
|
||||
ChannelMention(&'a str),
|
||||
#[regex(":(?&id):", |lex| &lex.slice()[1..lex.slice().len() - 1],)]
|
||||
Emoji(&'a str),
|
||||
#[token("@everyone")]
|
||||
MentionEveryone,
|
||||
#[token("@online")]
|
||||
MentionOnline
|
||||
MentionOnline,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Default)]
|
||||
pub struct MessageResults {
|
||||
pub user_mentions: HashSet<String>,
|
||||
pub role_mentions: HashSet<String>,
|
||||
pub channel_mentions: HashSet<String>,
|
||||
pub emojis: HashSet<String>,
|
||||
pub mentions_everyone: bool,
|
||||
pub mentions_online: bool
|
||||
pub mentions_online: bool,
|
||||
}
|
||||
|
||||
struct MessageParserIterator<'a, I> {
|
||||
inner: I,
|
||||
temp: VecDeque<MessageToken<'a>>
|
||||
temp: VecDeque<MessageToken<'a>>,
|
||||
}
|
||||
|
||||
impl<'a, I: Iterator<Item = MessageToken<'a>>> Iterator for MessageParserIterator<'a, I> {
|
||||
@@ -55,11 +61,11 @@ impl<'a, I: Iterator<Item = MessageToken<'a>>> Iterator for MessageParserIterato
|
||||
if next_token == Some(MessageToken::CodeblockMarker(ty)) {
|
||||
self.temp.clear();
|
||||
self.temp.push_back(MessageToken::CodeblockMarker(ty));
|
||||
break next_token
|
||||
break next_token;
|
||||
} else if let Some(token) = next_token {
|
||||
self.temp.push_back(token);
|
||||
} else {
|
||||
break Some(MessageToken::CodeblockMarker(ty))
|
||||
break Some(MessageToken::CodeblockMarker(ty));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -69,10 +75,10 @@ impl<'a, I: Iterator<Item = MessageToken<'a>>> Iterator for MessageParserIterato
|
||||
}
|
||||
}
|
||||
|
||||
pub fn parse_message_iter(text: &str) -> impl Iterator<Item = MessageToken> + '_ {
|
||||
pub fn parse_message_iter(text: &str) -> impl Iterator<Item = MessageToken<'_>> + '_ {
|
||||
MessageParserIterator {
|
||||
inner: MessageToken::lexer(text).flatten(),
|
||||
temp: VecDeque::new()
|
||||
temp: VecDeque::new(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -82,13 +88,23 @@ pub fn parse_message(text: &str) -> MessageResults {
|
||||
for token in parse_message_iter(text) {
|
||||
match token {
|
||||
MessageToken::Escape => {}
|
||||
MessageToken::CodeblockMarker(_) => {},
|
||||
MessageToken::UserMention(id) => { results.user_mentions.insert(id.to_string()); },
|
||||
MessageToken::RoleMention(id) => { results.role_mentions.insert(id.to_string()); },
|
||||
MessageToken::CodeblockMarker(_) => {}
|
||||
MessageToken::UserMention(id) => {
|
||||
results.user_mentions.insert(id.to_string());
|
||||
}
|
||||
MessageToken::RoleMention(id) => {
|
||||
results.role_mentions.insert(id.to_string());
|
||||
}
|
||||
MessageToken::ChannelMention(id) => {
|
||||
results.channel_mentions.insert(id.to_string());
|
||||
}
|
||||
MessageToken::Emoji(id) => {
|
||||
results.emojis.insert(id.to_string());
|
||||
}
|
||||
MessageToken::MentionEveryone => results.mentions_everyone = true,
|
||||
MessageToken::MentionOnline => results.mentions_online = true,
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
results
|
||||
}
|
||||
@@ -109,7 +125,10 @@ mod tests {
|
||||
let output = parse_message_iter("Hello <@01FD58YK5W7QRV5H3D64KTQYX3>.").collect::<Vec<_>>();
|
||||
|
||||
assert_eq!(output.len(), 1);
|
||||
assert_eq!(output[0], MessageToken::UserMention("01FD58YK5W7QRV5H3D64KTQYX3"));
|
||||
assert_eq!(
|
||||
output[0],
|
||||
MessageToken::UserMention("01FD58YK5W7QRV5H3D64KTQYX3")
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -117,7 +136,10 @@ mod tests {
|
||||
let output = parse_message_iter("Hello <%01FD58YK5W7QRV5H3D64KTQYX3>.").collect::<Vec<_>>();
|
||||
|
||||
assert_eq!(output.len(), 1);
|
||||
assert_eq!(output[0], MessageToken::RoleMention("01FD58YK5W7QRV5H3D64KTQYX3"));
|
||||
assert_eq!(
|
||||
output[0],
|
||||
MessageToken::RoleMention("01FD58YK5W7QRV5H3D64KTQYX3")
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -138,29 +160,57 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_everything() {
|
||||
let output = parse_message_iter("Hello <@01FD58YK5W7QRV5H3D64KTQYX3>, <%01FD58YK5W7QRV5H3D64KTQYX3>, @everyone and @online.").collect::<Vec<_>>();
|
||||
let output = parse_message_iter("Hello <@01FD58YK5W7QRV5H3D64KTQYX3>, <%01FD58YK5W7QRV5H3D64KTQYX3>, <#01FD58YK5W7QRV5H3D64KTQYX3> @everyone and @online. :01FD58YK5W7QRV5H3D64KTQYX3:").collect::<Vec<_>>();
|
||||
|
||||
assert_eq!(output.len(), 4);
|
||||
assert_eq!(output[0], MessageToken::UserMention("01FD58YK5W7QRV5H3D64KTQYX3"));
|
||||
assert_eq!(output[1], MessageToken::RoleMention("01FD58YK5W7QRV5H3D64KTQYX3"));
|
||||
assert_eq!(output[2], MessageToken::MentionEveryone);
|
||||
assert_eq!(output[3], MessageToken::MentionOnline);
|
||||
assert_eq!(output.len(), 6);
|
||||
assert_eq!(
|
||||
output[0],
|
||||
MessageToken::UserMention("01FD58YK5W7QRV5H3D64KTQYX3")
|
||||
);
|
||||
assert_eq!(
|
||||
output[1],
|
||||
MessageToken::RoleMention("01FD58YK5W7QRV5H3D64KTQYX3")
|
||||
);
|
||||
assert_eq!(
|
||||
output[2],
|
||||
MessageToken::ChannelMention("01FD58YK5W7QRV5H3D64KTQYX3")
|
||||
);
|
||||
assert_eq!(output[3], MessageToken::MentionEveryone);
|
||||
assert_eq!(output[4], MessageToken::MentionOnline);
|
||||
assert_eq!(output[5], MessageToken::Emoji("01FD58YK5W7QRV5H3D64KTQYX3"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_everything_no_spaces() {
|
||||
let output = parse_message_iter("<@01FD58YK5W7QRV5H3D64KTQYX3><%01FD58YK5W7QRV5H3D64KTQYX3>@everyone@online").collect::<Vec<_>>();
|
||||
let output = parse_message_iter(
|
||||
"<@01FD58YK5W7QRV5H3D64KTQYX3><%01FD58YK5W7QRV5H3D64KTQYX3><#01FD58YK5W7QRV5H3D64KTQYX3>@everyone@online:01FD58YK5W7QRV5H3D64KTQYX3:",
|
||||
)
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
assert_eq!(output.len(), 4);
|
||||
assert_eq!(output[0], MessageToken::UserMention("01FD58YK5W7QRV5H3D64KTQYX3"));
|
||||
assert_eq!(output[1], MessageToken::RoleMention("01FD58YK5W7QRV5H3D64KTQYX3"));
|
||||
assert_eq!(output[2], MessageToken::MentionEveryone);
|
||||
assert_eq!(output[3], MessageToken::MentionOnline);
|
||||
assert_eq!(output.len(), 6);
|
||||
assert_eq!(
|
||||
output[0],
|
||||
MessageToken::UserMention("01FD58YK5W7QRV5H3D64KTQYX3")
|
||||
);
|
||||
assert_eq!(
|
||||
output[1],
|
||||
MessageToken::RoleMention("01FD58YK5W7QRV5H3D64KTQYX3")
|
||||
);
|
||||
assert_eq!(
|
||||
output[2],
|
||||
MessageToken::ChannelMention("01FD58YK5W7QRV5H3D64KTQYX3")
|
||||
);
|
||||
assert_eq!(output[3], MessageToken::MentionEveryone);
|
||||
assert_eq!(output[4], MessageToken::MentionOnline);
|
||||
assert_eq!(output[5], MessageToken::Emoji("01FD58YK5W7QRV5H3D64KTQYX3"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_codeblock_no_mentions() {
|
||||
let output = parse_message_iter("```\n<@01FD58YK5W7QRV5H3D64KTQYX3><%01FD58YK5W7QRV5H3D64KTQYX3>@everyone@online\n```").collect::<Vec<_>>();
|
||||
let output = parse_message_iter(
|
||||
"```\n<@01FD58YK5W7QRV5H3D64KTQYX3><%01FD58YK5W7QRV5H3D64KTQYX3><#01FD58YK5W7QRV5H3D64KTQYX3>@everyone@online:01FD58YK5W7QRV5H3D64KTQYX3:\n```",
|
||||
)
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
assert_eq!(output.len(), 2);
|
||||
assert_eq!(output[0], MessageToken::CodeblockMarker(3));
|
||||
@@ -169,19 +219,36 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_uncontained_codeblock_should_mention() {
|
||||
let output = parse_message_iter("```\n<@01FD58YK5W7QRV5H3D64KTQYX3><%01FD58YK5W7QRV5H3D64KTQYX3>@everyone@online").collect::<Vec<_>>();
|
||||
let output = parse_message_iter(
|
||||
"```\n<@01FD58YK5W7QRV5H3D64KTQYX3><%01FD58YK5W7QRV5H3D64KTQYX3><#01FD58YK5W7QRV5H3D64KTQYX3>@everyone@online:01FD58YK5W7QRV5H3D64KTQYX3:",
|
||||
)
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
assert_eq!(output.len(), 5);
|
||||
assert_eq!(output.len(), 7);
|
||||
assert_eq!(output[0], MessageToken::CodeblockMarker(3));
|
||||
assert_eq!(output[1], MessageToken::UserMention("01FD58YK5W7QRV5H3D64KTQYX3"));
|
||||
assert_eq!(output[2], MessageToken::RoleMention("01FD58YK5W7QRV5H3D64KTQYX3"));
|
||||
assert_eq!(output[3], MessageToken::MentionEveryone);
|
||||
assert_eq!(output[4], MessageToken::MentionOnline);
|
||||
assert_eq!(
|
||||
output[1],
|
||||
MessageToken::UserMention("01FD58YK5W7QRV5H3D64KTQYX3")
|
||||
);
|
||||
assert_eq!(
|
||||
output[2],
|
||||
MessageToken::RoleMention("01FD58YK5W7QRV5H3D64KTQYX3")
|
||||
);
|
||||
assert_eq!(
|
||||
output[3],
|
||||
MessageToken::ChannelMention("01FD58YK5W7QRV5H3D64KTQYX3")
|
||||
);
|
||||
assert_eq!(output[4], MessageToken::MentionEveryone);
|
||||
assert_eq!(output[5], MessageToken::MentionOnline);
|
||||
assert_eq!(output[6], MessageToken::Emoji("01FD58YK5W7QRV5H3D64KTQYX3"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_inline_codeblock_no_mentions() {
|
||||
let output = parse_message_iter("`<@01FD58YK5W7QRV5H3D64KTQYX3><%01FD58YK5W7QRV5H3D64KTQYX3>@everyone@online`").collect::<Vec<_>>();
|
||||
let output = parse_message_iter(
|
||||
"`<@01FD58YK5W7QRV5H3D64KTQYX3><%01FD58YK5W7QRV5H3D64KTQYX3><#01FD58YK5W7QRV5H3D64KTQYX3>@everyone@online:01FD58YK5W7QRV5H3D64KTQYX3:`",
|
||||
)
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
assert_eq!(output.len(), 2);
|
||||
assert_eq!(output[0], MessageToken::CodeblockMarker(1));
|
||||
@@ -190,19 +257,33 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_uncontained_inline_codeblock_should_mention() {
|
||||
let output = parse_message_iter("`<@01FD58YK5W7QRV5H3D64KTQYX3><%01FD58YK5W7QRV5H3D64KTQYX3>@everyone@online").collect::<Vec<_>>();
|
||||
let output = parse_message_iter(
|
||||
"`<@01FD58YK5W7QRV5H3D64KTQYX3><%01FD58YK5W7QRV5H3D64KTQYX3><#01FD58YK5W7QRV5H3D64KTQYX3>@everyone@online:01FD58YK5W7QRV5H3D64KTQYX3:",
|
||||
)
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
assert_eq!(output.len(), 5);
|
||||
assert_eq!(output.len(), 6);
|
||||
assert_eq!(output[0], MessageToken::CodeblockMarker(1));
|
||||
assert_eq!(output[1], MessageToken::UserMention("01FD58YK5W7QRV5H3D64KTQYX3"));
|
||||
assert_eq!(output[2], MessageToken::RoleMention("01FD58YK5W7QRV5H3D64KTQYX3"));
|
||||
assert_eq!(output[3], MessageToken::MentionEveryone);
|
||||
assert_eq!(output[4], MessageToken::MentionOnline);
|
||||
assert_eq!(
|
||||
output[1],
|
||||
MessageToken::UserMention("01FD58YK5W7QRV5H3D64KTQYX3")
|
||||
);
|
||||
assert_eq!(
|
||||
output[2],
|
||||
MessageToken::RoleMention("01FD58YK5W7QRV5H3D64KTQYX3")
|
||||
);
|
||||
assert_eq!(
|
||||
output[3],
|
||||
MessageToken::ChannelMention("01FD58YK5W7QRV5H3D64KTQYX3")
|
||||
);
|
||||
assert_eq!(output[4], MessageToken::MentionEveryone);
|
||||
assert_eq!(output[5], MessageToken::MentionOnline);
|
||||
assert_eq!(output[6], MessageToken::Emoji("01FD58YK5W7QRV5H3D64KTQYX3"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_codeblock_with_language_no_mentions() {
|
||||
let output = parse_message_iter("```rust\n<@01FD58YK5W7QRV5H3D64KTQYX3><%01FD58YK5W7QRV5H3D64KTQYX3>@everyone@online```").collect::<Vec<_>>();
|
||||
let output = parse_message_iter("```rust\n<@01FD58YK5W7QRV5H3D64KTQYX3><%01FD58YK5W7QRV5H3D64KTQYX3><#01FD58YK5W7QRV5H3D64KTQYX3>@everyone@online:01FD58YK5W7QRV5H3D64KTQYX3:```").collect::<Vec<_>>();
|
||||
|
||||
assert_eq!(output.len(), 2);
|
||||
assert_eq!(output[0], MessageToken::CodeblockMarker(3));
|
||||
@@ -220,7 +301,8 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_double_inline_codeblock_with_backticks_inside() {
|
||||
let output = parse_message_iter("``this `should` not `ping` @everyone``").collect::<Vec<_>>();
|
||||
let output =
|
||||
parse_message_iter("``this `should` not `ping` @everyone``").collect::<Vec<_>>();
|
||||
|
||||
assert_eq!(output.len(), 2);
|
||||
assert_eq!(output[0], MessageToken::CodeblockMarker(2));
|
||||
@@ -238,7 +320,8 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_escaped_codeblock() {
|
||||
let output = parse_message_iter("i am ~~not~~ pinging \\`@everyone` ok.").collect::<Vec<_>>();
|
||||
let output =
|
||||
parse_message_iter("i am ~~not~~ pinging \\`@everyone` ok.").collect::<Vec<_>>();
|
||||
|
||||
assert_eq!(output.len(), 3);
|
||||
assert_eq!(output[0], MessageToken::Escape);
|
||||
@@ -253,4 +336,4 @@ mod tests {
|
||||
assert_eq!(output.len(), 1);
|
||||
assert_eq!(output[0], MessageToken::Escape);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user