Browse Source

[add][Closes #27] favicon generator

B Thibault 8 years ago
parent
commit
8990eb60b3
3 changed files with 114 additions and 5 deletions
  1. 2 1
      package.json
  2. 101 0
      srv/src/faviconWriter.js
  3. 11 4
      srv/src/httpServ.js

+ 2 - 1
package.json

@@ -10,7 +10,8 @@
     "crypto",
     "node-file-cache",
     "memory-cache",
-    "sleep"
+    "sleep",
+    "jimp"
 
   ] ,"repository": {
     "type": "git",

+ 101 - 0
srv/src/faviconWriter.js

@@ -0,0 +1,101 @@
+const fs = require('fs')
+    ,Jimp = require('jimp')
+
+    ,COLOR_MESSAGE = 0x96AFFFFF
+    ,COLOR_HIGHLIGHT = 0x4C9689FF //rgb(76, 150, 137);
+
+var font = {}
+    ,FONTNAME = __dirname +"/../res/absender1.fnt";
+
+FONTNAME = Jimp.FONT_SANS_128_BLACK;
+
+function FaviconWriter() { }
+
+function loadFont(fontname, cb) {
+    if (!font[fontname]) {
+        Jimp.loadFont(fontname).then((f) => {
+            font[fontname] = f;
+            cb(f);
+        });
+    } else {
+        cb(font[fontname]);
+    }
+}
+
+function centerText(image, font, fontHeight, color, text) {
+    var imageWidth = image.bitmap.width
+        ,imageHeight = image.bitmap.height
+        ,fontCalc = new Jimp(imageWidth, imageHeight)
+        ,fontPos = {
+            minX: Infinity
+            ,maxX: -Infinity
+            ,minY: Infinity
+            ,maxY: -Infinity
+        };
+
+    fontCalc.print(font, 0, 0, text);
+    for (var i =0; i < imageWidth; i++)
+        for (var j =0; j < imageHeight; j++)
+            if (fontCalc.getPixelColor(i, j) !== 0x00000000) {
+                fontCalc.setPixelColor(color, i, j);
+                fontPos.minX = Math.min(fontPos.minX, i);
+                fontPos.maxX = Math.max(fontPos.maxX, i);
+                fontPos.minY = Math.min(fontPos.minY, j);
+                fontPos.maxY = Math.max(fontPos.maxY, j);
+            }
+    var margin = 10;
+    fontPos.minX = Math.max(fontPos.minX -margin, 0);
+    fontPos.maxX = Math.min(fontPos.maxX +margin, imageWidth);
+    var sourceWidth = fontPos.maxX -fontPos.minX
+        ,sourceHeight = fontPos.maxY -fontPos.minY
+        ,zoomFactor = Math.min(imageWidth /sourceWidth, fontHeight /sourceHeight);
+
+    fontCalc.crop(fontPos.minX, fontPos.minY, sourceWidth, sourceHeight);
+    fontCalc.scale(zoomFactor);
+
+    image.blit(
+        fontCalc,       // font printed image
+        (imageWidth/2) - (sourceWidth *zoomFactor /2),  // target x
+        (imageHeight/2) -(sourceHeight *zoomFactor /2), // target y
+        0,   // source x
+        0,   // source y
+        sourceWidth *zoomFactor,    // source width
+        sourceHeight *zoomFactor);  // source height
+    return image;
+}
+
+function newImage(text, color, cb) {
+    loadFont(FONTNAME, (font) => {
+        centerText(new Jimp(256, 256), font, 236, color, text)
+            .getBuffer(Jimp.MIME_PNG, (_, buf) => {
+                cb(buf);
+            });
+    });
+}
+
+/**
+ * @param {number} unreadHi
+ * @param {number} unread
+ * @param {http.ServerResponse} res
+**/
+FaviconWriter.write = function(unreadHi, unread, cb) {
+    if (unreadHi) {
+        newImage('!' +unreadHi, COLOR_HIGHLIGHT, cb);
+    } else if (unread) {
+        newImage('' +unread, COLOR_MESSAGE, cb);
+    } else {
+        try {
+            var stat = fs.statSync("public/favicon_ok.png")
+            res.setHeader('Content-Length', stat.size);
+            res.writeHeader("200");
+            fs.createReadStream("public/favicon_ok.png").pipe(res, { end: true });
+        } catch (e) {
+            console.error("WTF cannot find favicon_ok.png in public dir");
+            res.writeHeader("404", "Not Found");
+            res.end();
+        }
+    }
+};
+
+module.exports = { FaviconWriter: FaviconWriter };
+

+ 11 - 4
srv/src/httpServ.js

@@ -5,7 +5,8 @@ var http = require("http")
     ,config = require("../config.js")
     ,sessionManager = require("./session.js").SessionManager
     ,Slack = require("./slack.js").Slack
-    ,slackManager = require("./slackManager.js").SlackManager;
+    ,slackManager = require("./slackManager.js").SlackManager
+    ,FaviconWriter = require("./faviconWriter.js").FaviconWriter;
 
 function Server(port) {
     var ctx = this;
@@ -104,10 +105,16 @@ Server.prototype.onRequest = function(req, res) {
         sessionManager.saveSession(req.session);
         return; // async pipe will close when finished
     } else if (req.urlObj.match(["favicon.png"])) {
-        // TODO
-        res.writeHeader("200");
-        require('fs').createReadStream("public/favicon_ok.png").pipe(res, { end: true });
+        if (!config.isDebug)
+            res.setHeader('Cache-Control', 'private, max-age=' +15 * 60);
+        var unreadHi = (req.urlObj.queryTokens.h && req.urlObj.queryTokens.h[0]) ? parseInt(req.urlObj.queryTokens.h[0], 10) : 0
+            ,unread = (req.urlObj.queryTokens.m && req.urlObj.queryTokens.m[0]) ? parseInt(req.urlObj.queryTokens.m[0], 10) : 0;
+        FaviconWriter.write(unreadHi, unread, (buf) => {
+            res.writeHeader("200");
+            res.end(buf);
+        });
         sessionManager.saveSession(req.session);
+        return;
     } else {
         // Api / dynamic content
         var apiSuccess = false;