const fs = require("node:fs"); const path = require("node:path"); const { Readable } = require("node:stream"); const { pipeline } = require("node:stream/promises"); const DOWNLOAD_DIR = path.resolve(process.env.DOWNLOAD_DIR || "downloads"); function getServerCredentials(options = {}) { const apiUrl = options.apiUrl || process.env.REINLOOP_API_URL; const adminToken = options.adminToken || process.env.B_ADMIN_TOKEN; if (!apiUrl) throw new Error("缺少 server API URL"); if (!adminToken) throw new Error("缺少 Admin Token"); return { apiUrl, adminToken }; } async function callServer(payload, options = {}) { const { apiUrl, adminToken } = getServerCredentials(options); const response = await fetch(apiUrl, { method: "POST", headers: { "content-type": "application/json" }, body: JSON.stringify({ ...payload, adminToken }) }); let result = null; try { result = await response.json(); } catch { result = null; } if (!response.ok) { const message = result && typeof result.errMsg === "string" && result.errMsg ? result.errMsg : `server 请求失败: HTTP ${response.status}`; throw new Error(message); } if (!result || typeof result !== "object") { throw new Error("server 返回格式无效"); } if (!result.success) throw new Error(result.errMsg || "server 返回失败"); return result; } async function downloadFromUrl(url, fileName, options = {}) { await fs.promises.mkdir(DOWNLOAD_DIR, { recursive: true }); return downloadToPath(url, path.join(DOWNLOAD_DIR, path.basename(fileName)), options); } async function downloadToPath(url, destination, options = {}) { const response = await fetch(url); if (!response.ok || !response.body) { throw new Error(`下载失败: HTTP ${response.status}`); } await fs.promises.mkdir(path.dirname(destination), { recursive: true }); const temporary = `${destination}.downloading`; try { await pipeline(Readable.fromWeb(response.body), fs.createWriteStream(temporary)); await fs.promises.rename(temporary, destination); } catch (error) { await fs.promises.rm(temporary, { force: true }); throw error; } console.log(`[${new Date().toISOString()}] 已下载: ${destination}`); return destination; } async function downloadFile(fileID, fileName, options = {}) { const { url } = await callServer({ type: "downloadModel", fileID }, options); return downloadFromUrl(url, fileName, options); } module.exports = { callServer, downloadFile, downloadFromUrl, downloadToPath, getServerCredentials };