diff --git a/bot/chorus_bot/ping.py b/bot/chorus_bot/ping.py index e6ec946..8a1dd4f 100644 --- a/bot/chorus_bot/ping.py +++ b/bot/chorus_bot/ping.py @@ -9,6 +9,8 @@ MODALITY_LABELS = { "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). @@ -34,7 +36,7 @@ def _safe_field_value(value: str) -> str: def build_ping_embed( *, modality: str, sender_id: str | None, snippet: str, raw_content: str, - captured_at: datetime, + captured_at: datetime, direction: str = "inbound", ) -> discord.Embed: label = MODALITY_LABELS.get(modality, modality) embed = discord.Embed( @@ -42,6 +44,7 @@ def build_ping_embed( 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, @@ -64,9 +67,12 @@ def parse_ping_embed(embed: discord.Embed) -> dict: 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, } diff --git a/bot/tests/test_ping.py b/bot/tests/test_ping.py index e668117..20c0289 100644 --- a/bot/tests/test_ping.py +++ b/bot/tests/test_ping.py @@ -1,4 +1,5 @@ from datetime import datetime, timezone +import discord from chorus_bot import ping @@ -90,3 +91,36 @@ def test_build_ping_embed_truncates_long_raw_content(): raw_content_field = next(f for f in embed.fields if f.name == "raw_content") assert len(raw_content_field.value) <= 1024 assert "truncated" in raw_content_field.value + + +def test_build_and_parse_round_trip_includes_direction(): + captured_at = datetime(2026, 7, 13, 7, 0, 0, tzinfo=timezone.utc) + embed = ping.build_ping_embed( + modality="lead_found", sender_id=None, snippet="found post", + raw_content="Someone posted about donating books on Nextdoor", + captured_at=captured_at, direction="outbound", + ) + parsed = ping.parse_ping_embed(embed) + assert parsed["direction"] == "outbound" + + +def test_build_ping_embed_direction_defaults_to_inbound(): + embed = ping.build_ping_embed( + modality="bh_email", sender_id="jane@example.com", snippet="hi", + raw_content="hi", captured_at=datetime(2026, 7, 13, 7, 0, 0, tzinfo=timezone.utc), + ) + parsed = ping.parse_ping_embed(embed) + assert parsed["direction"] == "inbound" + + +def test_parse_ping_embed_defaults_direction_when_field_missing(): + """Regression guard: embeds built before this change have no direction + field at all -- parsing one must not raise and must default to inbound.""" + embed = discord.Embed(title="bh_email", description="hi") + embed.add_field(name="modality", value="bh_email", inline=True) + embed.add_field(name="sender_id", value="jane@example.com", inline=True) + embed.add_field(name="captured_at", value="2026-07-13T07:00:00+00:00", inline=True) + embed.add_field(name="raw_content", value="hi", inline=False) + + parsed = ping.parse_ping_embed(embed) + assert parsed["direction"] == "inbound"