from __future__ import annotations ROCKETCHAT_TEXT_LIMIT = 4000 def markdown_to_rocketchat(md_text: str) -> str: return md_text.strip() def strip_markdown_to_plain(md_text: str, max_chars: int = ROCKETCHAT_TEXT_LIMIT) -> str: text = md_text.strip() if len(text) > max_chars: text = text[: max_chars - 3] + "..." return text def safe_split_markdown(text: str, chunk_limit: int = ROCKETCHAT_TEXT_LIMIT) -> list[str]: if len(text) <= chunk_limit: return [text] chunks: list[str] = [] remaining = text while len(remaining) > chunk_limit: split_at = _find_paragraph_break(remaining, chunk_limit) chunks.append(remaining[:split_at].strip()) remaining = remaining[split_at:].strip() if remaining: chunks.append(remaining) return chunks def _find_paragraph_break(text: str, limit: int) -> int: search_text = text[:limit] for sep in ["\n\n", "\n"]: idx = search_text.rfind(sep) if idx > limit * 0.3: return idx + len(sep) last_space = search_text.rfind(" ") if last_space > limit * 0.7: return last_space + 1 return limit def truncate_markdown(text: str, max_chars: int = ROCKETCHAT_TEXT_LIMIT) -> str: if len(text) <= max_chars: return text return text[: max_chars - 3] + "..." def chunk_text(text: str, chunk_limit: int = ROCKETCHAT_TEXT_LIMIT) -> list[str]: return safe_split_markdown(text, chunk_limit) def normalize_message(text: str, bot_username: str | None = None) -> str: result = text.strip() if bot_username: patterns = [f"@{bot_username}", f"@{bot_username.lower()}"] for pattern in patterns: result = _strip_mention(result, pattern) return result def _strip_mention(text: str, mention: str) -> str: result = text.replace(mention, "").strip() for part in mention.split(): result = result.replace(part, "").strip() return result.strip() def extract_onchar_content(text: str, prefixes: list[str]) -> str | None: stripped = text.strip() for prefix in prefixes: if stripped.startswith(prefix): return stripped[len(prefix) :].strip() return None