# -*- coding: utf-8 -*- """统一 Web 插件注册中心。 带 Web 控制台的插件只需在自身 __init__.py 里调用 register_web_plugin(...), hub 启动时会自动聚合注册表、自动挂载 /api/,无需手动改 hub 或配置环境变量。 """ from __future__ import annotations from typing import Any, Callable _plugins: dict[str, dict[str, Any]] = {} # NoneBot 插件模块名 -> web plugin id(用于插件目录合表) _module_to_id: dict[str, str] = {} def register_web_plugin( plugin_id: str, name: str, icon: str, builder: Callable[[], Any], module_name: str | None = None, ) -> None: """注册一个 Web 插件。builder 返回一个 FastAPI 子应用(或 None 表示不挂载)。 - plugin_id 会决定前端路由 /hub/ 与后端 API 前缀 /api/ - name 显示在侧边栏 - icon 为 Gravity 图标名(前端按需映射) - module_name 为 NoneBot 插件模块名,用于把「有 Web」的插件和插件目录合表 """ if builder is None: builder = lambda: None # noqa: E731 _plugins[plugin_id] = { "id": plugin_id, "name": name, "icon": icon, "builder": builder, "module_name": module_name, } if module_name: _module_to_id[module_name] = plugin_id def list_web_plugins() -> list[dict[str, Any]]: return [ { "id": p["id"], "name": p["name"], "icon": p["icon"], "module_name": p.get("module_name") or "", } for p in _plugins.values() ] def get_web_plugin_by_module(module_name: str) -> dict[str, Any] | None: """按 NoneBot 模块名查 web 插件记录(无则 None)。""" pid = _module_to_id.get(module_name) return _plugins.get(pid) if pid else None def get_web_plugin_builder(plugin_id: str) -> Callable[[], Any] | None: p = _plugins.get(plugin_id) return p["builder"] if p else None