from __future__ import annotations import html import re MAX_TEAMS_TEXT_LENGTH = 4000 def decode_html_entities(text: str) -> str: return html.unescape(text) def strip_at_mentions(text: str) -> str: return re.sub(r"[^<]*", "", text).strip() def strip_markdown_links(text: str) -> str: return re.sub(r"\[([^\]]*)\]\([^)]*\)", r"\1", text) def clean_inbound_text(text: str) -> str: text = decode_html_entities(text) text = strip_at_mentions(text) text = text.strip() return text def chunk_text(text: str, limit: int = MAX_TEAMS_TEXT_LENGTH) -> list[str]: if len(text) <= limit: return [text] chunks = [] remaining = text while len(remaining) > limit: split_at = remaining.rfind("\n", 0, limit) if split_at == -1: split_at = remaining.rfind(". ", 0, limit) if split_at == -1: split_at = remaining.rfind(" ", 0, limit) if split_at == -1: split_at = limit chunks.append(remaining[:split_at].strip()) remaining = remaining[split_at:].strip() if remaining: chunks.append(remaining.strip()) return chunks def escape_teams_markdown(text: str) -> str: return text.replace("*", r"\*").replace("_", r"\_").replace("~", r"\~").replace("#", r"\#") def render_mention(name: str, user_id: str) -> str: return f"{name}" def extract_media_urls(attachments: list[dict]) -> list[dict]: result = [] for att in attachments: content_type = att.get("contentType", "") content_url = att.get("contentUrl", "") name = att.get("name", "") if content_url: result.append( { "url": content_url, "content_type": content_type, "name": name, } ) return result