From 9f9374b715e388330e444cd6612581eccb983e47 Mon Sep 17 00:00:00 2001 From: mic1on Date: Sat, 11 Jul 2026 21:17:31 +0800 Subject: [PATCH] refactor: use explicit channel registry --- src/use_notify/channels/__init__.py | 18 ++++++++++++++++++ src/use_notify/notification.py | 7 +------ tests/test_notification.py | 9 +++++++++ 3 files changed, 28 insertions(+), 6 deletions(-) diff --git a/src/use_notify/channels/__init__.py b/src/use_notify/channels/__init__.py index dd8ae72..5c06ef8 100644 --- a/src/use_notify/channels/__init__.py +++ b/src/use_notify/channels/__init__.py @@ -13,3 +13,21 @@ # 兼容wecom WeCom = WeChat + +CHANNEL_REGISTRY = { + "bark": Bark, + "chanify": Chanify, + "console": Console, + "ding": Ding, + "email": Email, + "feishu": Feishu, + "ntfy": Ntfy, + "pushdeer": PushDeer, + "pushover": PushOver, + "wechat": WeChat, + "wecom": WeChat, +} + + +def get_channel_class(name): + return CHANNEL_REGISTRY.get(name.lower()) diff --git a/src/use_notify/notification.py b/src/use_notify/notification.py index ba0f6fd..401699e 100644 --- a/src/use_notify/notification.py +++ b/src/use_notify/notification.py @@ -280,12 +280,7 @@ def from_settings(cls, settings: dict): """ channels = [] for channel, cfg in settings.items(): - # Try to get class by case-insensitive match - channel_cls = None - for cls_name in dir(channels_models): - if cls_name.lower() == channel.lower(): - channel_cls = getattr(channels_models, cls_name) - break + channel_cls = channels_models.get_channel_class(channel) if not channel_cls: raise ValueError(f"Unknown channel {channel}") channel = channel_cls(cfg) diff --git a/tests/test_notification.py b/tests/test_notification.py index af45067..7688dae 100644 --- a/tests/test_notification.py +++ b/tests/test_notification.py @@ -417,6 +417,15 @@ def test_notify_from_settings_builds_case_insensitive_channels(): assert isinstance(notify_instance.channels[1], useNotifyChannel.WeCom) +def test_notify_from_settings_ignores_unregistered_module_attributes(monkeypatch): + monkeypatch.setattr( + notification_module.channels_models, "Ghost", useNotifyChannel.Bark, raising=False + ) + + with pytest.raises(ValueError, match="Unknown channel ghost"): + useNotify.from_settings({"ghost": {"token": "x"}}) + + def test_notify_from_settings_rejects_unknown_channel(): with pytest.raises(ValueError, match="Unknown channel"): useNotify.from_settings({"unknown": {"token": "x"}})