fix: format IRC ACTION messages as * nick action * and strip CTCP delimiters

CTCP ACTION messages (/me) were relayed with raw \x01 bytes, rendering
as boxed-X characters in OwnCast. Detect the ACTION pattern, extract the
body, and format it like traditional IRC clients. Also strip \x01 in
irc_format as a safety net for other CTCP leakage.

Made-with: Cursor
This commit is contained in:
cottongin
2026-03-12 16:37:46 -04:00
parent b0236ee52b
commit e2fbd52009
7 changed files with 112 additions and 9 deletions

View File

@@ -1,8 +1,8 @@
/// Strip mIRC-style formatting control codes from a string.
///
/// Removes bold (\x02), color (\x03 + optional fg[,bg] digits), reset (\x0F),
/// monospace (\x11), reverse (\x16), italic (\x1D), strikethrough (\x1E),
/// and underline (\x1F).
/// Removes CTCP delimiter (\x01), bold (\x02), color (\x03 + optional fg[,bg]
/// digits), reset (\x0F), monospace (\x11), reverse (\x16), italic (\x1D),
/// strikethrough (\x1E), and underline (\x1F).
pub fn strip_formatting(input: &str) -> String {
let bytes = input.as_bytes();
let len = bytes.len();
@@ -11,7 +11,7 @@ pub fn strip_formatting(input: &str) -> String {
while i < len {
match bytes[i] {
b'\x02' | b'\x0F' | b'\x11' | b'\x16' | b'\x1D' | b'\x1E' | b'\x1F' => {
b'\x01' | b'\x02' | b'\x0F' | b'\x11' | b'\x16' | b'\x1D' | b'\x1E' | b'\x1F' => {
i += 1;
}
b'\x03' => {
@@ -156,4 +156,17 @@ mod tests {
fn preserves_cjk_and_accented_chars() {
assert_eq!(strip_formatting("\x02café\x02 日本語"), "café 日本語");
}
#[test]
fn strips_ctcp_delimiter() {
assert_eq!(strip_formatting("\x01ACTION sniffs\x01"), "ACTION sniffs");
}
#[test]
fn strips_ctcp_delimiter_mixed_with_formatting() {
assert_eq!(
strip_formatting("\x01\x02ACTION bold\x02\x01"),
"ACTION bold"
);
}
}