from datetime import datetime import discord MODALITY_LABELS = { "bh_email": "BH Email", "personal_email": "Personal Email", "bh_text": "BH Text", "personal_text": "Personal Text", "voice": "Voice", "fb_messenger": "FB Messenger", "nd_messenger": "ND Messenger", "lead_found": "Found Lead", "magpie_lead": "Magpie Lead", } # Discord's API rejects embed field values of length 0 (min 1, max 1024 chars). # Use a zero-width space as a round-trip-safe sentinel for "empty" values so we # never send a literal "" to Discord. _EMPTY_FIELD_SENTINEL = "​" # Hard cap for any field value, with headroom for a truncation marker so the # final value never exceeds Discord's 1024-char limit regardless of caller. _FIELD_VALUE_MAX = 1024 _TRUNCATION_MARKER = "\n\n[...truncated for Discord embed limit...]" def _safe_field_value(value: str) -> str: """Return a Discord-safe embed field value: never empty, never over 1024 chars.""" if not value: return _EMPTY_FIELD_SENTINEL if len(value) > _FIELD_VALUE_MAX: keep = _FIELD_VALUE_MAX - len(_TRUNCATION_MARKER) return value[:keep] + _TRUNCATION_MARKER return value def build_ping_embed( *, modality: str, sender_id: str | None, snippet: str, raw_content: str, captured_at: datetime, direction: str = "inbound", image_url: str | None = None, ) -> discord.Embed: label = MODALITY_LABELS.get(modality, modality) embed = discord.Embed( title=f"{label}" + (f" - {sender_id}" if sender_id else ""), description=snippet, ) embed.add_field(name="modality", value=_safe_field_value(modality), inline=True) embed.add_field(name="direction", value=_safe_field_value(direction), inline=True) embed.add_field(name="sender_id", value=_safe_field_value(sender_id or ""), inline=True) embed.add_field( name="captured_at", value=_safe_field_value(captured_at.isoformat()), inline=True, ) embed.add_field( name="raw_content", value=_safe_field_value(raw_content), inline=False, ) # Discord CDN attachment URLs carry a signed expiry (ex/is/hm query params), # typically valid ~24h. Fine for same-day triage; a stale link just stops # rendering the preview without breaking anything else in the embed. if image_url: embed.set_image(url=image_url) return embed def parse_ping_embed(embed: discord.Embed) -> dict: values = {field.name: field.value for field in embed.fields} sender_id = values.get("sender_id") if sender_id == _EMPTY_FIELD_SENTINEL: sender_id = None else: sender_id = sender_id or None raw_content = values["raw_content"] if raw_content == _EMPTY_FIELD_SENTINEL: raw_content = "" direction = values.get("direction") or "inbound" return { "modality": values["modality"], "sender_id": sender_id, "raw_content": raw_content, "captured_at": datetime.fromisoformat(values["captured_at"]), "direction": direction, }