首页
/ homepage 集成 SABnzbd Widget 完整配置指南:速率、队列与剩余时间监控

homepage 集成 SABnzbd Widget 完整配置指南:速率、队列与剩余时间监控

2026-09-09 09:11:17作者:范垣楠Rhoda

导读

本文讲解如何在 homepage 项目中为 SABnzbd(Usenet 下载工具)添加服务 Widget,实现下载速率(Rate)、队列条目数(Queue)与预计剩余时间(Time Left)的实时展示。你将掌握从获取 API Key、编写 services.yaml 配置,到理解请求代理链路与前端单位换算原理的完整流程,可直接复制配置接入自己的仪表盘。

前置准备:确认 SABnzbd 实例与 API Key

在配置 Widget 之前,需要满足两个条件:

  1. 一个可访问的 SABnzbd 实例:homepage 通过 HTTP 请求 SABnzbd 的 API,因此你的 SABnzbd 地址必须能从运行 homepage 的机器(容器或宿主机)访问到。常见形式为 http://sabnzbd.host.or.ip:8080
  2. API Key:在 SABnzbd 的 Config > General 页面中可以找到你的 API Key(通常位于 SABnzbd 配置页面底部,API Key 字段)。该 Key 是调用 SABnzbd API 的身份凭证,homepage 会把它拼接到请求 URL 中。

原文档提示:API Key 在 Config > General 下查找。它是一串较长的字符串,复制时注意不要包含多余空格或换行。

编写 Widget 配置

SABnzbd Widget 在 homepage 的 services.yaml 中配置。将其放入某个服务分组(Group)下,完整的最小配置如下:

widget:
  type: sabnzbd
  url: http://sabnzbd.host.or.ip
  key: apikeyapikeyapikeyapikeyapikey

配置字段说明

