Archived
1
0
Fork 0
This repository has been archived on 2022-05-09. You can view files and clone it, but cannot push or open issues or pull requests.
ytdlp-web/server.js

264 lines
8 KiB
JavaScript

const config = require("./config");
const express = require("express");
const axios = require("axios");
const url = require('url');
const ytdlp = require("yt-dlp-exec");
const utils = require("./utils");
const fs = require("fs");
let hcaptcha = (process.env.HCAPTCHA_SITEKEY)?{sitekey: process.env.HCAPTCHA_SITEKEY, secret: process.env.HCAPTCHA_SECRET}:((config.hcaptcha)?config.hcaptcha:undefined)
const bodyParser = require('body-parser');
const ffmpegstatic = require("ffmpeg-static")
const app = express();
app.use(bodyParser.urlencoded({extended:false}))
app.use(express.static(`static/`));
app.set("view engine", "ejs");
if (fs.existsSync(`logs/`)) fs.rmSync(`logs/`, {recursive: true})
if (fs.existsSync(`temp/`)) fs.rmSync(`temp/`, {recursive: true})
if (!fs.existsSync(`logs/`)) fs.mkdirSync(`logs/`);
if (!fs.existsSync(`temp/`)) fs.mkdirSync(`temp/`);
app.listen((process.env.PORT || config.port), function() {
console.log(`[ytdlp-web] Listening on port ${config.port}`);
});
app.get("/", function(req, res){
let options = {
config: config
}
if (hcaptcha) {
options.hcaptcha = hcaptcha.sitekey
}
res.render(`pages/home`, options)
});
app.post("/down", async function(req, res) {
var id = utils.generateId();
if (hcaptcha) {
let params = new url.URLSearchParams({ response: req.body.captcha, sitekey: hcaptcha.sitekey, secret: hcaptcha.secret });
let hcaptchaRes
try {
hcaptchaRes = (await axios.post('https://hcaptcha.com/siteverify', params.toString())).data;
} catch (error) {
return res.send({
success: false,
type: "error",
message: 'captcha failed'
});
}
if (!hcaptchaRes.success) {
return res.send({
success: false,
type: "error",
message: 'captcha failed'
});
}
}
if (!req.body.url) {res.send({success: false, message: "You must provide a URL to download.", type: "error"}); return;}
if (!req.body.type) {var t = "v";} else {var t = req.body.type;}
ytdlp(decodeURIComponent(req.body.url), {
dumpSingleJson: true
}).then(function(resp) {
if (resp.is_live) {
res.send({
success: false,
message: "Livestreams cannot be downloaded.",
type: "error"
});
return;
}
if (resp._type !== "video") {
console.log(resp._type);
res.send({
success: false,
message: "The type of URL is not a video/audio, this web server only supports those types of downloads.",
type: "error"
});
return;
}
if (resp.requested_downloads && resp.requested_downloads.filesize > 400000000) {
fs.writeFileSync(`logs/${id}.txt`, `[warning] This file is above 400MB and may fail if this is in a Heroku instance`);
} else if (!resp.requested_downloads && !resp.requested_formats) {
fs.writeFileSync(`logs/${id}.txt`, `[warning] We can't estimate the size of this file, but it may fail if this is in a Heroku instance`);
}
res.send({
success: true,
id: id,
meta: {
title: (resp.fulltitle || null),
thumb: (resp.thumbnail || null)
}
})
var opt = optByType(t, id);
var s = ytdlp.exec(decodeURIComponent(req.body.url), opt);
s.stdout.on("data", function(data) {
var d = data.toString().replace(/^\s+|\s+$/g, "");
if (d.includes("\\n")) d = d.split("\n")[d.split("\\n").length - 1];
if (d.includes("Deleting original file") && !d.includes(".part") && !d.includes(".f") || d.includes("Not remuxing media") || d.includes("Finished downloading playlist")) {
console.log(d);
//console.log(findFile(id))
//if (typeof findFile(id) == "object") cleanup(id);
fs.writeFileSync(`logs/${id}.txt`, `[ytdlp-web] Complete`);
removeLogs(id);
return;
}
if (d !== "") fs.writeFileSync(`logs/${id}.txt`, d);
});
s.stderr.on("data", function(data) {
var d = data.toString().replace(/^\s+|\s+$/g, "");
if (typeof d !== "string") {console.log(d);}
console.log(d);
if (d.includes("already is in target")) {fs.writeFileSync(`logs/${id}.txt`, `[ytdlp-web] Complete`); removeLogs(id); return;}
if (d.startsWith("WARNING: ") || d.includes("Opening") || d.includes(";") || d.includes("throttling") || d.includes("frame") || d.includes("hls") || d.includes("Duration") || d.includes(",") || d.includes("Postprocessing")) return;
console.log(d);
if (d == "") return;
if (d !== "") fs.writeFileSync(`logs/${id}.txt`, d);
removeLogs(id);
cleanup(id);
if (findFile(id) !== null) fs.unlinkSync(`temp/${findFile(id)}`);
})
}).catch(function(err) {
res.send({
success: false,
type: "error",
message: err.message
});
})
})
app.post("/logs", function(req, res) {
if (!req.body.id) res.redirect("/");
try {
var f = fs.readFileSync(`logs/${req.body.id}.txt`).toString();
if (!f.toLowerCase().includes("error")) {
var t = f.split("[")[f.split("[").length - 1].split("]")[0];
if (t == "download") t = "downloading to server"
var m = f.split("] ").slice(f.split("] ").length - 1)[0]
res.send({
success: true,
type: t,
message: m
})
} else {
var t = "error";
res.send({
success: false,
type: t,
message: `${f.substring(7)} <b>This is a <a rel="noreferer nofollow" href="https://github.com/yt-dlp/yt-dlp/issues/">yt-dlp</a> issue. Not a site issue. </b>`
});
}
} catch(err) {
if (err.code == "ENOENT") {
res.send({
success: true,
type: `ytdlp-web`,
message: `Creating log file... [Process ID: ${req.query.id}]`
});
} else {
res.send({
success: true,
type: "error",
message: err.message
});
}
}
});
app.get("/f", function(req, res) {
if (req.query.id) {
var f = findFile(req.query.id);
if (typeof f == "string") {
res.download(`temp/${f}`, function(e) {
if (e) {res.send(e.message);} else {fs.unlinkSync(`temp/${f}`);}
})
} else if (f == null) {
res.redirect("/");
} else if (typeof f == "object") {
cleanup(req.query.id);
var f = findFile(req.query.id);
if (typeof f == "string") {
res.download(`temp/${f}`, function(e) {
if (e) {res.send(e.message); res.end()} else {fs.unlinkSync(`temp/${f}`);}
})
} else {
res.send("Couldn't extract data due to findFile() not returning a valid response. Report this to the issue tracker.");
}
} else {
res.send("Couldn't extract data due to findFile() not returning a valid response. Report this to the issue tracker.");
}
} else {
res.redirect("/");
}
})
function removeLogs(id) {
setTimeout(function() {
if (fs.existsSync(`logs/${id}.txt`)) fs.unlinkSync(`logs/${id}.txt`)
}, 10000)
}
function optByType(t, id) {
switch(t) {
case "v":
var h = {
noCallHome: true,
preferFreeFormats: true,
output: `${__dirname}/temp/${id}.%(ext)s`,
remux: `mp4`,
noWarning: "",
ppa: `Merger: -strict -2`
}
return h;
case "a":
var h = {
noCallHome: true,
preferFreeFormats: true,
output: `${__dirname}/temp/${id}.%(ext)s`,
extractAudio: true,
audioFormat: `mp3`,
noWarning: "",
}
return h;
}
}
function findFile(id) {
var r = [];
for (var c in fs.readdirSync(`temp/`)) {
if (fs.readdirSync(`temp/`)[c].split(".")[0] == id) {r.push(fs.readdirSync(`temp/`)[c]);} else {continue}
}
if (r.length == 1) return r[0];
if (r.length == 0) return null;
return r;
}
function cleanup(id) {
if (typeof findFile(id) !== "object") {return true;}
else {
var r = findFile(id);
var ll = "";
var llfs = 0;
for (var c in r) {
var size = fs.statSync(`temp/${r[c]}`).size;
if (size > llfs) {
llfs = size;
ll = r[c];
} else {continue;}
}
for (var c in r) {
if (r[c] !== ll) {fs.unlinkSync(`temp/${r[c]}`);}
}
return true;
}
}