File size: 5,090 Bytes
8c38b3e
 
 
f94538c
9198234
8c38b3e
 
9198234
8c38b3e
 
 
 
 
 
 
 
 
 
 
9198234
8c38b3e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9198234
8c38b3e
9198234
8c38b3e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9198234
 
8c38b3e
 
 
 
 
6b9d192
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8c38b3e
6b9d192
 
 
 
 
 
 
 
 
 
 
 
 
8c38b3e
 
 
 
 
 
 
 
 
 
 
e802f17
8c38b3e
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
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
const yts = require('yt-search');
const morgan = require('morgan');
const express = require('express');
const ytdl = require('ytdl-core')

// Regex untuk mengidentifikasi URL YouTube dan Mega
const ytIdRegex = /(?:http(?:s|):\/\/|)(?:(?:www\.|)?youtube(?:\-nocookie|)\.com\/(?:shorts\/)?(?:watch\?.*(?:|\&)v=|embed\/|v\/)?|youtu\.be\/)([-_0-9A-Za-z]{11})/;

// Fungsi untuk melakukan HTTP POST request
const post = async (url, form, headers = {}) => {
    const response = await fetch(url, {
        method: 'post',
        body: new URLSearchParams(form),
        headers
    });
    return response;
};

// Fungsi untuk mengkonversi video dari YouTube
const convert = async (url, v_id, ftype, fquality, fname, token, timeExpire) => {
    let params = {
        v_id,
        ftype,
        fquality,
        fname,
        token,
        timeExpire,
        client: 'yt5s.com'
    };

    // Mengirim permintaan konversi
    let resServer = await (await post(url, params, { 'x-requested-key': 'de0cfuirtgf67a' })).json();
    let server = resServer.c_server;

    // Jika tidak ada server dan tipe file adalah mp3, kembalikan null
    if (!server && ftype === 'mp3') return server || resServer.d_url || '';

    // Mengambil data hasil konversi
    let data = await (await post(`${server}/api/json/convert`, params)).json();
    let result;

    // Memeriksa status kode hasil konversi
    if (data.statusCode === 200) result = data.result;
    while (!result) {
        let json = await (await post(`${server}/api/json/convert`, params)).json();
        if (json.statusCode === 200) {
            result = json.result;
            break;
        }
        await new Promise(resolve => setTimeout(resolve, 2000));
    }
    return result;
};

// Fungsi untuk mendownload video dari YouTube
const youtubedl = async (url) => {
    let html = await (await fetch('https://yt5s.com/en32')).text();
    let urlAjax = (html.match(/k_url_search="(.*?)"/) || [])[1];
    let urlConvert = (html.match(/k_url_convert="(.*?)"/) || [])[1];
    let json = await (await post(urlAjax, { q: url, vt: 'home' })).json();
    let video = {}, audio = {};
    if (!json?.links) throw json.mess;
    Object.values(json.links.mp4).map(({ k, size }) => video[k] = {
        quality: k,
        fileSizeH: size,
        fileSize: parseFloat(size) * (/MB$/.test(size) ? 1000 : 1),
        download: convert.bind(null, urlConvert, json.vid, 'mp4', k, json.fn, json.token, parseInt(json.timeExpires))
    });

    Object.values(json.links.mp3).map(({ key, size }) => audio[key] = {
        quality: key,
        fileSizeH: size,
        fileSize: parseFloat(size) * (/MB$/.test(size) ? 1000 : 1),
        download: convert.bind(null, urlConvert, json.vid, 'mp3', key.replace(/kbps/i, ''), json.fn, json.token, parseInt(json.timeExpires))
    });

    return {
        id: json.vid,
        title: json.title,
        thumbnail: `https://i.ytimg.com/vi/${json.vid}/0.jpg`,
        video,
        audio
    };
};

const app = express()
    .set('json spaces', 4)
    .use(morgan('dev'))
    .use(express.json())
    .all('/', (_, res) => res.send('Hello World'))
    .get('/yt', async (req, res) => {
    const host = 'https://' + req.get('host');
    try {
        let { url, type, quality, json } = req.query;
        if (!ytIdRegex.test(url)) return res.json({ message: 'Invalid URL' });
        if (!!json) {
            let ytId = ytIdRegex.exec(url)?.[1];
            if (!ytId) return res.json({ message: 'No video id found' });
            let data = await yts({ videoId: ytId });
            const downloadUrls = {
                audio: `${host}/yt?url=${url}&type=audio&quality=`,
                video: `${host}/yt?url=${url}&type=video&quality=`,
            };
            return res.json({
                ...data,
                download: downloadUrls
            });
        }
        if (!type || !/audio|video/i.test(type)) type = 'video';
        let data = await youtubedl(url).catch(e => console.log(e));
        if (!data) return res.json({ message: 'Error: link download not found' });
        type = type.toLowerCase();
        let result = quality ? Object.values(data[type]).find(x => x.quality == quality) : Object.values(data[type])[0];
        if (quality && !result) return res.json({ message: `Invalid quality: ${quality}, available quality (${Object.keys(data[type]).join('/')})` });
        if (!result) return res.json({ message: 'Error: can\'t download' });
        res.redirect(await result.download());
    } catch (e) {
        console.log(e);
        res.json({ message: e });
    }
})
    .get('/search', async (req, res) => {
        try {
            let q = req.query.q || req.query.query;
            if (!q) return res.json({ message: 'Input parameter q' });
            let data = await yts(q);
            if (!data.all[0]) return res.json({ message: 'Not found' });
            res.json(data.all);
        } catch (e) {
            console.log(e);
            res.json({ message: e });
        }
    })
    .listen(7860, () => console.log('App running on port 7860'));