# Nanami API 文档 所有公开接口均无需认证,供客户端软件直接调用。 基础 URL: `https://nui.rucky.cn` --- # 一、插件市场 API 供启动器拉取插件列表、详情、版本和下载。 --- ## 1.1 获取插件列表 ### 请求 ``` GET /api/addons ``` ### 参数 | 参数 | 类型 | 必填 | 说明 | |---|---|---|---| | category | string | 否 | 按分类筛选(如 `ui`, `quest`, `combat`, `general`) | | search | string | 否 | 按名称或简介模糊搜索 | | published | string | 否 | 默认 `true` 只返回已发布插件,传 `false` 返回全部 | ### 响应示例 ```json [ { "id": "cxxx001", "name": "Nanami", "slug": "nanami", "summary": "一站式乌龟服插件管理器", "description": "详细描述...", "iconUrl": "/uploads/nanami-icon.png", "category": "general", "published": true, "totalDownloads": 1234, "createdAt": "2026-01-01T00:00:00.000Z", "updatedAt": "2026-03-18T10:00:00.000Z", "releases": [ { "id": "rel001", "version": "1.0.0", "isLatest": true } ], "_count": { "releases": 3 } } ] ``` ### 响应字段说明 | 字段 | 类型 | 说明 | |---|---|---| | id | string | 插件唯一 ID | | name | string | 插件名称 | | slug | string | 插件标识(URL 友好) | | summary | string | 简短描述 | | description | string | 详细描述(支持长文本) | | iconUrl | string\|null | 图标地址 | | category | string | 分类标签 | | published | boolean | 是否已发布 | | totalDownloads | int | 累计下载次数 | | releases | array | 最新版本信息(仅包含 isLatest=true 的版本) | | _count.releases | int | 版本总数 | --- ## 1.2 获取插件详情 通过 ID 或 slug 获取单个插件的完整信息,包含所有版本和截图。 ### 请求 ``` GET /api/addons/{id_or_slug} ``` ### 参数 | 参数 | 说明 | |---|---| | id_or_slug | 插件 ID 或 slug,如 `nanami` | ### 响应示例 ```json { "id": "cxxx001", "name": "Nanami", "slug": "nanami", "summary": "一站式乌龟服插件管理器", "description": "详细的 Markdown 描述...", "iconUrl": "/uploads/nanami-icon.png", "category": "general", "published": true, "totalDownloads": 1234, "createdAt": "2026-01-01T00:00:00.000Z", "updatedAt": "2026-03-18T10:00:00.000Z", "releases": [ { "id": "rel003", "addonId": "cxxx001", "version": "1.2.0", "changelog": "- 新增XX功能\n- 修复YY问题", "downloadType": "local", "filePath": "uploads/nanami-1.2.0.zip", "externalUrl": null, "gameVersion": "1.12.1", "downloadCount": 500, "isLatest": true, "createdAt": "2026-03-18T10:00:00.000Z" }, { "id": "rel002", "addonId": "cxxx001", "version": "1.1.0", "changelog": "- 修复界面问题", "downloadType": "local", "filePath": "uploads/nanami-1.1.0.zip", "externalUrl": null, "gameVersion": "1.12.1", "downloadCount": 300, "isLatest": false, "createdAt": "2026-02-15T10:00:00.000Z" } ], "screenshots": [ { "id": "ss001", "addonId": "cxxx001", "imageUrl": "/uploads/screenshot1.png", "sortOrder": 0 } ] } ``` ### 错误响应 | HTTP 状态码 | 说明 | |---|---| | 404 | 插件不存在 | --- ## 1.3 获取版本列表 获取所有版本,可按插件 ID 筛选。 ### 请求 ``` GET /api/releases?addonId={addonId} ``` ### 参数 | 参数 | 类型 | 必填 | 说明 | |---|---|---|---| | addonId | string | 否 | 按插件 ID 筛选 | ### 响应示例 ```json [ { "id": "rel003", "addonId": "cxxx001", "version": "1.2.0", "changelog": "- 新增XX功能", "downloadType": "local", "filePath": "uploads/nanami-1.2.0.zip", "externalUrl": null, "gameVersion": "1.12.1", "downloadCount": 500, "isLatest": true, "createdAt": "2026-03-18T10:00:00.000Z", "addon": { "id": "cxxx001", "name": "Nanami", "slug": "nanami" } } ] ``` ### 版本字段说明 | 字段 | 类型 | 说明 | |---|---|---| | id | string | 版本唯一 ID | | addonId | string | 所属插件 ID | | version | string | 版本号(如 "1.2.0") | | changelog | string | 更新日志 | | downloadType | string | `local` 本地文件 / `url` 外部链接 | | gameVersion | string | 适配的游戏版本(如 "1.12.1") | | downloadCount | int | 下载次数 | | isLatest | boolean | 是否为最新版本 | | addon | object | 所属插件基本信息 | --- ## 1.4 下载插件 通过版本 ID 下载对应的插件压缩包。 ### 请求 ``` GET /api/download/{releaseId} ``` ### 行为 - **本地文件**:返回文件二进制流,`Content-Disposition` 设为 `attachment` - **外部链接**:302 重定向到外部下载地址 - 每次调用自动递增版本下载计数和插件总下载计数 ### 响应头(本地文件时) ``` Content-Type: application/octet-stream Content-Disposition: attachment; filename="nanami-1.2.0.zip" Content-Length: 1048576 ``` ### 错误响应 | HTTP 状态码 | 说明 | |---|---| | 404 | 版本不存在或文件丢失 | --- # 二、软件更新 API 供启动器检查自身版本更新和热更新。 --- ## 软件标识(slug) | slug | 用途 | 文件类型 | |---|---|---| | `nanami-launcher` | 启动器全量安装包 | Nanami-Launcher-x.x.x.exe | | `nanami-launcher-patch` | 热更新补丁包 | app.asar | --- ## 2.1 检查更新 客户端启动时调用此接口,传入当前版本号以检测是否有新版本可用。 ### 请求 ``` GET /api/software/check-update?slug={slug}&versionCode={versionCode} ``` ### 参数 | 参数 | 类型 | 必填 | 说明 | |---|---|---|---| | slug | string | 是 | 软件标识 | | versionCode | int | 否 | 当前客户端的版本代码(整数),不传默认为 0 | ### 响应示例 **有更新:** ```json { "hasUpdate": true, "forceUpdate": false, "latest": { "version": "1.2.0", "versionCode": 120, "changelog": "- 新增XX功能\n- 修复YY问题", "downloadUrl": "https://nui.rucky.cn/api/software/download/cxxx123", "fileSize": 5242880, "minVersion": "1.0.0", "createdAt": "2026-03-18T10:00:00.000Z" } } ``` **无更新:** ```json { "hasUpdate": false, "forceUpdate": false, "latest": { "version": "1.0.0", "versionCode": 100, "changelog": "...", "downloadUrl": "https://nui.rucky.cn/api/software/download/cxxx123", "fileSize": 5242880, "minVersion": null, "createdAt": "2026-03-01T10:00:00.000Z" } } ``` ### 响应字段说明 | 字段 | 类型 | 说明 | |---|---|---| | hasUpdate | boolean | 是否有新版本 | | forceUpdate | boolean | 是否强制更新(true 时客户端应阻止用户继续使用旧版) | | latest.version | string | 最新版本号(如 "1.2.0") | | latest.versionCode | int | 最新版本代码(整数,用于比较大小) | | latest.changelog | string | 更新日志 | | latest.downloadUrl | string | 下载地址(直接用于下载) | | latest.fileSize | int | 文件大小(字节) | | latest.minVersion | string\|null | 最低兼容版本号 | | latest.createdAt | string | 发布时间 (ISO 8601) | ### 错误响应 | HTTP 状态码 | 说明 | |---|---| | 400 | 缺少 slug 参数 | | 404 | 软件不存在或暂无版本 | --- ## 2.2 下载软件包 通过版本 ID 下载对应的软件安装包。一般从"检查更新"接口返回的 `downloadUrl` 直接获取。 ### 请求 ``` GET /api/software/download/{versionId} ``` ### 行为 - **本地文件**:返回文件二进制流,`Content-Disposition` 设为 `attachment` - **外部链接**:302 重定向到外部下载地址 - 每次调用自动递增下载计数 ### 响应头(本地文件时) ``` Content-Type: application/octet-stream Content-Disposition: attachment; filename="nanami-launcher-v1.2.0.exe" Content-Length: 5242880 ``` ### 错误响应 | HTTP 状态码 | 说明 | |---|---| | 404 | 版本不存在或文件丢失 | --- ## 2.3 首页启动器最新版本下载 直接下载 `nanami-launcher` 的最新版本,用于首页下载按钮。 ### 请求 ``` GET /api/software/latest ``` 下载最新全量包(自动递增下载计数)。 ``` GET /api/software/latest?info=1 ``` 仅返回版本信息 JSON,不下载。 --- ## 2.4 客户端更新检查流程 Nanami 启动器在启动后应按以下顺序检查更新: ``` 客户端启动(当前 versionCode = 76) │ ├── 步骤 1: 检查全量更新 │ GET /api/software/check-update?slug=nanami-launcher&versionCode=76 │ │ │ ├── forceUpdate=true → 弹出强制更新对话框,下载完整安装包 │ │ 不再检查热更新 │ │ │ └── hasUpdate=true, forceUpdate=false → 显示"新版本"徽章(用户自行决定) │ │ │ └── 继续步骤 2 │ ├── 步骤 2: 检查热更新 │ GET /api/software/check-update?slug=nanami-launcher-patch&versionCode=76 │ │ │ ├── hasUpdate=true → 静默下载 app.asar,替换本地文件 │ │ 显示"就绪"徽章,提示重启生效 │ │ │ └── hasUpdate=false → 当前已是最新,无需操作 │ └── 正常运行 ``` ### 版本号对应关系示例 | 发布类型 | 版本号 | versionCode | slug | |---|---|---|---| | 全量安装包 | 0.7.6 | 76 | nanami-launcher | | 热更新补丁 | 0.7.7 | 77 | nanami-launcher-patch | | 全量大版本 | 0.8.0 | 80 | nanami-launcher | ### 后台操作 - **发布全量版本**:在「Nanami 启动器(全量包)」中上传 `.exe` 文件 - **发布热更新**:在「Nanami 热更新包」中上传 `app.asar` 文件 - 两者的 `versionCode` 应保持递增关系,以便客户端正确比较 --- --- # 三、客户端集成示例(Electron) ## 3.1 启动器自身更新 ```javascript const BASE_URL = "https://nui.rucky.cn/api/software/check-update"; const CURRENT_VERSION_CODE = 76; async function checkUpdates() { // 步骤 1: 检查全量更新 const fullResp = await fetch( `${BASE_URL}?slug=nanami-launcher&versionCode=${CURRENT_VERSION_CODE}` ); const fullData = await fullResp.json(); if (fullData.hasUpdate && fullData.forceUpdate) { showForceUpdateDialog(fullData.latest); return; } if (fullData.hasUpdate) { showUpdateBadge(fullData.latest); } // 步骤 2: 检查热更新 const patchResp = await fetch( `${BASE_URL}?slug=nanami-launcher-patch&versionCode=${CURRENT_VERSION_CODE}` ); const patchData = await patchResp.json(); if (patchData.hasUpdate) { const asarResp = await fetch(patchData.latest.downloadUrl); const buffer = await asarResp.arrayBuffer(); // 写入本地 app.asar 路径... showRestartBadge(); } } ``` ## 3.2 插件市场拉取 ```javascript const API_BASE = "https://nui.rucky.cn"; // 获取全部已发布插件 async function fetchAddons(category?: string, search?: string) { const params = new URLSearchParams(); if (category) params.set("category", category); if (search) params.set("search", search); const resp = await fetch(`${API_BASE}/api/addons?${params}`); return resp.json(); } // 获取单个插件详情(含所有版本和截图) async function fetchAddonDetail(slug: string) { const resp = await fetch(`${API_BASE}/api/addons/${slug}`); return resp.json(); } // 下载插件最新版本 async function downloadAddon(addon: any) { const latestRelease = addon.releases?.find((r: any) => r.isLatest); if (!latestRelease) return; const downloadUrl = `${API_BASE}/api/download/${latestRelease.id}`; const resp = await fetch(downloadUrl); const buffer = await resp.arrayBuffer(); // 保存到 WoW 插件目录 Interface/AddOns/... } // 检查插件是否有更新(对比本地已安装版本) async function checkAddonUpdates(installedAddons: { slug: string; version: string }[]) { const addons = await fetchAddons(); const updates = []; for (const installed of installedAddons) { const remote = addons.find((a: any) => a.slug === installed.slug); if (!remote) continue; const latestRelease = remote.releases?.[0]; if (latestRelease && latestRelease.version !== installed.version) { updates.push({ addon: remote, currentVersion: installed.version, newVersion: latestRelease.version, }); } } return updates; } ```