const express = require('express'); const multer = require('multer'); const axios = require('axios'); const fs = require('fs-extra'); const FormData = require('form-data'); const path = require('path'); const { v4: uuidv4 } = require('uuid'); const app = express(); const PORT = 7860; const DATA_FILE = './data/files.json'; const MAX_CATBOX_SIZE = 200 * 1024 * 1024; // 200 MB const upload = multer({ dest: 'uploads/' }); // Load or initialize DB let db = fs.existsSync(DATA_FILE) ? JSON.parse(fs.readFileSync(DATA_FILE)) : {}; fs.ensureFileSync(DATA_FILE); app.use(express.static(path.join(__dirname, 'public'))); // Optional: Serve index.html at root app.get('/', (req, res) => { res.sendFile(path.join(__dirname, 'public/index.html')); }); // 📤 Upload to Catbox or Litterbox async function uploadToCatboxOrLitterbox(filepath, originalname) { const fileSize = (await fs.stat(filepath)).size; const formData = new FormData(); const fileStream = fs.createReadStream(filepath); if (fileSize <= MAX_CATBOX_SIZE) { formData.append('reqtype', 'fileupload'); formData.append('fileToUpload', fileStream, originalname); const res = await axios.post('https://catbox.moe/user/api.php', formData, { headers: formData.getHeaders() }); return { url: res.data, type: 'catbox' }; } else { formData.append('reqtype', 'fileupload'); formData.append('time', '72h'); formData.append('fileToUpload', fileStream, originalname); const res = await axios.post('https://litterbox.catbox.moe/resources/internals/api.php', formData, { headers: formData.getHeaders() }); return { url: res.data, type: 'litterbox' }; } } // 📤 Upload Route app.post('/upload', upload.single('file'), async (req, res) => { const file = req.file; const id = uuidv4(); try { const { url, type } = await uploadToCatboxOrLitterbox(file.path, file.originalname); db[id] = { id, filename: file.originalname, localPath: file.path, externalUrl: url, source: type, expiresAt: type === 'litterbox' ? Date.now() + 1000 * 60 * 60 * 24 * 3 : null }; fs.writeFileSync(DATA_FILE, JSON.stringify(db, null, 2)); res.json({ id, viewLink: `https://nexusv1-uploadx.hf.space/view/${id}`, externalUrl: url, source: type }); } catch (e) { res.status(500).json({ error: 'Upload failed', details: e.message }); } }); // 🔗 View Route – No Redirect app.get('/view/:id', async (req, res) => { const id = req.params.id; const file = db[id]; if (!file || !(await fs.pathExists(file.localPath))) { return res.status(404).send('File not found'); } res.download(file.localPath, file.filename); }); // 🔄 Periodic Reupload for Litterbox files setInterval(async () => { for (let id in db) { const file = db[id]; if (file.source === 'litterbox' && file.expiresAt && (file.expiresAt - Date.now() < 1000 * 60 * 60 * 6)) { try { console.log(`♻️ Reuploading ${file.filename} (${id})`); const { url, type } = await uploadToCatboxOrLitterbox(file.localPath, file.filename); db[id].externalUrl = url; db[id].source = type; db[id].expiresAt = type === 'litterbox' ? Date.now() + 1000 * 60 * 60 * 24 * 3 : null; fs.writeFileSync(DATA_FILE, JSON.stringify(db, null, 2)); console.log(`✅ Reuploaded: ${url}`); } catch (err) { console.error(`❌ Failed to reupload ${file.filename}:`, err.message); } } } }, 1000 * 60 * 30); // every 30 mins app.listen(PORT, () => console.log(`🟢 Server running on http://localhost:${PORT}`));