const express = require("express") const ytdl = require("@distube/ytdl-core") const fetch = require("node-fetch") const fs = require("fs") const path = require("path") const tmp = require("tmp") const app = express() app.use(express.json()) app.get("/download", async (req, res) => { const url = req.query.url const type = req.query.type || "video" if (!url) return res.status(400).json({ error: "url required" }) const cookieHeader = process.env.YT_COOKIE try { const info = await ytdl.getInfo(url, { requestOptions: { headers: { Cookie: cookieHeader } } }) let ryd = {} try { const r = await fetch(`https://returnyoutubedislikeapi.com/votes?videoId=${info.videoDetails.videoId}`) ryd = await r.json() } catch {} const metadata = { title: info.videoDetails.title, uploader: info.videoDetails.author.name, duration: info.videoDetails.lengthSeconds, views: info.videoDetails.viewCount, likes: info.videoDetails.likes, dislikes: ryd.dislikes || 0, videoId: info.videoDetails.videoId } const tmpFile = tmp.fileSync({ postfix: type === "audio" ? ".mp3" : ".mp4" }) const stream = ytdl.downloadFromInfo(info, { requestOptions: { headers: { Cookie: cookieHeader } }, quality: "highest", filter: type === "audio" ? "audioonly" : "audioandvideo" }) stream.pipe(fs.createWriteStream(tmpFile.name)) stream.on("end", () => { res.json({ metadata, download_url: `/file?path=${encodeURIComponent(tmpFile.name)}` }) }) } catch (e) { res.status(500).json({ error: e.message }) } }) app.get("/file", (req, res) => { const filePath = req.query.path if (!filePath || !fs.existsSync(filePath)) return res.status(404).json({ error: "file not found" }) res.download(filePath, path.basename(filePath), () => { fs.unlinkSync(filePath) }) }) app.listen(process.env.PORT || 8000, () => console.log(`Server running on port ${process.env.PORT || 8000}`))