var fs = require("fs"); var http = require("http"); var crypto = require("crypto"); var pathlib = require("path"); var urllib = require("url"); var index = fs.readFileSync("index.html"); var conf = JSON.parse(fs.readFileSync("conf.json")); function error(res, err) { console.trace(err); res.end(err.toString()); } // The individual slide function Slide(dir) { var self = {}; self.dir = dir; function serve(parts, res) { if (parts.pathname === "/slide") { fs.createReadStream(pathlib.join(dir, "index.html")) .on("error", err => error(res, err)) .pipe(res); } else { fs.createReadStream(pathlib.join(dir, parts.pathname)) .on("error", err => error(res, err)) .pipe(res); } } self.serve = function(parts, res) { try { serve(parts, res); } catch (err) { if (err.code && err.code === "ENOENT") res.writeHead(404); error(res, err); } } return self; } // The slideshow, whose job it is to manage all slides // and tell the client whether it has to update or not function Slideshow(dir, changeInterval) { var self = {}; var currentSlide = null; var awaiters = []; self.serve = function(req, res) { var parts = urllib.parse(req.url); // /: Send the base site to the client if (parts.pathname === "/") { res.end(index); // /await: long polling, request won't end before a new slide comes } else if (parts.pathname === "/await") { awaiters.push(res); // There's a current slide: leave serving files up to the slide } else if (currentSlide) { currentSlide.serve(parts, res); // There's no current slide show } else { res.end("No current slideshow."); } } // This function starts the slideshow and goes through the slides // one by one. When done, it starts again by calling this function again. function init() { var slides = fs.readdirSync(dir) .sort() .map(file => Slide(pathlib.join(dir, file))); var slideIndex = 0; currentSlide = slides[slideIndex]; var interval = setInterval(() => { slideIndex += 1; // Go to the next slide, or restart if (slideIndex >= slides.length) { clearInterval(interval); init(); } else { currentSlide = slides[slideIndex]; } // End all awaiting connections to notify slide change awaiters.forEach(res => res.end()); }, changeInterval); } init(); return self; } var slideshow = Slideshow(conf.slides, conf.interval); http.createServer((req, res) => { slideshow.serve(req, res); }).listen(conf.port);