UNPKG

@vreden/youtube_scraper

Version:

A simple YouTube video downloader for audio and video formats with resolusi and quality.

212 lines (199 loc) 6.17 kB
const axios = require("axios"); const yts = require("yt-search"); const { createDecipheriv } = require('crypto') function getYouTubeVideoId(url) { const regex = /(?:https?:\/\/)?(?:www\.)?(?:youtube\.com\/(?:[^\/\n\s]+\/\S+\/|v\/|embed\/|user\/[^\/\n\s]+\/)?(?:watch\?v=|v%3D|embed%2F|video%2F)?|youtu\.be\/|youtube\.com\/watch\?v=|youtube\.com\/embed\/|youtube\.com\/v\/|youtube\.com\/shorts\/|youtube\.com\/playlist\?list=)([a-zA-Z0-9_-]{11})/; const match = url.match(regex); return match ? match[1] : null; } const audio = [92, 128, 256, 320] const video = [144, 360, 480, 720, 1080] const hexcode = (hex) => Buffer.from(hex, 'hex') const decode = (enc) => { try { const secret_key = 'C5D58EF67A7584E4A29F6C35BBC4EB12' const data = Buffer.from(enc, 'base64') const iv = data.slice(0, 16) const content = data.slice(16) const key = hexcode(secret_key) const decipher = createDecipheriv('aes-128-cbc', key, iv) let decrypted = Buffer.concat([decipher.update(content), decipher.final()]) return JSON.parse(decrypted.toString()) } catch (error) { throw new Error(error.message) } } async function savetube(link, quality, value) { try { const cdn = (await axios.get("https://media.savetube.me/api/random-cdn")).data.cdn const infoget = (await axios.post('https://' + cdn + '/v2/info', { 'url': link },{ headers: { 'User-Agent': 'Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Mobile Safari/537.36', 'Referer': 'https://yt.savetube.me/1kejjj1?id=362796039' } })).data const info = decode(infoget.data) const response = (await axios.post('https://' + cdn + '/download', { 'downloadType': value, 'quality': `${quality}`, 'key': info.key },{ headers: { 'Content-Type': 'application/json', 'User-Agent': 'Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Mobile Safari/537.36', 'Referer': 'https://yt.savetube.me/start-download?from=1kejjj1%3Fid%3D362796039' } })).data return { status: true, quality: `${quality}${value === "audio" ? "kbps" : "p"}`, availableQuality: value === "audio" ? audio : video, url: response.data.downloadUrl, filename: `${info.title} (${quality}${value === "audio" ? "kbps).mp3" : "p).mp4"}` } } catch (error) { console.error("Converting error:", error) return { status: false, message: "Converting error" } } } async function ytmp3(link, formats = 128) { const videoId = getYouTubeVideoId(link); const format = audio.includes(Number(formats)) ? Number(formats) : 128 if (!videoId) { return { status: false, message: "Invalid YouTube URL" }; } try { let url = "https://youtube.com/watch?v=" + videoId let data = await yts(url); let response = await savetube(url, format, "audio") return { status: true, creator: "@vreden/youtube_scraper", metadata: data.all[0], download: response }; } catch (error) { console.log(error) return { status: false, message: error.response ? `HTTP Error: ${error.response.status}` : error.message }; } } async function ytmp4(link, formats = 360) { const videoId = getYouTubeVideoId(link); const format = video.includes(Number(formats)) ? Number(formats) : 360 if (!videoId) { return { status: false, message: "Invalid YouTube URL" }; } try { let url = "https://youtube.com/watch?v=" + videoId let data = await yts(url); let response = await savetube(url, format, "video") return { status: true, creator: "@vreden/youtube_scraper", metadata: data.all[0], download: response }; } catch (error) { console.log(error) return { status: false, message: error.response ? `HTTP Error: ${error.response.status}` : error.message }; } } async function transcript(link) { try { const response = await axios.get('https://ytb2mp4.com/api/fetch-transcript', { params: { 'url': link }, headers: { 'User-Agent': 'Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.0.0 Mobile Safari/537.36', 'Referer': 'https://ytb2mp4.com/youtube-transcript' } }); return { status: true, creator: "@vreden/youtube_scraper", transcript: response.data.transcript } } catch (error) { return { status: false, message: error.message } } } async function ytdlv2(link, format) { try { const result = await axios.get(`https://ytdl.vreden.web.id/metadata?url=${link}`) const videoId = getYouTubeVideoId(link); const url = "https://youtube.com/watch?v=" + videoId const mp3 = await ytmp3(url, format) const mp4 = await ytmp4(url, format) result.data.downloads.audio = mp3.download.url result.data.downloads.video = mp4.download.url return { status: true, creator: "@vreden/youtube_scraper", ...result.data } } catch (error) { return { status: false, message: error.message } } } async function search(teks) { try { let data = await yts(teks); return { status: true, creator: "@vreden/youtube_scraper", results: data.all }; } catch (error) { return { status: false, message: error.message }; } } async function channel(teks) { try { let result = await axios.get(`https://ytdl.vreden.web.id/channel/${teks}`) return { status: true, creator: "@vreden/youtube_scraper", ...result.data }; } catch (error) { return { status: false, message: error.message }; } } module.exports = { search, ytmp3, ytmp4, transcript, ytdlv2, channel };