diff --git a/cron/scheduler.py b/cron/scheduler.py index 21c91bcdee..d527a22601 100644 --- a/cron/scheduler.py +++ b/cron/scheduler.py @@ -49,6 +49,22 @@ _KNOWN_DELIVERY_PLATFORMS = frozenset({ "qqbot", }) +# Platforms that support a configured cron/notification home target, mapped to +# the environment variable used by gateway setup/runtime config. +_HOME_TARGET_ENV_VARS = { + "matrix": "MATRIX_HOME_ROOM", + "telegram": "TELEGRAM_HOME_CHANNEL", + "discord": "DISCORD_HOME_CHANNEL", + "slack": "SLACK_HOME_CHANNEL", + "signal": "SIGNAL_HOME_CHANNEL", + "mattermost": "MATTERMOST_HOME_CHANNEL", + "sms": "SMS_HOME_CHANNEL", + "feishu": "FEISHU_HOME_CHANNEL", + "wecom": "WECOM_HOME_CHANNEL", + "weixin": "WEIXIN_HOME_CHANNEL", + "bluebubbles": "BLUEBUBBLES_HOME_CHANNEL", +} + from cron.jobs import get_due_jobs, mark_job_run, save_job_output, advance_next_run # Sentinel: when a cron agent has nothing new to report, it can start its @@ -76,8 +92,17 @@ def _resolve_origin(job: dict) -> Optional[dict]: return None +def _get_home_target_chat_id(platform_name: str) -> str: + """Return the configured home target chat/room ID for a delivery platform.""" + env_var = _HOME_TARGET_ENV_VARS.get(platform_name.lower()) + if not env_var: + return "" + return os.getenv(env_var, "") + + def _resolve_single_delivery_target(job: dict, deliver_value: str) -> Optional[dict]: """Resolve one concrete auto-delivery target for a cron job.""" + origin = _resolve_origin(job) if deliver_value == "local": @@ -92,8 +117,8 @@ def _resolve_single_delivery_target(job: dict, deliver_value: str) -> Optional[d } # Origin missing (e.g. job created via API/script) — try each # platform's home channel as a fallback instead of silently dropping. - for platform_name in ("matrix", "telegram", "discord", "slack", "feishu", "wecom", "weixin", "bluebubbles"): - chat_id = os.getenv(f"{platform_name.upper()}_HOME_CHANNEL", "") + for platform_name in _HOME_TARGET_ENV_VARS: + chat_id = _get_home_target_chat_id(platform_name) if chat_id: logger.info( "Job '%s' has deliver=origin but no origin; falling back to %s home channel", @@ -148,7 +173,7 @@ def _resolve_single_delivery_target(job: dict, deliver_value: str) -> Optional[d if platform_name.lower() not in _KNOWN_DELIVERY_PLATFORMS: return None - chat_id = os.getenv(f"{platform_name.upper()}_HOME_CHANNEL", "") + chat_id = _get_home_target_chat_id(platform_name) if not chat_id: return None diff --git a/tests/cron/test_scheduler.py b/tests/cron/test_scheduler.py index da141edbf6..0877564fe6 100644 --- a/tests/cron/test_scheduler.py +++ b/tests/cron/test_scheduler.py @@ -67,6 +67,10 @@ class TestResolveDeliveryTarget: @pytest.mark.parametrize( ("platform", "env_var", "chat_id"), [ + ("matrix", "MATRIX_HOME_ROOM", "!bot-room:example.org"), + ("signal", "SIGNAL_HOME_CHANNEL", "+15551234567"), + ("mattermost", "MATTERMOST_HOME_CHANNEL", "team-town-square"), + ("sms", "SMS_HOME_CHANNEL", "+15557654321"), ("feishu", "FEISHU_HOME_CHANNEL", "oc_home"), ("wecom", "WECOM_HOME_CHANNEL", "wecom-home"), ("weixin", "WEIXIN_HOME_CHANNEL", "wxid_home"), @@ -76,10 +80,14 @@ class TestResolveDeliveryTarget: self, monkeypatch, platform, env_var, chat_id ): for fallback_env in ( + "MATRIX_HOME_ROOM", "MATRIX_HOME_CHANNEL", "TELEGRAM_HOME_CHANNEL", "DISCORD_HOME_CHANNEL", "SLACK_HOME_CHANNEL", + "SIGNAL_HOME_CHANNEL", + "MATTERMOST_HOME_CHANNEL", + "SMS_HOME_CHANNEL", "BLUEBUBBLES_HOME_CHANNEL", "FEISHU_HOME_CHANNEL", "WECOM_HOME_CHANNEL", @@ -94,6 +102,16 @@ class TestResolveDeliveryTarget: "thread_id": None, } + def test_bare_matrix_delivery_uses_matrix_home_room(self, monkeypatch): + monkeypatch.delenv("MATRIX_HOME_CHANNEL", raising=False) + monkeypatch.setenv("MATRIX_HOME_ROOM", "!room123:example.org") + + assert _resolve_delivery_target({"deliver": "matrix"}) == { + "platform": "matrix", + "chat_id": "!room123:example.org", + "thread_id": None, + } + def test_explicit_telegram_topic_target_with_thread_id(self): """deliver: 'telegram:chat_id:thread_id' parses correctly.""" job = {