summaryrefslogtreecommitdiff
path: root/modules/subd-buien/subd-buien.js
diff options
context:
space:
mode:
Diffstat (limited to 'modules/subd-buien/subd-buien.js')
-rw-r--r--modules/subd-buien/subd-buien.js133
1 files changed, 133 insertions, 0 deletions
diff --git a/modules/subd-buien/subd-buien.js b/modules/subd-buien/subd-buien.js
new file mode 100644
index 0000000..1d599eb
--- /dev/null
+++ b/modules/subd-buien/subd-buien.js
@@ -0,0 +1,133 @@
+const cmn = require("../$common.js");
+const fs = require("fs");
+const express = require("express");
+const child_process = require("child_process");
+
+// NOTE:
+// This module expects a buienradar-store instance in the 'buienradar-store'
+// directory within this module's directory. The database therein should be
+// named 'db', and the background image should be stored under key 'mode'
+// (which should probably be the cmpref).
+
+
+// cb : (err, status, stdout : Buffer) -> ()
+function runDbmanage(bdir, args, cb) {
+ const options = {
+ cwd: bdir,
+ stdio: ["inherit", "pipe", "inherit"],
+ timeout: 5000, // milliseconds
+ };
+ const proc = child_process.spawn(bdir + "/dbmanage", args, options);
+
+ const outbufs = [];
+ proc.stdout.on("data", data => {
+ outbufs.push(data);
+ });
+
+ let callbackInvoked = false;
+
+ proc.on("error", err => {
+ if (callbackInvoked) return;
+ callbackInvoked = true;
+ cb(err, null, null);
+ });
+
+ proc.on("exit", (code, sig) => {
+ if (callbackInvoked) return;
+ callbackInvoked = true;
+ if (code != null) cb(null, code, Buffer.concat(outbufs));
+ else cb("Process terminated by signal", null, null);
+ });
+}
+
+// cb : (err, frames : [String]) -> ()
+function getFramesList(bdir, cb) {
+ runDbmanage(bdir, ["list", bdir + "/db"], (err, status, out) => {
+ if (err) cb(err, null);
+ else if (status != 0) cb("Error getting list of frames from DB", null);
+ else cb(null, out.toString("utf8").trim().split("\n").filter(s => s != "mode"));
+ });
+}
+
+// cb : (err, pngs : Buffer) -> ()
+function getFramesPng(bdir, stamps, cb) {
+ runDbmanage(bdir, ["getmultiple", bdir + "/db"].concat(stamps), (err, status, out) => {
+ if (err) { cb(err, null); return; }
+ if (status != 0) { cb("Error getting frames from DB", null); return; }
+ cb(null, out);
+
+ // const pngs = [];
+
+ // let cursor = 0;
+ // while (cursor < out.length) {
+ // let pnglen = out.readBigUInt64LE(cursor);
+ // if (Number(pnglen) != pnglen) {
+ // cb("PNG too large", null);
+ // return;
+ // }
+ // pnglen = Number(pnglen);
+
+ // pngs.push(out.slice(cursor + 8, cursor + 8 + pnglen));
+ // cursor += 8 + pnglen;
+ // }
+
+ // cb(null, pngs);
+ });
+}
+
+// cb : (err, present : Bool) -> ()
+function checkFramePresent(bdir, stamp, cb) {
+ runDbmanage(bdir, ["has", bdir + "/db", stamp], (err, status, out) => {
+ if (err) { cb(err, null); return; }
+ if (status == 1) { cb("Error getting status from DB", null); return; }
+ if (status == 0) cb(null, true);
+ else cb(null, false);
+ });
+}
+
+module.exports = function (app, io, moddir) {
+ const buiendir = moddir + "/buienradar-store";
+ console.log(`buien: Using buienradar-store directory '${buiendir}'`);
+
+ const router = express.Router();
+
+ router.get("/", function (req, res) {
+ res.sendFile(moddir + "/index.html");
+ });
+
+ router.get("/api/list/json", function (req, res) {
+ getFramesList(buiendir, (err, frames) => {
+ if (err) {
+ console.log(err);
+ res.sendStatus(500);
+ } else res.json(frames);
+ });
+ });
+
+ router.get("/api/images", function (req, res) {
+ const url = new URL(req.url, `https://${req.headers.host}`);
+ const stamps = url.searchParams.getAll("s").flatMap(s => s.split(","));
+ getFramesPng(buiendir, stamps, (err, buf) => {
+ if (err) {
+ console.log(err);
+ res.sendStatus(500);
+ } else res.send(buf);
+ });
+ });
+
+ router.get("/api/has/:stamp", function (req, res) {
+ checkFramePresent(buiendir, req.params.stamp, (err, present) => {
+ if (err) {
+ console.log(err);
+ res.sendStatus(500);
+ } else if (present) res.sendStatus(200);
+ else res.sendStatus(404);
+ });
+ });
+
+ app.use(function (req, res, next) {
+ if (req.subdomains.length && req.subdomains[req.subdomains.length - 1] == "buien") {
+ router.handle(req, res, next);
+ } else next();
+ });
+};