Apis / server.js
darkvibe314's picture
Update server.js
5959f43 verified
Raw
History Blame Contribute Delete
4.19 kB
const express = require('express');
const yts = require('yt-search');
const { spawn, exec } = require('child_process');
const util = require('util');
const path = require('path');
const dns = require('dns');
// Fixes the ENOTFOUND error for yt-search inside Docker
dns.setDefaultResultOrder('ipv4first');
const execPromise = util.promisify(exec);
const app = express();
app.use(express.json());
app.get('/', (req, res, next) => {
if (req.accepts('html')) next();
else res.json({ status: "Online", creator: "Silent Tech API" });
});
app.use(express.static(path.join(__dirname, 'public')));
// ════════════════════════════════════════════
// πŸ” ENDPOINT 1: YT SEARCH (Using yts)
// ════════════════════════════════════════════
app.get('/api/ytsearch', async (req, res) => {
try {
const query = req.query.q;
if (!query) return res.status(400).json({ success: false, error: 'Missing parameter: q' });
const search = await yts(query);
const videos = search.videos.slice(0, 10).map(v => ({
title: v.title,
url: v.url,
duration: v.timestamp,
views: v.views.toLocaleString(),
thumbnail: v.thumbnail,
author: v.author.name
}));
res.json({ creator: 'Silent Tech', success: true, results: videos });
} catch (e) {
res.status(500).json({ success: false, error: "Search failed: " + e.message });
}
});
// ════════════════════════════════════════════
// 🎡 ENDPOINT 2: METADATA & STREAM LINKS
// ════════════════════════════════════════════
async function getVideoMeta(url) {
// Removed the broken IP flag, standard yt-dlp only
const { stdout } = await execPromise(`yt-dlp -J "${url.replace(/(["'$`\\])/g, '\\$1')}"`);
return JSON.parse(stdout);
}
app.get('/api/ytmp3', async (req, res) => {
try {
const url = req.query.url;
const meta = await getVideoMeta(url);
const host = req.headers['x-forwarded-proto'] ? `${req.headers['x-forwarded-proto']}://${req.get('host')}` : `http://${req.get('host')}`;
res.json({ success: true, title: meta.title, thumbnail: meta.thumbnail, download_url: `${host}/api/stream?url=${encodeURIComponent(url)}&type=mp3` });
} catch (e) { res.status(500).json({ success: false, error: e.message }); }
});
app.get('/api/ytmp4', async (req, res) => {
try {
const url = req.query.url;
const meta = await getVideoMeta(url);
const host = req.headers['x-forwarded-proto'] ? `${req.headers['x-forwarded-proto']}://${req.get('host')}` : `http://${req.get('host')}`;
res.json({ success: true, title: meta.title, thumbnail: meta.thumbnail, download_url: `${host}/api/stream?url=${encodeURIComponent(url)}&type=mp4` });
} catch (e) { res.status(500).json({ success: false, error: e.message }); }
});
// ════════════════════════════════════════════
// πŸ›‘οΈ INTERNAL STREAMER (Bypasses Bot IP Bans)
// ════════════════════════════════════════════
app.get('/api/stream', (req, res) => {
const { url, type } = req.query;
if (!url || !type) return res.status(400).send('Missing parameters');
const format = type === 'mp4' ? 'best[ext=mp4]' : 'bestaudio';
res.header('Content-Disposition', `attachment; filename="SilentTech.${type}"`);
if (type === 'mp4') res.header('Content-Type', 'video/mp4');
if (type === 'mp3') res.header('Content-Type', 'audio/mpeg');
const ytdlp = spawn('yt-dlp', ['-f', format, '-o', '-', url]);
ytdlp.stdout.pipe(res);
});
app.listen(7860, "0.0.0.0", () => console.log('Silent Tech Multi-API running on port 7860'));