diff --git a/cron/scheduler.py b/cron/scheduler.py index 52ae8e31..f73d6585 100644 --- a/cron/scheduler.py +++ b/cron/scheduler.py @@ -87,6 +87,22 @@ def _resolve_delivery_target(job: dict) -> Optional[dict]: chat_id, thread_id = rest.split(":", 1) else: chat_id, thread_id = rest, None + + # Resolve human-friendly labels like "Alice (dm)" to real IDs. + # send_message(action="list") shows labels with display suffixes + # that aren't valid platform IDs (e.g. WhatsApp JIDs). + try: + from gateway.channel_directory import resolve_channel_name + target = chat_id + # Strip display suffix like " (dm)" or " (group)" + if target.endswith(")") and " (" in target: + target = target.rsplit(" (", 1)[0].strip() + resolved = resolve_channel_name(platform_name.lower(), target) + if resolved: + chat_id = resolved + except Exception: + pass + return { "platform": platform_name, "chat_id": chat_id, diff --git a/tests/cron/test_scheduler.py b/tests/cron/test_scheduler.py index 12bd8043..afec21ce 100644 --- a/tests/cron/test_scheduler.py +++ b/tests/cron/test_scheduler.py @@ -84,6 +84,48 @@ class TestResolveDeliveryTarget: "thread_id": None, } + def test_human_friendly_label_resolved_via_channel_directory(self): + """deliver: 'whatsapp:Alice (dm)' resolves to the real JID.""" + job = {"deliver": "whatsapp:Alice (dm)"} + with patch( + "gateway.channel_directory.resolve_channel_name", + return_value="12345678901234@lid", + ): + result = _resolve_delivery_target(job) + assert result == { + "platform": "whatsapp", + "chat_id": "12345678901234@lid", + "thread_id": None, + } + + def test_human_friendly_label_without_suffix_resolved(self): + """deliver: 'telegram:My Group' resolves without display suffix.""" + job = {"deliver": "telegram:My Group"} + with patch( + "gateway.channel_directory.resolve_channel_name", + return_value="-1009999", + ): + result = _resolve_delivery_target(job) + assert result == { + "platform": "telegram", + "chat_id": "-1009999", + "thread_id": None, + } + + def test_raw_id_not_mangled_when_directory_returns_none(self): + """deliver: 'whatsapp:12345@lid' passes through when directory has no match.""" + job = {"deliver": "whatsapp:12345@lid"} + with patch( + "gateway.channel_directory.resolve_channel_name", + return_value=None, + ): + result = _resolve_delivery_target(job) + assert result == { + "platform": "whatsapp", + "chat_id": "12345@lid", + "thread_id": None, + } + def test_bare_platform_uses_matching_origin_chat(self): job = { "deliver": "telegram",