var querystring = require("querystring"); var fs = require("fs"); var pathlib = require("path"); var formidable = require("formidable"); var basepath = "/admin/api/"; // Used in every method handler to make sure the correct arguments are provided function hasargs(query, respond, expected) { var missing = []; for (var e of expected) { if (query[e] === undefined) missing.push(e); } if (missing.length > 0) { respond("Missing arguments: "+missing.join(", ")); return false; } else { return true; } } // Method handlers are defined here var methods = { // List all slides in the slides directory list_slides: function(query, conf, req, respond) { fs.readdir(conf.slides, (err, files) => { if (err) return respond(err); respond(null, files); }); }, // Get metadata about a slide slide_meta: function(query, conf, req, respond) { if (!hasargs(query, respond, [ "slide" ])) return; var path = pathlib.join(conf.slides, query.slide); fs.stat(path, (err, stat) => { if (err || !stat.isDirectory()) return respond(path+" is not a slide."); fs.readFile(pathlib.join(path, "meta.json"), (err, res) => { if (err && err.code === "ENOENT") return respond(null, {}); else if (err) return respond(err); try { respond(null, JSON.parse(res)); } catch (err) { respond(err); } }); }); }, // Get a list of files of a slide slide_file_list: function(query, conf, req, respond) { if (!hasargs(query, respond, [ "slide" ])) return; var dir = pathlib.join(conf.slides, query.slide); fs.readdir(dir, (err, files) => { if (err) return respond(err); respond(null, { files: files }); }); }, // Get a slide's HTML slide_content: function(query, conf, req, respond) { if (!hasargs(query, respond, [ "slide" ])) return; var path = pathlib.join(conf.slides, query.slide, "index.md"); fs.readFile(path, "utf-8", (err, text) => { if (err && err.code === "ENOENT") return respond(null, { text: "" }); else if (err) return respond(err); respond(null, { text: text }); }); }, // Update a slide's HTML slide_content_update: function(query, conf, req, respond) { if (!hasargs(query, respond, [ "slide", "text" ])) return; var path = pathlib.join(conf.slides, query.slide, "index.md"); fs.writeFile(path, query.text, err => { respond(err); }); }, // Rename a file slide_file_rename: function(query, conf, req, respond) { if (!hasargs(query, respond, [ "slide", "from", "to" ])) return; var op = pathlib.join(conf.slides, query.slide, query.from); var np = pathlib.join(conf.slides, query.slide, query.to); fs.rename(op, np, err => respond(err)); }, // Delete a file slide_file_delete: function(query, conf, req, respond) { if (!hasargs(query, respond, [ "slide", "file" ])) return; var path = pathlib.join(conf.slides, query.slide, query.file); fs.unlink(path, err => respond(err)); }, // Upload a file to a slide slide_file_upload: function(query, conf, req, respond) { if (!hasargs(query, respond, [ "slide" ])) return; var form = new formidable.IncomingForm(); form.uploadDir = pathlib.join(conf.slides, query.slide); form.keepExtensions = true; form.on("fileBegin", (name, file) => { file.path = pathlib.join(form.uploadDir, file.name); }); form.parse(req, (err, fields, files) => { respond(); }); } } exports.canServe = function(parts) { // Temporary, while working on stuff return false; return methods[parts.pathname.replace(basepath, "")] !== undefined; } exports.serve = function(parts, conf, req, res) { var fn = methods[parts.pathname.replace(basepath, "")]; if (!fn) { res.writeHead(404); res.end(); return; } var query = querystring.parse(parts.query); for (var i in query) { query[i] = decodeURIComponent(query[i]); } // Better than manually doing res.end(JSON.stringify(obj)) everywhere function respond(err, obj) { var result = { obj: obj, err: err ? err.toString() : null }; if (err) res.writeHead(400); else res.writeHead(200); res.end(JSON.stringify(result)); } // Finally, call method handler fn(query, conf, req, respond); }