const cron = require("node-cron"); const axios = require("axios"); const fs = require("fs-extra"); const path = require("path"); const unzipper = require("unzipper"); const time = "0 0 2 * *" //设置时间 // 下载链接 const DOWNLOAD_URL = "https://www.ip2location.com/download/?token=3Fi4pprzwKQUHVgw8F8HOnfWrmLTjpLCvJ9w8E7nzIlm3avAT2aJp8u68VHGiPyb&file=DB1LITEBIN"; // 文件保存路径 const DESTINATION_PATH = path.join(__dirname, "src/db"); const ZIP_FILE_PATH = path.join(DESTINATION_PATH, "db_download.zip"); // 临时 ZIP 文件路径 // 下载文件(带重试机制) async function downloadFileWithRetry(url, destination, retries = 3) { for (let attempt = 1; attempt <= retries; attempt++) { try { console.log(`📥 尝试下载 (${attempt}/${retries})...`); const response = await axios({ method: "GET", url, responseType: "stream", }); // 确保目录存在 await fs.ensureDir(path.dirname(destination)); // 保存 ZIP 文件 const writer = fs.createWriteStream(destination); response.data.pipe(writer); await new Promise((resolve, reject) => { writer.on("finish", resolve); writer.on("error", reject); }); console.log("✅ ZIP 文件下载成功!"); return true; } catch (error) { console.error(`❌ 下载失败 (尝试 ${attempt}/${retries}):`, error.message); if (attempt === retries) { console.error("⚠️ 最终下载失败,放弃重试!"); return false; } await new Promise((resolve) => setTimeout(resolve, 5000)); // 等待 5 秒再重试 } } } // 解压 ZIP 文件 async function unzipFile(zipPath, extractTo) { try { console.log("📂 开始解压 ZIP 文件..."); await fs.ensureDir(extractTo); // 确保解压目录存在 await fs.createReadStream(zipPath) .pipe(unzipper.Extract({ path: extractTo })) .promise(); console.log("✅ ZIP 文件解压成功!"); await fs.remove(zipPath); // 删除 ZIP 文件,节省空间 } catch (error) { console.error("❌ 解压 ZIP 文件时出错:", error.message); } } // 定时任务:每天 16:14 执行 cron.schedule(time, async () => { console.log("📌 开始下载 IP2Location 数据库..."); const success = await downloadFileWithRetry(DOWNLOAD_URL, ZIP_FILE_PATH); if (success) { await unzipFile(ZIP_FILE_PATH, DESTINATION_PATH); } }); // 让进程保持运行,防止定时任务停止 process.stdin.resume();