const http = require('http'); const https = require('https'); const fs = require('fs'); const crypto = require('crypto'); const path = require('path'); const uuid = require('uuid-v4'); const mime = require('mime-types') global.streams = []; function fallback(req, res) { res.writeHead(400); res.end("400 Bad Request"); } function missing(req, res) { res.writeHead(400); res.end('400 Bad Request'); } function forbid(req, res) { res.writeHead(425); res.end('403 Forbidden'); } function notfound(req, res) { res.writeHead(404); res.end('404 Not Found'); } function invalid(req, res) { res.writeHead(401); res.end('400 Bad Request'); } function placeholder(req, res) { res.writeHead(302); res.end("302 Found"); } const requestListener = function(req, res) { let uid = uuid(); console.log(uid); temp[uid] = {}; req.on('end', () => { process.stdout.write("-"); delete temp[uid]; process.stdout.write("-\n"); }) let userIp; userIp = req.socket.address().address; if (req.headers["x-forwarded-for"] !== undefined) { userIp = req.headers["x-forwarded-for"] } temp[uid].parts = req.url.split("/").filter(i => i.trim() !== ""); console.log(temp[uid].parts, req.headers["user-agent"], userIp); if (temp[uid].parts.length >= 2) { if (temp[uid].parts.length >= 3 && temp[uid].parts.length < 6 && temp[uid].parts[0] === "authorize") { let song = temp[uid].parts[1].replace(/[^0-9a-f]/gm, ""); let quality = temp[uid].parts[2].replace(/[^a-z]/gm, ""); let ua try { ua = temp[uid].parts[3].replace(/[^a-z]/gm, ""); } catch (e) { ua = Buffer.from(req.headers["user-agent"]).toString("base64"); } let ip try { ip = temp[uid].parts[4].replace(/[^a-z]/gm, ""); } catch (e) { ip = Buffer.from(userIp).toString("base64"); } let id = crypto.createHash('sha512').update(crypto.randomBytes(128).toString("base64")).digest('hex'); streams.push({ song, quality: crypto.createHash('md5').update(quality).digest('hex'), id, user: Buffer.from(ua, "base64").toString(), ip: Buffer.from(ip, "base64").toString(), created: new Date() }) res.write("/stream/" + song + "/" + crypto.createHash('md5').update(quality).digest('hex') + "/" + id); res.end(); } else if (temp[uid].parts.length === 4 && temp[uid].parts[0] === "stream") { let song = temp[uid].parts[1].replace(/[^0-9a-f]/gm, ""); let quality = temp[uid].parts[2].replace(/[^0-9a-f]/gm, ""); let stream = temp[uid].parts[3].replace(/[^0-9a-f]/gm, ""); if (fs.existsSync("./files/" + song)) { console.log(fs.readdirSync("./files/" + song).filter((i) => i.split(".")[0].split("-")[1] !== undefined).map((i) => { return [ i, i.split(".")[0].split("-")[1], crypto.createHash('md5').update(i.split(".")[0].split("-")[1]).digest('hex') ] })); let selected = fs.readdirSync("./files/" + song).filter((i) => i.split(".")[0].split("-")[1] !== undefined).filter((i) => crypto.createHash('md5').update(i.split(".")[0].split("-")[1]).digest('hex') === quality); if (selected.length > 0) { if (streams.map((i) => { return i.id; }).includes(stream)) { if (streams.filter(i => i.id === stream)[0].user === req.headers["user-agent"] && streams.filter(i => i.id === stream)[0].ip === userIp && streams.filter(i => i.id === stream)[0].song === song && streams.filter(i => i.id === stream)[0].quality === quality) { streams.filter(i => i.id === stream)[0].created = new Date(); res.writeHead(200, { 'Content-Type': mime.lookup(selected[0]) || 'application/octet-stream', 'Cache-Control': 'no-cache, must-revalidate', 'Content-Disposition': 'inline', 'Expires': '0', 'Content-Length': fs.statSync("./files/" + song + "/" + selected[0]).size }); let readStream = fs.createReadStream("./files/" + song + "/" + selected[0]); readStream.pipe(res); } else { forbid(req, res); } } else { forbid(req, res); } } else { notfound(req, res); } } else { notfound(req, res); } } else { invalid(req, res); } } else { invalid(req, res); } } const server = http.createServer((req, res) => { global.temp = {}; setInterval(() => { global.streams = streams.filter(i => new Date() - i.created < 3600000); }, 10000) try { requestListener(req, res); } catch (e) { console.error(e); res.writeHead(500); res.end('500 Internal Server Error'); } }); server.listen(8875); console.log("Listening")