ytdl-server/wss.js

78 lines
2.7 KiB
JavaScript

var {WebSocketServer} = require("ws");
var qs = require("qs");
var proxyaddr = require("proxy-addr");
var child_process = require("child_process");
var {app, server} = require("./web");
var {getList, uncacheList} = require("./metalist");
var fs = require("fs");
var wss = new WebSocketServer({ server });
wss.on("connection", function(ws, req) {
req.ip = proxyaddr(req, app.get("trust proxy"));
req.query = qs.parse(req.url.substring(req.url.indexOf('?')+1));
var log = (msg, e) => console[e?'error':'log'](`[${new Date().toLocaleString()}] ${req.ip} - ${msg}`);
log("socket open: " + req.url);
var yturl = req.query.url;
if (!yturl) { ws.send(color("red", "missing url")); ws.close(); return }
var alias = req.query.alias;
if (alias) {
alias = alias.toLowerCase();
if (!/^[a-z0-9-_]{1,32}$/.test(alias)) { ws.send(color("red", "alias must be no more than 32 chars of only letters, numbers, hypens or underscores.")); ws.close(); return }
if (fs.existsSync(`aliases/${alias}`)) { ws.send(color("red", `the alias ${alias} already exists.`)); ws.close(); return }
}
var ytid = yturl.match(/https:\/\/(?:(?:www\.)?youtube\.com\/(?:watch\?v=|shorts\/)|youtu\.be\/)([A-Za-z0-9_-]{11})/)?.[1];
if (!ytid) { ws.send(color("red", "youtube url not valid")); ws.close(); return }
ws.send(color("green", "spawning yt-dlp..."));
var cp = child_process.spawn("yt-dlp", ["--format=mp4", "--max-filesize=1G", `--match-filter=duration<7200`, "--no-mtime", `https://www.youtube.com/watch?v=${ytid}`], {cwd: "videos", shell: false});
cp.on("error", error => {
log(error.message, true);
ws.send(color("red", error.message));
});
cp.stdout.on("data", data => {
var msg = data.toString().trim();
if (msg) {
log(msg);
ws.send("yt-dlp: " + color("blue", msg));
}
});
cp.stderr.on("data", data => {
var msg = data.toString().trim();
if (msg) {
log(msg, true);
ws.send(color("orange", "yt-dlp: " + color("blue", msg)));
}
});
cp.on("close", (code, signal) => {
log(`cp exit ${code} (${signal})`);
ws.send(color("green", `yt-dlp exited with code ${code}`));
let files = fs.readdirSync("videos");
let file = files.find(file => file.includes(`[${ytid}]`));
if (file) {
if (alias) fs.writeFileSync(`aliases/${alias}`, file);
let url = `https://${req.headers.host}/v/${file}`;
ws.send(`MP4 URL (<button onclick="navigator.clipboard.writeText(\`${url}\`)">Copy</button>): <a href="${url}">${url}</a>`)
} else {
ws.send(color("red", "error: couldn't find file to alias"));
}
uncacheList();
ws.close();
});
ws.on("close", () => {
log("socket closed");
cp.kill();
});
});
function color(color, text) {
return `<span style="color: ${color}">${text}</span>`;
}