diff --git a/tests/tools/test_send_message_target_parse.py b/tests/tools/test_send_message_target_parse.py index 6b1226580055..3440fef3032b 100644 --- a/tests/tools/test_send_message_target_parse.py +++ b/tests/tools/test_send_message_target_parse.py @@ -29,6 +29,23 @@ def test_e164_target_still_requires_phone_platform() -> None: assert _parse_target_ref("matrix", "+15551234567")[2] is False +def test_photon_dm_chat_guid_is_explicit() -> None: + # 'any;-;+1555...' is the platform-native DM space GUID inbound events + # carry — it must pass through verbatim instead of bouncing off the + # channel directory (issue #69960's secondary target-resolution bug). + chat_id, thread_id, is_explicit = _parse_target_ref( + "photon", "any;-;+15551234567" + ) + + assert chat_id == "any;-;+15551234567" + assert thread_id is None + assert is_explicit is True + + +def test_photon_dm_chat_guid_only_matches_photon() -> None: + assert _parse_target_ref("signal", "any;-;+15551234567")[2] is False + + def test_whatsapp_group_jid_target_is_explicit() -> None: chat_id, thread_id, is_explicit = _parse_target_ref( "whatsapp", "120363408391911677@g.us" diff --git a/tools/send_message_tool.py b/tools/send_message_tool.py index fff26ff75972..f6b7dc37d972 100644 --- a/tools/send_message_tool.py +++ b/tools/send_message_tool.py @@ -44,6 +44,8 @@ _NUMERIC_TOPIC_RE = _TELEGRAM_TOPIC_TARGET_RE # downstream adapters (signal, etc.) expect. _PHONE_PLATFORMS = frozenset({"photon", "signal", "sms", "whatsapp"}) _E164_TARGET_RE = re.compile(r"^\s*\+(\d{7,15})\s*$") +# Photon DM chat GUID (mirrors _DM_CHAT_GUID_RE in the photon adapter). +_PHOTON_DM_GUID_RE = re.compile(r"^any;-;\+\d{6,}$") # WhatsApp JIDs: group chats (@g.us), individual users # (@s.whatsapp.net), linked identities (@lid), and broadcast / # newsletter chats. These are explicit native targets the bridge accepts @@ -603,6 +605,12 @@ def _parse_target_ref(platform_name: str, target_ref: str): # Preserve the leading '+' — signal-cli and sms/whatsapp adapters # expect E.164 format for direct recipients. return target_ref.strip(), None, True + if platform_name == "photon": + # Photon DM chat GUIDs ('any;-;+1555...') are platform-native ids the + # adapter resolves itself — pass through verbatim instead of bouncing + # them off the channel directory (mirrors the react handler). + if _PHOTON_DM_GUID_RE.fullmatch(target_ref.strip()): + return target_ref.strip(), None, True if target_ref.lstrip("-").isdigit(): return target_ref, None, True # Matrix room IDs (start with !) and user IDs (start with @) are explicit