fix: strip emoji between bot mention and command text

strip_mention_separator now skips all non-ASCII-alphanumeric chars
(emoji, colons, spaces) and returns a slice starting at the first
command character. Fixes mention pills with emoji display names
(e.g. "timmy ️ status") not matching bot commands.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
dave
2026-04-02 18:06:52 +00:00
parent 7ff88641c0
commit d37fdf8e10
+20 -8
View File
@@ -72,16 +72,19 @@ pub fn strip_bot_mention<'a>(message: &'a str, bot_name: &str, bot_user_id: &str
trimmed trimmed
} }
/// Strip an optional Element tab-completion separator (`:` or `,`) and /// Strip decoration between a bot mention and the command text.
/// surrounding whitespace from the start of text that follows a bot mention.
/// ///
/// Element's tab-completion inserts `DisplayName: ` (colon + space) after the /// After the bot name/ID is stripped, what remains may include whitespace,
/// name. Without this strip the leading `:` would be treated as part of the /// emoji from display names (e.g. `Timmy ⚡️`), and Element tab-completion
/// command name and no command would match. /// separators (`:` or `,`). This function skips all of that and returns a
/// slice starting at the first ASCII alphanumeric character (the command).
fn strip_mention_separator(rest: &str) -> &str { fn strip_mention_separator(rest: &str) -> &str {
let rest = rest.trim_start(); let byte_skip = rest
let rest = rest.strip_prefix([',', ':']).unwrap_or(rest); .char_indices()
rest.trim_start() .find(|(_, c)| c.is_ascii_alphanumeric())
.map(|(i, _)| i)
.unwrap_or(rest.len());
&rest[byte_skip..]
} }
/// Returns `true` when `text` ends while inside an open fenced code block. /// Returns `true` when `text` ends while inside an open fenced code block.
@@ -381,6 +384,15 @@ mod tests {
assert_eq!(rest, "help"); assert_eq!(rest, "help");
} }
#[test]
fn strip_mention_short_name_emoji_suffix_in_body() {
// bot_name is "Timmy" (no emoji) but Element mention pill puts
// "Timmy ⚡️ status" in the body — the emoji is part of the display
// name as set on the Matrix server, not in bot.toml.
let rest = strip_bot_mention("Timmy ⚡️ status", "Timmy", "@timmy:homeserver.local");
assert_eq!(rest, "status");
}
// -- drain_complete_paragraphs ------------------------------------------ // -- drain_complete_paragraphs ------------------------------------------
#[test] #[test]