为 HamsterHub 写插件与主题。
从一份 manifest 开始,声明定时任务、事件、界面入口,或挂一个常驻子进程;用 regions 拼出属于自己的界面形态。以下是核心格式、运行时与权限模型。
01插件是什么
HamsterHub 的插件分两类,装好即用,都在插件中心统一开关与配置:
声明式插件
纯 manifest 声明:定时任务(cron)、事件订阅、侧边栏 iframe、Webhook 转发。不执行第三方原生代码,可从 URL 安装,风险低。
常驻子进程 (sidecar)
manifest 里 runtime.type=process:HH 启动你的可执行文件、做健康检查、崩溃自动重启,并按声明的权限回调 HH API。
每个插件在源码里独占一个目录 internal/plugins/<slug>/;有配置项的插件配一个专属面板 web/src/plugins/<slug>/ConfigPanel.vue。完整开发指南见仓库 docs/PLUGIN_SIDECAR_DEVELOPMENT.md。
安装方式
- 插件商店:浏览内置 catalog 一键安装。
- 从 URL:粘贴
manifest.json(或 catalog.json)的公开地址。 - 新建 / 编辑:内置编辑器,表单与 JSON 双视图,全量改 manifest。
02Manifest 格式
声明式插件(cron + 事件 + 侧边栏入口 + Webhook):
// 声明式插件 manifest.json
{
"slug": "my-plugin",
"name": "我的插件",
"icon": "🧩",
"description": "...",
"cron_spec": "0 */6 * * *", // 定时触发
"event_subscribe": "media.imported,download.done",
"webhook_url": "http://127.0.0.1:9000/hook", // cron/事件时 POST 到这
"sidebar_label": "我的面板",
"iframe_url": "http://127.0.0.1:9000/ui",
"permissions": ["subscribe.read", "notification.write"]
}
常驻子进程(sidecar):加一段 runtime,HH 会启动并托管它。
{
"slug": "my-sidecar",
"name": "我的服务",
"runtime": {
"type": "process",
"command": "./bin/server", // 相对 plugin_dir
"args": ["--serve"],
"port": 39001,
"health": "/health",
"timeout_seconds": 30
},
"permissions": ["media.read", "download.write"]
}
子进程能拿到的环境变量
HH 启动 sidecar 时注入:
HH_PLUGIN_SLUG/HH_PLUGIN_DIR/HH_PLUGIN_DATA_DIR/HH_PLUGIN_LOG_DIRHH_PLUGIN_CONFIG:用户在配置面板填的 JSONHH_PLUGIN_PORT:分配的监听端口HH_API_BASE+HH_PLUGIN_TOKEN:回调 HH API 用,请求头带X-HH-Plugin-Token,按你声明并经用户同意的 scope 放行。
03权限 Scope
插件回调 HH API 时,只有 permissions 里声明、且安装时用户同意的 scope 才放行。回调 API 是白名单的——系统/中继/组网/全盘枚举等敏感端点一律不对插件开放。
| Scope | 能做什么 | 风险 |
|---|---|---|
site.read | 查看站点列表、健康与账号状态 | medium |
site.write | 新增/改/删站点、导入站点(含登录信息) | high |
site.cookie.read | 读站点 Cookie(= 等同账号,泄露即被盗号) | high |
search.read | 用你的站点跑搜索、拉结果 | medium |
download.read | 读下载列表与进度 | low |
download.write | 添加/暂停/删除下载任务 | medium |
subscribe.read | 读订阅规则与状态 | low |
subscribe.write | 增/改/删订阅、触发抓取 | medium |
media.read | 读媒体库条目与文件列表 | low |
media.write | 触发整理入库,可删除媒体库文件 | high |
notification.write | 经你配置的渠道发通知 | low |
system.read | 读系统指标 / 仪表盘(只读) | medium |
04安全与信任模型
声明式插件受回调白名单约束,能力可控。常驻子进程(sidecar)则不同——它是你机器上的一个原生程序:
sidecar 与 HamsterHub 同用户运行,拥有完整磁盘读写、自由出站网络与系统命令权限——破坏力等同于你在 NAS 上亲手运行一个程序。只安装你信任的发布者的进程型插件。安装前 HH 会给出能力/权限/风险报告并要你确认。
- 可选沙箱:给插件开「受限模式」后,HH 以 root 运行时会把子进程降权到
nobody,读不到 HH 的配置/数据库/密钥。 - 资源上限:manifest 可声明内存/CPU 上限,超限即停,防跑飞的进程拖垮 HH。
- 崩溃自愈:意外退出自动拉起,带崩溃循环熔断(5 分钟内超 5 次放弃)。
- 组网隔离:设备间互联由控制面按账号强隔离,插件跨不到其它账号的网络。
优先做声明式插件;确需原生能力再用 sidecar,并在 manifest 提供 sha256 校验值、声明最小必要 scope、写清它会读写什么。
05主题开发
主题是一份 manifest:定义配色、字体与四个区域(regions)——顶/左/右/底——的显示、尺寸与内容,即可拼出侧栏、底部 Tab、极简顶栏等不同形态。从 设置 → 外观 → 安装主题 用 URL 或粘贴 JSON 装入(存本地,不依赖后端)。完整参考见仓库 docs/THEME_DEVELOPMENT.md。
{
"id": "my-theme",
"name": "My Theme",
"emoji": "✨",
"mode": "dark",
"regions": {
"top": { "show": true, "size": 64, "style": "glass",
"content": ["logo","menu","spacer","search+actions"] },
"left": { "show": false },
"bottom": { "show": true, "kind": "dock", "size": 80 }
},
"menuStyle": "icon+label",
"overrides": { "common": { "primaryColor": "#f0b948" } },
"vars": { "--hh-radius": "20px" }
}
校验规则:必填 id / name / mode / overrides.common.primaryColor;regions.<key>.show 必须是布尔;content 元素须在白名单内。老 manifest 只有 layout 无 regions 时自动 polyfill。
几种一改 region 就能造的形态
- 手机风:顶栏 logo + 底部
kind:"bar"Tab Bar,primaryKeys指定主 Tab。 - Slack 风:左窄栏 + 右侧栏 + 顶部状态条。
- 极简:只留顶栏
content:["logo","menu","spacer","search+actions"]。