const express = require("express"), fs = require("fs"), path = require("path") var app = express() var PORT = process.env.PORT || 8080 var directory = process.env.FILES_DIR var pubDir = path.join(directory, 'public') function humanFileSize(bytes, si = false, dp = 1) { const thresh = si ? 1000 : 1024; if (Math.abs(bytes) < thresh) { return bytes + ' B'; } const units = si ? ['kB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'] : ['KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB']; let u = -1; const r = 10 ** dp; do { bytes /= thresh; ++u; } while (Math.round(Math.abs(bytes) * r) / r >= thresh && u < units.length - 1); return bytes.toFixed(dp) + ' ' + units[u]; } if (!directory) { console.error("No directory specified! Please specify one using the environment variable FILES_DIR.") return } const videoFormats = ["mp4", "mkv"] app.use(express.static(directory)) app.use(express.static(pubDir)) app.use(express.static(path.join(__dirname, 'resources'))) app.listen(PORT, () => { console.log("Now listening on PORT: " + PORT) }) app.get("/watch/*", (req, res) => { res.setHeader("Content-Type", "text/html") var video = req.params[0] var absPath = path.join(directory, video) if (!fs.existsSync(absPath)) { absPath = path.join(pubDir, video) } var html = fs.readFileSync(path.join(__dirname, 'resources/watch.html')).toString() html = html.replaceAll("{VID_PATH}", video) var vidTitle = video.substring(video.lastIndexOf('/') + 1, video.lastIndexOf('.')) var vidStats = fs.statSync(absPath) html = html.replaceAll("{TITLE}", vidTitle) html = html.replaceAll("{VID_INFO}", `Size: ${humanFileSize(vidStats.size)}`) html = html.replaceAll("{BACK}", "/" + video.substring(0, video.lastIndexOf("/"))) res.send(html) }) app.get("/video/*", (req, res) => { var video = req.params[0] var vidPath = path.join(directory, video) if (!fs.existsSync(vidPath)) { vidPath = path.join(pubDir, video) } const range = req.headers.range const videoPath = vidPath; const videoSize = fs.statSync(videoPath).size const chunkSize = 1 * 1e6; const start = Number(range.replace(/\D/g, "")) const end = Math.min(start + chunkSize, videoSize - 1) const contentLength = end - start + 1; const headers = { "Content-Range": `bytes ${start}-${end}/${videoSize}`, "Accept-Ranges": "bytes", "Content-Length": contentLength, "Content-Type": "video/mkv" } res.writeHead(206, headers) const stream = fs.createReadStream(videoPath, { start, end }) stream.pipe(res) }) app.get("/*", (req, res) => { var file = req.params[0] var absPath = path.join(pubDir, file) var html = fs.readFileSync(path.join(__dirname, 'resources/base.html')).toString() res.setHeader('Content-Type', 'text/html') var addedHTML = "" html = html.replace("{TITLE}", '/' + file) try { var dirContents = fs.readdirSync(absPath) var dirStats = fs.statSync(absPath) } catch (error) { html = html.replace("{CONTENT}", "

404: not found!

Go to root") res.send(html) return } addedHTML += `

${dirContents.length} Files

`.trim() if (file != '') { addedHTML += 'Parent Directory
' } var dirs = [] var ogFolder = file addedHTML += "" html = html.replace("{CONTENT}", addedHTML) res.write(html, () => { res.end() }) }) process.on('uncaughtException', (err, origin) => { fs.writeSync( process.stderr.fd, `Caught exception: ${err}\n` + `Exception origin: ${origin}`, ); });