65 lines
1.9 KiB
Python
65 lines
1.9 KiB
Python
# -*- coding: utf-8 -*-
|
||
"""统一 Web 插件注册中心。
|
||
|
||
带 Web 控制台的插件只需在自身 __init__.py 里调用 register_web_plugin(...),
|
||
hub 启动时会自动聚合注册表、自动挂载 /api/<id>,无需手动改 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/<id> 与后端 API 前缀 /api/<id>
|
||
- 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
|