字段 必填 说明
type 固定为 sabnzbd,用于在 homepage 的 widgets 注册表 中匹配对应实现
url SABnzbd 实例的基础地址,无需带末尾斜杠(代理层会自动去除尾部 /
key 来自 SABnzbd Config > General 的 API Key,用于请求鉴权

从源码看,key 会被直接填充进 API 模板 {url}/api/?apikey={key}&output=json&mode={endpoint}(见 widget.js),因此 API Key 必须准确无误,否则请求将返回鉴权错误,组件会渲染错误提示 UI。

Allowed fields:可展示的统计字段

该 Widget 支持且仅支持以下三个字段:

["rate", "queue", "timeleft"]
  • rate(Rate):当前下载速率,例如 1.0 M,组件会将字符串换算为字节数后按 common.byterate 翻译键格式化展示;
  • queue(Queue):当前队列中的下载条目数量(noofslots 字段);
  • timeleft(Time Left):队列预计完成所需时间,例如 00:01:00

这三个字段是文档明确允许的展示项,不包含上传速率、磁盘剩余等 SABnzbd 提供的其他 API 字段,请勿在配置中声明不支持的字段。

深入源码:请求如何被构造与代理

配置中只需要三个字段,但背后是 homepage 一套完整的代理机制在运作。

API 模板与 endpoint 映射

widget.js 定义了 SABnzbd Widget 的全部后端逻辑:

const widget = {
  api: "{url}/api/?apikey={key}&output=json&mode={endpoint}",
  proxyHandler: genericProxyHandler,

  mappings: {
    queue: {
      endpoint: "queue",
      validate: ["queue"],
    },
  },
};
  • api 模板:最终请求地址由 {url}{key}{endpoint} 三个占位符组成。output=json 要求 SABnzbd 返回 JSON 格式,mode={endpoint} 会被替换为具体的 API 模式。
  • mappings.queue:唯一的 endpoint 映射,客户端请求 queue 端点时,代理层将其转换为 SABnzbd API 的 mode=queue 调用。
  • validate: ["queue"]:响应数据必须包含顶层 queue 字段才算合法,否则代理会返回 "Invalid data" 错误。

占位符替换与代理转发

占位符替换由 api-helpers.js 中的 formatApiCall 完成:它扫描模板中的 {...} 并依次用对应参数替换,其中 url 会先去除尾部斜杠(replace(/\/+$/, "")),避免出现 http://host//api/... 之类的双斜杠问题。

请求转发由 generic.js 中的 genericProxyHandler 负责:

  1. 根据 groupservice 从用户配置中读取该服务的 Widget 定义;
  2. 校验 Widget 类型是否注册(widgets?.[widget.type]?.api),未注册则返回 403;
  3. formatApiCall 拼接完整 API URL;
  4. 支持为 Widget 附加自定义 headersusername/password(Basic Auth)与 requestBody
  5. 通过 httpProxy 发起请求,status === 200 时调用 validateWidgetData 校验数据形状;
  6. 校验失败返回 "Invalid data" 错误,>= 400 状态码返回 "HTTP Error" 并附上脱敏后的 URL(仅保留主机名,见 sanitizeErrorURL)。

前端侧的 use-widget-api.js 通过 SWR 请求 /api/services/proxy?group=...&service=...&endpoint=queue,并自动处理错误透传与可选的刷新间隔。

前端渲染:单位换算与三块统计信息

组件实现在 component.jsx(对应 src/widgets/sabnzbd/component.jsx)。加载成功后渲染三块统计:

<Block label="sabnzbd.rate" value={t("common.byterate", { value: fromUnits(queueData.queue.speed) })} />
<Block label="sabnzbd.queue" value={t("common.number", { value: queueData.queue.noofslots })} />
<Block label="sabnzbd.timeleft" value={queueData.queue.timeleft} />

关键点在于 fromUnits 函数(component.jsx):

function fromUnits(value) {
  const units = ["B", "K", "M", "G", "T", "P"];
  const [number, unit] = value.split(" ");
  const index = units.indexOf(unit);
  if (index === -1) {
    return 0;
  }
  return parseFloat(number) * 1024 ** index;
}

SABnzbd API 返回的 speed 是类似 "1.0 M" 的字符串(数值 + 空格 + 单位),fromUnits 将其拆分为数字与单位后缀,按 1024 进制(K=1024、M=1024²、G=1024³……)换算为字节数,再由 common.byterate 翻译键格式化为人类可读速率。若单位无法识别则返回 0,避免渲染异常。

三块统计的文案标签(Rate / Queue / Time Left)来自 public/locales/en/common.jsonsabnzbd 命名空间,其余语言文件同理,因此 Widget 文案会随 homepage 界面语言自动切换。

测试验证:组件行为有据可查

仓库为 SABnzbd Widget 提供了完整测试,可作为行为契约:

  • widget.test.js:校验导出的 Widget 配置结构合法;
  • component.test.jsx
    • 加载态:数据未返回时渲染 3 个占位 Block(sabnzbd.rate / sabnzbd.queue / sabnzbd.timeleft);
    • 错误态:接口报错时渲染 widget.api_error 错误 UI 并透传错误消息;
    • 数据态{ queue: { speed: "1.0 M", noofslots: 2, timeleft: "00:01:00" } } 时,速率块期望值为 1024 ** 2(即 1 MiB),队列块为 2,剩余时间块为 "00:01:00",与 fromUnits 换算逻辑一一对应。

这组测试同时验证了前端渲染与换算逻辑,你在排查展示异常时可以直接参照其断言。

常见问题排查

现象 可能原因 排查方向
Widget 显示 "HTTP Error" url 不可达或 SABnzbd 未运行 在运行 homepage 的环境中 curl 测试 {url}/api/?apikey=...&output=json&mode=queue
显示鉴权失败 API Key 错误 回到 SABnzbd Config > General 重新复制 Key,检查是否有空格
显示 "Invalid data" 响应缺少顶层 queue 字段 确认 SABnzbd 版本 API 返回格式,或直接在浏览器访问上述 API 地址核对 JSON 结构
速率显示为 0 SABnzbd 返回的单位不在 B/K/M/G/T/P 中,或当前无下载任务 空闲队列时 speed 可能为空值,属正常现象

小结

SABnzbd Widget 是 homepage 服务集成体系中的一个典型示例:配置侧只需 typeurlkey 三个字段,后端通过 widget.js 的 API 模板与 generic.js 的通用代理完成请求转发与数据校验,前端再由 component.jsx 完成单位换算与三块统计渲染。如果你需要展示更多 SABnzbd 指标,可以结合 widgets.js 注册表API 文档 了解扩展方式;其他下载类服务(如 qBittorrent、Transmission)的配置思路与此一致,可对照 services 文档目录 逐一配置。

登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.14 K
2.75 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
857
1.35 K
docsdocs
暂无描述
Markdown
899
5.82 K
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
920
1.85 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.8 K
1.02 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
532
596
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
1.02 K
521
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.36 K
1.46 K
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
548
392