diff --git a/CHANGELOG.md b/CHANGELOG.md
index 89f7c9b2..d5a6239a 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -30,6 +30,7 @@ Special thanks to the following contributors: @B1gG, @codac, @ezeholz, @khassel,
- Moved some files into better suited directories
- Update dependencies in package.json, require node >= v12, remove `rrule-alt` and `rrule`
- Update dependencies in package.json and migrate husky to v6, fix husky setup in prod environment
+- Cleaned up error handling in newsfeed and calendar modules
### Removed
diff --git a/js/node_helper.js b/js/node_helper.js
index 81d2d9d5..86ad3aa4 100644
--- a/js/node_helper.js
+++ b/js/node_helper.js
@@ -113,6 +113,32 @@ const NodeHelper = Class.extend({
}
});
+NodeHelper.checkFetchStatus = function (response) {
+ // response.status >= 200 && response.status < 300
+ if (response.ok) {
+ return response;
+ } else {
+ throw Error(response.statusText);
+ }
+};
+
+/**
+ * Look at the specified error and return an appropriate error type, that
+ * can be translated to a detailed error message
+ *
+ * @param {Error} error the error from fetching something
+ * @returns {string} the string of the detailed error message in the translations
+ */
+NodeHelper.checkFetchError = function (error) {
+ let error_type = "MODULE_ERROR_UNSPECIFIED";
+ if (error.code === "EAI_AGAIN") {
+ error_type = "MODULE_ERROR_NO_CONNECTION";
+ } else if (error.message === "Unauthorized") {
+ error_type = "MODULE_ERROR_UNAUTHORIZED";
+ }
+ return error_type;
+};
+
NodeHelper.create = function (moduleDefinition) {
return NodeHelper.extend(moduleDefinition);
};
diff --git a/modules/default/alert/notificationFx.js b/modules/default/alert/notificationFx.js
index 9589edcf..317fa75a 100644
--- a/modules/default/alert/notificationFx.js
+++ b/modules/default/alert/notificationFx.js
@@ -122,6 +122,8 @@
/**
* Dismiss the notification
+ *
+ * @param {boolean} [close] call the onClose callback at the end
*/
NotificationFx.prototype.dismiss = function (close = true) {
this.active = false;
diff --git a/modules/default/calendar/calendar.js b/modules/default/calendar/calendar.js
index e7a6fcc9..40e43ad2 100755
--- a/modules/default/calendar/calendar.js
+++ b/modules/default/calendar/calendar.js
@@ -146,11 +146,10 @@ Module.register("calendar", {
this.broadcastEvents();
}
}
- } else if (notification === "FETCH_ERROR") {
- Log.error("Calendar Error. Could not fetch calendar: " + payload.url);
+ } else if (notification === "CALENDAR_ERROR") {
+ let error_message = this.translate(payload.error_type);
+ this.error = this.translate("MODULE_CONFIG_ERROR", { MODULE_NAME: this.name, ERROR: error_message });
this.loaded = true;
- } else if (notification === "INCORRECT_URL") {
- Log.error("Calendar Error. Incorrect url: " + payload.url);
}
this.updateDom(this.config.animationSpeed);
@@ -168,6 +167,12 @@ Module.register("calendar", {
const wrapper = document.createElement("table");
wrapper.className = this.config.tableClass;
+ if (this.error) {
+ wrapper.innerHTML = this.error;
+ wrapper.className = this.config.tableClass + " dimmed";
+ return wrapper;
+ }
+
if (events.length === 0) {
wrapper.innerHTML = this.loaded ? this.translate("EMPTY") : this.translate("LOADING");
wrapper.className = this.config.tableClass + " dimmed";
diff --git a/modules/default/calendar/calendarfetcher.js b/modules/default/calendar/calendarfetcher.js
index 855257d4..805e080b 100644
--- a/modules/default/calendar/calendarfetcher.js
+++ b/modules/default/calendar/calendarfetcher.js
@@ -6,6 +6,7 @@
*/
const CalendarUtils = require("./calendarutils");
const Log = require("logger");
+const NodeHelper = require("node_helper");
const ical = require("node-ical");
const fetch = require("node-fetch");
const digest = require("digest-fetch");
@@ -62,17 +63,7 @@ const CalendarFetcher = function (url, reloadInterval, excludedEvents, maximumEn
}
fetcher
- .catch((error) => {
- fetchFailedCallback(this, error);
- scheduleTimer();
- })
- .then((response) => {
- if (response.status !== 200) {
- fetchFailedCallback(this, response.statusText);
- scheduleTimer();
- }
- return response;
- })
+ .then(NodeHelper.checkFetchStatus)
.then((response) => response.text())
.then((responseData) => {
let data = [];
@@ -87,12 +78,16 @@ const CalendarFetcher = function (url, reloadInterval, excludedEvents, maximumEn
maximumNumberOfDays
});
} catch (error) {
- fetchFailedCallback(this, error.message);
+ fetchFailedCallback(this, error);
scheduleTimer();
return;
}
this.broadcastEvents();
scheduleTimer();
+ })
+ .catch((error) => {
+ fetchFailedCallback(this, error);
+ scheduleTimer();
});
};
diff --git a/modules/default/calendar/calendarutils.js b/modules/default/calendar/calendarutils.js
index 223dfb26..7f0b14b8 100644
--- a/modules/default/calendar/calendarutils.js
+++ b/modules/default/calendar/calendarutils.js
@@ -18,8 +18,8 @@ const CalendarUtils = {
* Calculate the time correction, either dst/std or full day in cases where
* utc time is day before plus offset
*
- * @param {object} event
- * @param {Date} date
+ * @param {object} event the event which needs adjustement
+ * @param {Date} date the date on which this event happens
* @returns {number} the necessary adjustment in hours
*/
calculateTimezoneAdjustment: function (event, date) {
@@ -117,6 +117,13 @@ const CalendarUtils = {
return adjustHours;
},
+ /**
+ * Filter the events from ical according to the given config
+ *
+ * @param {object} data the calendar data from ical
+ * @param {object} config The configuration object
+ * @returns {string[]} the filtered events
+ */
filterEvents: function (data, config) {
const newEvents = [];
@@ -500,8 +507,8 @@ const CalendarUtils = {
/**
* Lookup iana tz from windows
*
- * @param msTZName
- * @returns {*|null}
+ * @param {string} msTZName the timezone name to lookup
+ * @returns {string|null} the iana name or null of none is found
*/
getIanaTZFromMS: function (msTZName) {
// Get hash entry
@@ -571,12 +578,13 @@ const CalendarUtils = {
},
/**
+ * Determines if the user defined title filter should apply
*
- * @param title
- * @param filter
- * @param useRegex
- * @param regexFlags
- * @returns {boolean|*}
+ * @param {string} title the title of the event
+ * @param {string} filter the string to look for, can be a regex also
+ * @param {boolean} useRegex true if a regex should be used, otherwise it just looks for the filter as a string
+ * @param {string} regexFlags flags that should be applied to the regex
+ * @returns {boolean} True if the title should be filtered out, false otherwise
*/
titleFilterApplies: function (title, filter, useRegex, regexFlags) {
if (useRegex) {
diff --git a/modules/default/calendar/node_helper.js b/modules/default/calendar/node_helper.js
index d544878b..5b1a8bad 100644
--- a/modules/default/calendar/node_helper.js
+++ b/modules/default/calendar/node_helper.js
@@ -40,13 +40,14 @@ module.exports = NodeHelper.create({
try {
new URL(url);
} catch (error) {
- this.sendSocketNotification("INCORRECT_URL", { id: identifier, url: url });
+ Log.error("Calendar Error. Malformed calendar url: ", url, error);
+ this.sendSocketNotification("CALENDAR_ERROR", { error_type: "MODULE_ERROR_MALFORMED_URL" });
return;
}
let fetcher;
if (typeof this.fetchers[identifier + url] === "undefined") {
- Log.log("Create new calendar fetcher for url: " + url + " - Interval: " + fetchInterval);
+ Log.log("Create new calendarfetcher for url: " + url + " - Interval: " + fetchInterval);
fetcher = new CalendarFetcher(url, fetchInterval, excludedEvents, maximumEntries, maximumNumberOfDays, auth, broadcastPastEvents, selfSignedCert);
fetcher.onReceive((fetcher) => {
@@ -55,16 +56,16 @@ module.exports = NodeHelper.create({
fetcher.onError((fetcher, error) => {
Log.error("Calendar Error. Could not fetch calendar: ", fetcher.url(), error);
- this.sendSocketNotification("FETCH_ERROR", {
+ let error_type = NodeHelper.checkFetchError(error);
+ this.sendSocketNotification("CALENDAR_ERROR", {
id: identifier,
- url: fetcher.url(),
- error: error
+ error_type
});
});
this.fetchers[identifier + url] = fetcher;
} else {
- Log.log("Use existing calendar fetcher for url: " + url);
+ Log.log("Use existing calendarfetcher for url: " + url);
fetcher = this.fetchers[identifier + url];
fetcher.broadcastEvents();
}
diff --git a/modules/default/compliments/compliments.js b/modules/default/compliments/compliments.js
index fc90527f..054a409f 100644
--- a/modules/default/compliments/compliments.js
+++ b/modules/default/compliments/compliments.js
@@ -55,7 +55,7 @@ Module.register("compliments", {
/**
* Generate a random index for a list of compliments.
*
- * @param {string[]} compliments Array with compliments.
+ * @param {string[]} compliments Array with compliments.
* @returns {number} a random index of given array
*/
randomIndex: function (compliments) {
diff --git a/modules/default/newsfeed/newsfeed.js b/modules/default/newsfeed/newsfeed.js
index 441984f4..bc033a19 100644
--- a/modules/default/newsfeed/newsfeed.js
+++ b/modules/default/newsfeed/newsfeed.js
@@ -89,8 +89,8 @@ Module.register("newsfeed", {
this.loaded = true;
this.error = null;
- } else if (notification === "INCORRECT_URL") {
- this.error = `Incorrect url: ${payload.url}`;
+ } else if (notification === "NEWSFEED_ERROR") {
+ this.error = this.translate(payload.error_type);
this.scheduleUpdateInterval();
}
},
@@ -183,9 +183,9 @@ Module.register("newsfeed", {
}
if (this.config.prohibitedWords.length > 0) {
- newsItems = newsItems.filter(function (value) {
+ newsItems = newsItems.filter(function (item) {
for (let word of this.config.prohibitedWords) {
- if (value["title"].toLowerCase().indexOf(word.toLowerCase()) > -1) {
+ if (item.title.toLowerCase().indexOf(word.toLowerCase()) > -1) {
return false;
}
}
diff --git a/modules/default/newsfeed/newsfeedfetcher.js b/modules/default/newsfeed/newsfeedfetcher.js
index d4db511d..6dd8683a 100644
--- a/modules/default/newsfeed/newsfeedfetcher.js
+++ b/modules/default/newsfeed/newsfeedfetcher.js
@@ -6,6 +6,7 @@
*/
const Log = require("logger");
const FeedMe = require("feedme");
+const NodeHelper = require("node_helper");
const fetch = require("node-fetch");
const iconv = require("iconv-lite");
@@ -84,12 +85,13 @@ const NewsfeedFetcher = function (url, reloadInterval, encoding, logFeedWarnings
};
fetch(url, { headers: headers })
+ .then(NodeHelper.checkFetchStatus)
+ .then((response) => {
+ response.body.pipe(iconv.decodeStream(encoding)).pipe(parser);
+ })
.catch((error) => {
fetchFailedCallback(this, error);
scheduleTimer();
- })
- .then((res) => {
- res.body.pipe(iconv.decodeStream(encoding)).pipe(parser);
});
};
diff --git a/modules/default/newsfeed/node_helper.js b/modules/default/newsfeed/node_helper.js
index 6fd461a1..32656a9f 100644
--- a/modules/default/newsfeed/node_helper.js
+++ b/modules/default/newsfeed/node_helper.js
@@ -27,8 +27,8 @@ module.exports = NodeHelper.create({
* Creates a fetcher for a new feed if it doesn't exist yet.
* Otherwise it reuses the existing one.
*
- * @param {object} feed The feed object.
- * @param {object} config The configuration object.
+ * @param {object} feed The feed object
+ * @param {object} config The configuration object
*/
createFetcher: function (feed, config) {
const url = feed.url || "";
@@ -38,13 +38,14 @@ module.exports = NodeHelper.create({
try {
new URL(url);
} catch (error) {
- this.sendSocketNotification("INCORRECT_URL", { url: url });
+ Log.error("Newsfeed Error. Malformed newsfeed url: ", url, error);
+ this.sendSocketNotification("NEWSFEED_ERROR", { error_type: "MODULE_ERROR_MALFORMED_URL" });
return;
}
let fetcher;
if (typeof this.fetchers[url] === "undefined") {
- Log.log("Create new news fetcher for url: " + url + " - Interval: " + reloadInterval);
+ Log.log("Create new newsfetcher for url: " + url + " - Interval: " + reloadInterval);
fetcher = new NewsfeedFetcher(url, reloadInterval, encoding, config.logFeedWarnings);
fetcher.onReceive(() => {
@@ -52,15 +53,16 @@ module.exports = NodeHelper.create({
});
fetcher.onError((fetcher, error) => {
- this.sendSocketNotification("FETCH_ERROR", {
- url: fetcher.url(),
- error: error
+ Log.error("Newsfeed Error. Could not fetch newsfeed: ", url, error);
+ let error_type = NodeHelper.checkFetchError(error);
+ this.sendSocketNotification("NEWSFEED_ERROR", {
+ error_type
});
});
this.fetchers[url] = fetcher;
} else {
- Log.log("Use existing news fetcher for url: " + url);
+ Log.log("Use existing newsfetcher for url: " + url);
fetcher = this.fetchers[url];
fetcher.setReloadInterval(reloadInterval);
fetcher.broadcastItems();
diff --git a/tests/configs/data/feed_test_rodrigoramirez.xml b/tests/configs/data/feed_test_rodrigoramirez.xml
index dbce18e9..b781a8a8 100644
--- a/tests/configs/data/feed_test_rodrigoramirez.xml
+++ b/tests/configs/data/feed_test_rodrigoramirez.xml
@@ -1,44 +1,44 @@
-
La entrada QPanel 0.13.0 aparece primero en Rodrigo Ramírez Norambuena.
]]>Para instalar esta nueva versión, la debes descargar de
La entrada QPanel 0.13.0 aparece primero en Rodrigo Ramírez Norambuena.
]]>La entrada Problema VirtualBox “starting virtual machine” … aparece primero en Rodrigo Ramírez Norambuena.
]]>Ninguna, pero ninguna maquina arrancó, se quedaban en ese mensaje. Fue de esos instantes en que sudas helado …
Con un poco de investigación fue a parar al archivo ~/.VirtualBox/VBoxSVC.log que indicaba
@@ -85,7 +85,7 @@
Fui… algo de donde agarrarse. Mirando un poco mas se trataba de problemas con los permisos al vboxdrvu, mirando indicaba que tenía 0600.
-
$ ls -lh /dev/vboxdrvu +$ ls -lh /dev/vboxdrvu crw------- 1 root root 10, 56 Sep 10 12:47 /dev/vboxdrvu
El tema es que deben estar en 0666, le cambias los permisos y eso soluciona el problema
@@ -95,24 +95,24 @@ $ ls -lh /dev/vboxdrvu crw-rw-rw- 1 root root 10, 56 Sep 10 12:47 /dev/vboxdrvu
La entrada Problema VirtualBox “starting virtual machine” … aparece primero en Rodrigo Ramírez Norambuena.
]]>La entrada Mejorando la consola interactiva de Python aparece primero en Rodrigo Ramírez Norambuena.
]]>La consola de Python funciona y cumple su cometido. Solo al tipear python te permite entrar en modo interactivo e ir probando cosas.
El punto es que a veces uno necesita ir un poco más allá. Como autocomentado de código o resaltado de sintaxis, para eso tengo dos truco que utilizo generalmente.
O lo agregas a un bashrc, zshrc o la shell que ocupes.
La entrada Mejorando la consola interactiva de Python aparece primero en Rodrigo Ramírez Norambuena.
]]>La entrada QPanel 0.12.0 con estadísticas aparece primero en Rodrigo Ramírez Norambuena.
]]>Para instalar esta nueva versión, debes visitar la siguiente URL
Si deseas colaborar con el proyecto puedes agregar nuevas sugerencias mediante un issue ó colaborar mediante mediante un Pull Request
La entrada QPanel 0.12.0 con estadísticas aparece primero en Rodrigo Ramírez Norambuena.
]]>La entrada QPanel 0.11.0 con Spy, Whisper y mas aparece primero en Rodrigo Ramírez Norambuena.
]]>Para instalar esta nueva versión, debes visitar la siguiente URL
El proyecto siempre está abierto a nuevas sugerencias las cuales puedes agregar mediante un issue.
La entrada QPanel 0.11.0 con Spy, Whisper y mas aparece primero en Rodrigo Ramírez Norambuena.
]]>La entrada Añadir Swap a un sistema aparece primero en Rodrigo Ramírez Norambuena.
]]>La memoria swap es un espacio de intercambio en disco para cuando el sistema ya no puede utilizar más memoria RAM.
El problema para mi es que algunos sistemas de maquinas virtuales no asignan por defecto un espacio para la Swap, lo que te lleva a que el sistema pueda tener crash durante la ejecución.
Para comprobar la asignación de memoria, al ejecutar el comando free nos debería mostrar como algo similar a lo siguiente
@@ -271,27 +271,27 @@ Swap: 3071 0 3071
La entrada Añadir Swap a un sistema aparece primero en Rodrigo Ramírez Norambuena.
]]>La entrada QPanel 0.10.0 con vista consolidada aparece primero en Rodrigo Ramírez Norambuena.
]]>Para instalar esta nueva versión, debes visitar la siguiente URL
El proyecto siempre está abierto a nuevas sugerencias las cuales puedes agregar mediante un issue.
La entrada QPanel 0.10.0 con vista consolidada aparece primero en Rodrigo Ramírez Norambuena.
]]>La entrada Nerdearla 2016, WebRTC Glue aparece primero en Rodrigo Ramírez Norambuena.
]]>Habían muchas cosas interesantes tanto en las presentaciones, co-working y workshop que se hubieron. Si te lo perdiste te recomiendo que estés pendiente para el proximo año.
Te podias encontrar con una nuestra como esta
La entrada Nerdearla 2016, WebRTC Glue aparece primero en Rodrigo Ramírez Norambuena.
]]>La entrada QPanel 0.9.0 aparece primero en Rodrigo Ramírez Norambuena.
]]>Para instalar esta nueva versión, debes visitar la siguiente URL
El proyecto siempre está abierto a nuevas sugerencias las cuales puedes agregar mediante un issue.
La entrada QPanel 0.9.0 aparece primero en Rodrigo Ramírez Norambuena.
]]>La entrada Mandar un email desde la shell aparece primero en Rodrigo Ramírez Norambuena.
]]>Si usas mail a secas te va pidiendo los datos para crear el correo, principalmente el body del correo. Para automatizar esto a través de un echo le pasas por pipe a mail
echo "Cuerpo del mensaje" | mail -s Asunto a@rodrigoramirez.com
La entrada Mandar un email desde la shell aparece primero en Rodrigo Ramírez Norambuena.
]]>