Build for HamsterHub

为 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

安装方式

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 时注入:

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 会给出能力/权限/风险报告并要你确认。

发布建议

优先做声明式插件;确需原生能力再用 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.primaryColorregions.<key>.show 必须是布尔;content 元素须在白名单内。老 manifest 只有 layoutregions 时自动 polyfill。

几种一改 region 就能造的形态