File size: 4,194 Bytes
7497a2c
5959f43
7497a2c
 
 
6cf3361
 
5959f43
6cf3361
7497a2c
 
 
 
6cf3361
 
5959f43
 
6cf3361
 
7497a2c
 
 
5959f43
7497a2c
 
 
 
 
 
5959f43
 
7497a2c
5959f43
 
 
 
 
7497a2c
 
 
 
2056762
7497a2c
 
 
 
5959f43
7497a2c
5959f43
 
 
 
 
 
7497a2c
 
 
5959f43
 
7497a2c
5959f43
 
7497a2c
 
 
 
 
5959f43
 
7497a2c
5959f43
 
7497a2c
 
2056762
5959f43
7497a2c
 
 
 
 
 
5959f43
7497a2c
 
 
5959f43
7497a2c
 
 
5959f43
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
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'));