diff --git a/nanobot/channels/msteams.py b/nanobot/channels/msteams.py index 9a1efe9b7..3a341657f 100644 --- a/nanobot/channels/msteams.py +++ b/nanobot/channels/msteams.py @@ -358,17 +358,19 @@ class MSTeamsChannel(BaseChannel): if quoted and reply: return self._format_reply_with_quote(quoted, reply) - # Observed compact fallback where the relay flattens everything into one line - # and appends the literal reply text marker at the end. + # Observed compact fallback where the relay flattens quote and reply into + # a single line after the synthetic FWDIOC-BOT prefix. compact = re.sub(r"\s+", " ", normalized_newlines).strip() if compact.startswith("FWDIOC-BOT "): compact = compact[len("FWDIOC-BOT ") :].strip() - - marker = " Reply with quote test" - if compact.endswith(marker): - quoted = compact[: -len(marker)].strip() - reply = marker.strip() - return self._format_reply_with_quote(quoted, reply) + for boundary in (". ", "! ", "? ", "… "): + idx = compact.rfind(boundary) + if idx == -1: + continue + quoted = compact[: idx + 1].strip() + reply = compact[idx + len(boundary) :].strip() + if quoted and reply and len(reply) <= 160: + return self._format_reply_with_quote(quoted, reply) return cleaned diff --git a/tests/test_msteams.py b/tests/test_msteams.py index c75b51f94..3978d8cfb 100644 --- a/tests/test_msteams.py +++ b/tests/test_msteams.py @@ -264,6 +264,14 @@ def test_sanitize_inbound_text_structures_live_fwdioc_quote_shape(make_channel): ) +def test_normalize_teams_reply_quote_leaves_plain_text_test_phrase_untouched(make_channel): + ch = make_channel() + + text = "Normal message ending with Reply with quote test" + + assert ch._normalize_teams_reply_quote(text) == text + + def test_sanitize_inbound_text_structures_multiline_fwdioc_quote_shape(make_channel): ch = make_channel()