hai / app.js
fourmovie's picture
update
d2fc58a
const express = require('express');
const cors = require('cors');
const swaggerUi = require('swagger-ui-express');
const fs = require('fs');
const path = require('path');
const { exec } = require('child_process');
const { trackUsage, getUsageStats } = require('./utils/usageTracker');
const app = express();
app.use(cors());
app.use(express.json());
// Config
const DOMAIN = process.env.DOMAIN || 'https://rezaharis-hai.hf.space';
const AUTHOR = 'Fourstore';
const RELEASE_DATE = new Date().toISOString().split('T')[0];
// Ensure directories exist
const cookiesDir = path.join(__dirname, 'cookies');
const downloadsDir = path.join(__dirname, 'downloads');
const cookieFile = path.join(cookiesDir, 'youtube_cookie.txt');
[downloadsDir, cookiesDir].forEach(dir => {
if (!fs.existsSync(dir)) fs.mkdirSync(dir);
});
// Fix for static files with special characters
app.use('/downloads', express.static(downloadsDir, {
setHeaders: (res, filePath) => {
const ext = path.extname(filePath);
if (['.mp3', '.webm', '.mp4'].includes(ext)) {
res.setHeader('Content-Disposition', 'inline');
}
}
}));
// Swagger setup
const swaggerDocument = require('./swagger.json');
app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(swaggerDocument));
// Homepage
app.get('/', (req, res) => {
res.json({
service: "YouTube Downloader API",
author: AUTHOR,
release_date: RELEASE_DATE,
endpoints: {
download: `${DOMAIN}/download`,
downloads: `${DOMAIN}/downloads/{filename}`,
docs: `${DOMAIN}/api-docs`
}
});
});
// Download endpoint
app.post('/download', (req, res) => {
const { url, format = 'audio' } = req.body;
if (!url) return res.status(400).json({ error: "URL is required" });
trackUsage('/download');
const outputTemplate = `${downloadsDir}/%(title)s.%(ext)s`;
let command = `yt-dlp --cookies ${cookieFile} -o "${outputTemplate}" "${url}"`;
if (format === 'audio') {
command += ' -x --audio-format mp3';
}
console.log(`[EXEC] Running: ${command}`);
exec(command, (error, stdout, stderr) => {
if (error) {
console.error(`[ERROR] ${error.message}`);
return res.status(500).json({ error: "Download failed", details: stderr });
}
// Parse filename from yt-dlp output
const filenameMatch = stdout.match(/Destination: (.+)/) || stdout.match(/\[ExtractAudio\] Destination: (.+)/);
if (!filenameMatch) {
return res.status(500).json({ error: "Cannot determine output file" });
}
const localPath = filenameMatch[1];
const filename = path.basename(localPath);
const encodedFilename = encodeURIComponent(filename); // Encode untuk URL
const downloadUrl = `${DOMAIN}/downloads/${encodedFilename}`;
res.json({
success: true,
filename: filename,
download_url: downloadUrl,
direct_access: `${DOMAIN}/downloads/${filename.replace(/ /g, '%20')}`, // Alternatif encode
format: format
});
});
});
const PORT = process.env.PORT || 7860;
app.listen(PORT, () => {
console.log(`Server ready at ${DOMAIN}`);
console.log(`Downloads directory: ${downloadsDir}`);
});