Create index.js
Browse files
index.js
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
|
| 2 |
+
const express = require("express")
|
| 3 |
+
const ytdl = require("@distube/ytdl-core")
|
| 4 |
+
const fetch = require("node-fetch")
|
| 5 |
+
const fs = require("fs")
|
| 6 |
+
const path = require("path")
|
| 7 |
+
const tmp = require("tmp")
|
| 8 |
+
|
| 9 |
+
const app = express()
|
| 10 |
+
app.use(express.json())
|
| 11 |
+
|
| 12 |
+
app.get("/download", async (req, res) => {
|
| 13 |
+
const url = req.query.url
|
| 14 |
+
const type = req.query.type || "video"
|
| 15 |
+
if (!url) return res.status(400).json({ error: "url required" })
|
| 16 |
+
|
| 17 |
+
const cookieHeader = process.env.YT_COOKIE
|
| 18 |
+
|
| 19 |
+
try {
|
| 20 |
+
const info = await ytdl.getInfo(url, {
|
| 21 |
+
requestOptions: { headers: { Cookie: cookieHeader } }
|
| 22 |
+
})
|
| 23 |
+
|
| 24 |
+
let ryd = {}
|
| 25 |
+
try {
|
| 26 |
+
const r = await fetch(`https://returnyoutubedislikeapi.com/votes?videoId=${info.videoDetails.videoId}`)
|
| 27 |
+
ryd = await r.json()
|
| 28 |
+
} catch {}
|
| 29 |
+
|
| 30 |
+
const metadata = {
|
| 31 |
+
title: info.videoDetails.title,
|
| 32 |
+
uploader: info.videoDetails.author.name,
|
| 33 |
+
duration: info.videoDetails.lengthSeconds,
|
| 34 |
+
views: info.videoDetails.viewCount,
|
| 35 |
+
likes: info.videoDetails.likes,
|
| 36 |
+
dislikes: ryd.dislikes || 0,
|
| 37 |
+
videoId: info.videoDetails.videoId
|
| 38 |
+
}
|
| 39 |
+
|
| 40 |
+
const tmpFile = tmp.fileSync({ postfix: type === "audio" ? ".mp3" : ".mp4" })
|
| 41 |
+
const stream = ytdl.downloadFromInfo(info, {
|
| 42 |
+
requestOptions: { headers: { Cookie: cookieHeader } },
|
| 43 |
+
quality: "highest",
|
| 44 |
+
filter: type === "audio" ? "audioonly" : "audioandvideo"
|
| 45 |
+
})
|
| 46 |
+
|
| 47 |
+
stream.pipe(fs.createWriteStream(tmpFile.name))
|
| 48 |
+
stream.on("end", () => {
|
| 49 |
+
res.json({
|
| 50 |
+
metadata,
|
| 51 |
+
download_url: `/file?path=${encodeURIComponent(tmpFile.name)}`
|
| 52 |
+
})
|
| 53 |
+
})
|
| 54 |
+
} catch (e) {
|
| 55 |
+
res.status(500).json({ error: e.message })
|
| 56 |
+
}
|
| 57 |
+
})
|
| 58 |
+
|
| 59 |
+
app.get("/file", (req, res) => {
|
| 60 |
+
const filePath = req.query.path
|
| 61 |
+
if (!filePath || !fs.existsSync(filePath)) return res.status(404).json({ error: "file not found" })
|
| 62 |
+
res.download(filePath, path.basename(filePath), () => {
|
| 63 |
+
fs.unlinkSync(filePath)
|
| 64 |
+
})
|
| 65 |
+
})
|
| 66 |
+
|
| 67 |
+
app.listen(process.env.PORT || 8000, () => console.log(`Server running on port ${process.env.PORT || 8000}`))
|