loader.py 1.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354
  1. """
  2. 渠道自动加载器。
  3. ``_CHANNEL_REGISTRY`` 登记所有可用渠道(channel_id → 插件类路径);
  4. ``CHANNELS_ENABLED`` 环境变量(逗号分隔)控制运行时实际启动哪些渠道。
  5. 新增渠道只需两步:
  6. 1. 在对应渠道模块的 Api 类上实现 ``ChannelPlugin`` Protocol
  7. (``from_env()`` classmethod + ``build_router()`` 方法)
  8. 2. 在 ``_CHANNEL_REGISTRY`` 中追加一行
  9. """
  10. from __future__ import annotations
  11. import importlib
  12. import logging
  13. import os
  14. from fastapi import APIRouter
  15. logger = logging.getLogger(__name__)
  16. # channel_id → 插件类的完整模块路径
  17. _CHANNEL_REGISTRY: dict[str, str] = {
  18. "feishu": "gateway.core.channels.feishu.api.FeishuChannelApi",
  19. # "wechat": "gateway.core.channels.wechat.api.WeChatChannelApi",
  20. }
  21. def _import_plugin(dotted_path: str) -> type:
  22. module_path, cls_name = dotted_path.rsplit(".", 1)
  23. module = importlib.import_module(module_path)
  24. return getattr(module, cls_name)
  25. def load_enabled_channels() -> list[APIRouter]:
  26. """读取 ``CHANNELS_ENABLED`` 并返回已启用渠道的路由列表。
  27. 未配置时默认启用 ``feishu``。未知渠道 ID 记录警告后跳过,不中断启动。
  28. """
  29. enabled_raw = os.getenv("CHANNELS_ENABLED", "feishu")
  30. enabled = [c.strip() for c in enabled_raw.split(",") if c.strip()]
  31. routers: list[APIRouter] = []
  32. for channel_id in enabled:
  33. if channel_id not in _CHANNEL_REGISTRY:
  34. logger.warning("Channel '%s' is not in the registry, skipping", channel_id)
  35. continue
  36. plugin_cls = _import_plugin(_CHANNEL_REGISTRY[channel_id])
  37. channel = plugin_cls.from_env()
  38. routers.append(channel.build_router())
  39. logger.info("Channel '%s' loaded", channel_id)
  40. return routers