| const express = require("express"); |
| const axios = require("axios"); |
| const fs = require("fs"); |
| const path = require("path"); |
| const https = require("https"); |
| const crypto = require("crypto"); |
|
|
| const app = express(); |
| const PORT = 7860; |
| const DOWNLOAD_DIR = path.join(__dirname, "downloads"); |
|
|
| |
| if (!fs.existsSync(DOWNLOAD_DIR)) { |
| fs.mkdirSync(DOWNLOAD_DIR, { recursive: true }); |
| } |
|
|
| |
| const axiosInstance = axios.create({ |
| httpsAgent: new https.Agent({ rejectUnauthorized: false }), |
| timeout: 300000, |
| }); |
|
|
| |
| const generateRequestId = () => crypto.randomBytes(6).toString("hex"); |
|
|
| |
| const isValidUrl = (url) => { |
| try { |
| new URL(url); |
| return true; |
| } catch (error) { |
| return false; |
| } |
| }; |
|
|
| |
| const scheduleFileDeletion = (filePath, delay = 600000) => { |
| setTimeout(() => { |
| fs.unlink(filePath, (err) => { |
| if (!err) { |
| console.log(`β
Deleted file: ${filePath}`); |
| } |
| }); |
| }, delay); |
| }; |
|
|
| |
| const downloadFile = async (fileUrl, filePath, requestId) => { |
| let retries = 3; |
|
|
| while (retries > 0) { |
| try { |
| console.log(`β¬οΈ [${requestId}] Downloading: ${fileUrl}`); |
|
|
| const response = await axiosInstance({ |
| url: fileUrl, |
| method: "GET", |
| responseType: "stream", |
| headers: { "User-Agent": "Mozilla/5.0", "Accept": "*/*" } |
| }); |
|
|
| const totalSize = response.headers["content-length"]; |
| console.log(`π [${requestId}] Expected size: ${totalSize} bytes`); |
|
|
| const writer = fs.createWriteStream(filePath); |
| response.data.pipe(writer); |
|
|
| await new Promise((resolve, reject) => { |
| writer.on("finish", resolve); |
| writer.on("error", reject); |
| }); |
|
|
| |
| const fileSize = fs.statSync(filePath).size; |
| if (totalSize && fileSize < totalSize * 0.9) { |
| console.error(`β οΈ [${requestId}] Download incomplete: ${fileSize} bytes (expected ${totalSize} bytes)`); |
| fs.unlinkSync(filePath); |
| throw new Error("Incomplete download, retrying..."); |
| } |
|
|
| console.log(`β
[${requestId}] Download complete: ${filePath}`); |
| return true; |
|
|
| } catch (error) { |
| console.error(`β [${requestId}] Download failed: ${error.message}`); |
| retries--; |
|
|
| if (retries === 0) { |
| console.error(`β [${requestId}] All retries failed, skipping.`); |
| } |
| } |
| } |
|
|
| return false; |
| }; |
|
|
| |
| app.get("/download", async (req, res) => { |
| const fileUrl = req.query.url; |
|
|
| |
| if (!fileUrl || !isValidUrl(fileUrl)) { |
| return res.status(400).json({ error: "β Invalid or missing URL parameter" }); |
| } |
|
|
| |
| const requestId = generateRequestId(); |
| console.log(`π₯ [${requestId}] Received request for: ${fileUrl}`); |
|
|
| |
| const fileExt = path.extname(new URL(fileUrl).pathname) || ".dat"; |
| const filename = `${requestId}${fileExt}`; |
| const filePath = path.join(DOWNLOAD_DIR, filename); |
|
|
| const hostUrl = `${req.protocol}://${req.get("host")}`; |
| const servedUrl = `${hostUrl}/files/${filename}`; |
|
|
| |
| res.json({ message: "Processing in background", fileUrl: servedUrl }); |
|
|
| |
| (async () => { |
| const success = await downloadFile(fileUrl, filePath, requestId); |
| if (success) { |
| scheduleFileDeletion(filePath); |
| } |
| })(); |
| }); |
|
|
| |
| app.use("/files", express.static(DOWNLOAD_DIR)); |
|
|
| |
| const server = app.listen(PORT, () => { |
| console.log(`π Server running on port ${PORT}`); |
| }); |
|
|
| |
| server.timeout = 600000; |