├── MMM-syslog.js ├── README.md └── node_helper.js /MMM-syslog.js: -------------------------------------------------------------------------------- 1 | /* global Module */ 2 | 3 | /* Magic Mirror 4 | * Module: MMM-syslog 5 | * 6 | * By Paul-Vincent Roll http://paulvincentroll.com 7 | * MIT Licensed. 8 | */ 9 | 10 | Module.register('MMM-syslog',{ 11 | 12 | messages: [], 13 | 14 | defaults: { 15 | max: 5, 16 | format: false, 17 | types: { 18 | INFO: "dimmed", 19 | WARNING: "normal", 20 | ERROR: "bright" 21 | }, 22 | icons: { 23 | INFO: "info", 24 | WARNING: "exclamation", 25 | ERROR: "exclamation-triangle" 26 | }, 27 | shortenMessage: false, 28 | alert: true 29 | }, 30 | 31 | getStyles: function () { 32 | return ["font-awesome.css"]; 33 | }, 34 | 35 | getScripts: function() { 36 | return ["moment.js"]; 37 | }, 38 | 39 | start: function() { 40 | this.sendSocketNotification("CONNECT", {max: this.config.max, logFile: this.file('logs.json')}); 41 | Log.info("Starting module: " + this.name); 42 | moment.locale(config.language); 43 | 44 | //Update DOM every minute so that the time of the call updates and calls get removed after a certain time 45 | setInterval(() => { 46 | this.updateDom(); 47 | }, 60000); 48 | }, 49 | 50 | socketNotificationReceived: function(notification, payload) { 51 | if(notification === "NEW_MESSAGE"){ 52 | if (this.config.alert && !payload.silent) { 53 | this.sendNotification("SHOW_ALERT", {type: "notification", title: payload.type, message: payload.message}); 54 | } 55 | this.messages.push(payload); 56 | while(this.messages.length > this.config.max){ 57 | this.messages.shift(); 58 | } 59 | this.updateDom(3000); 60 | } 61 | }, 62 | 63 | getDom: function() { 64 | 65 | var wrapper = document.createElement("div"); 66 | if(this.config.title !== false){ 67 | var title = document.createElement("header"); 68 | title.innerHTML = this.config.title || this.name; 69 | wrapper.appendChild(title); 70 | } 71 | var logs = document.createElement("table"); 72 | 73 | for (var i = this.messages.length - 1; i >= 0; i--) { 74 | //Create callWrapper 75 | var callWrapper = document.createElement("tr"); 76 | callWrapper.classList.add("normal"); 77 | 78 | var iconCell = document.createElement("td"); 79 | var icon = document.createElement("i"); 80 | if(this.config.icons.hasOwnProperty(this.messages[i].type)){ 81 | icon.classList.add("fa", "fa-fw", "fa-" + this.config.icons[this.messages[i].type]); 82 | } 83 | else { 84 | icon.classList.add("fa", "fa-fw", "fa-question"); 85 | } 86 | if(this.config.types.hasOwnProperty(this.messages[i].type)){ 87 | icon.classList.add(this.config.types[this.messages[i].type]); 88 | } 89 | 90 | iconCell.classList.add("small"); 91 | 92 | iconCell.appendChild(icon); 93 | callWrapper.appendChild(iconCell); 94 | 95 | var message = this.messages[i].message; 96 | if(this.config.shortenMessage && message.length > this.config.shortenMessage){ 97 | message = message.slice(0, this.config.shortenMessage) + "…"; 98 | } 99 | //Set caller of row 100 | var caller = document.createElement("td"); 101 | caller.innerHTML = " " + message; 102 | caller.classList.add("title", "small", "align-left"); 103 | if(this.config.types.hasOwnProperty(this.messages[i].type)){ 104 | caller.classList.add(this.config.types[this.messages[i].type]); 105 | } 106 | callWrapper.appendChild(caller); 107 | 108 | //Set time of row 109 | var time = document.createElement("td"); 110 | time.innerHTML = this.config.format ? moment(this.messages[i].timestamp).format(this.config.format) : moment(this.messages[i].timestamp).fromNow(); 111 | time.classList.add("time", "light", "xsmall"); 112 | callWrapper.appendChild(time); 113 | 114 | //Add to logs 115 | logs.appendChild(callWrapper); 116 | } 117 | wrapper.appendChild(logs); 118 | return wrapper; 119 | } 120 | }); 121 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # MMM-syslog 2 | Notification API Module for MagicMirror2 3 | 4 | ## Example 5 | 6 | ![](https://forum.magicmirror.builders/uploads/files/1473753516823-syslog-icon-4.jpg) 7 | 8 | ## Dependencies 9 | * An installation of [MagicMirror2](https://github.com/MichMich/MagicMirror) 10 | 11 | ## Installation 12 | 1. Clone this repo into `~/MagicMirror/modules` directory. 13 | 2. Configure your `~/MagicMirror/config/config.js`: 14 | 15 | ``` 16 | { 17 | module: 'MMM-syslog', 18 | position: 'top_right', 19 | config: { 20 | ... 21 | } 22 | } 23 | ``` 24 | 25 | ## Config Options 26 | | **Option** | **Default** | **Description** | 27 | | --- | --- | --- | 28 | | `max` | `5` | How many messages should be displayed on the screen. | 29 | | `format` | `false` | Displays relative date format, for absolute date format provide a string like `'DD:MM HH:mm'` [All Options](http://momentjs.com/docs/#/displaying/format/) | 30 | | `types` | `{INFO: "dimmed", WARNING: "normal", ERROR: "bright"}` | Object with message types and their css class. | 31 | | `shortenMessage` | `false` | After how many characters the message should be cut. Default: show all. | 32 | | `alert` | `true` | Display notification? | 33 | 34 | ## How to Use 35 | Make an http get request like: 36 | http://MIRROR_IP:MIRROR_PORT/syslog?type=INFO&message=YOUR_MESSAGE&silent=true : no notification 37 | 38 | -------------------------------------------------------------------------------- /node_helper.js: -------------------------------------------------------------------------------- 1 | /* global Module */ 2 | 3 | /* Magic Mirror 4 | * Module: MMM-syslog 5 | * 6 | * By Paul-Vincent Roll http://paulvincentroll.com 7 | * MIT Licensed. 8 | */ 9 | 10 | const NodeHelper = require("node_helper"); 11 | const url = require("url"); 12 | const fs = require("fs"); 13 | 14 | module.exports = NodeHelper.create({ 15 | 16 | start: function() { 17 | this.expressApp.get('/syslog', (req, res) => { 18 | 19 | var query = url.parse(req.url, true).query; 20 | var message = query.message; 21 | var type = query.type; 22 | var silent = query.silent || false; 23 | 24 | if (message == null && type == null){ 25 | res.send({"status": "failed", "error": "No message and type given."}); 26 | } 27 | else if (message == null){ 28 | res.send({"status": "failed", "error": "No message given."}); 29 | } 30 | else if (type == null) { 31 | res.send({"status": "failed", "error": "No type given."}); 32 | } 33 | else { 34 | var log = {"type": type, "message": message, "silent": silent, "timestamp": new Date()}; 35 | res.send({"status": "success", "payload": log}); 36 | this.sendSocketNotification("NEW_MESSAGE", log); 37 | this.storeLog(log); 38 | } 39 | }); 40 | }, 41 | 42 | socketNotificationReceived: function(notification, payload) { 43 | if(notification === "CONNECT"){ 44 | this.logFile = payload.logFile; 45 | this.loadLogs(); 46 | this.max = payload.max; 47 | } 48 | }, 49 | 50 | storeLog: function(log){ 51 | this.logs.push(log); 52 | while(this.logs.length > this.max){ 53 | this.logs.shift(); 54 | } 55 | fs.writeFileSync(this.logFile, JSON.stringify({"messages": this.logs}), 'utf8'); 56 | }, 57 | 58 | loadLogs: function(){ 59 | if(this.fileExists(this.logFile)){ 60 | this.logs = JSON.parse(fs.readFileSync(this.logFile, 'utf8')).messages; 61 | for(var i = 0; i < this.logs.length; i++){ 62 | this.sendSocketNotification("NEW_MESSAGE", this.logs[i]); 63 | } 64 | } else { 65 | this.logs = []; 66 | } 67 | }, 68 | 69 | fileExists: function(path){ 70 | try { 71 | return fs.statSync(path).isFile(); 72 | } catch(e) { 73 | console.log("No log file found."); 74 | return false; 75 | } 76 | } 77 | 78 | }); --------------------------------------------------------------------------------