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 }) }); if (!response.ok) throw new Error(`server 请求失败: HTTP ${response.status}`); const result = await response.json(); if (!result.success) throw new Error(result.errMsg || "server 返回失败"); return result; } function downloadHeaders(options = {}) { if (!options.adminToken) return {}; return { authorization: `Bearer ${options.adminToken}`, "x-admin-token": options.adminToken }; } 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, { headers: downloadHeaders(options) }); 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 };