Merge pull request #2089 from rejas/newsfeed

Cleaned up newsfeed module code
This commit is contained in:
Michael Teeuw
2020-07-17 16:28:44 +02:00
committed by GitHub
13 changed files with 63 additions and 87 deletions

View File

@@ -18,6 +18,7 @@ _This release is scheduled to be released on 2020-10-01._
### Updated ### Updated
- Change incorrect weather.js default properties. - Change incorrect weather.js default properties.
- Cleaned up newsfeed module.
### Deleted ### Deleted

View File

@@ -84,11 +84,11 @@ Module.register("newsfeed", {
// Override dom generator. // Override dom generator.
getDom: function () { getDom: function () {
var wrapper = document.createElement("div"); const wrapper = document.createElement("div");
if (this.config.feedUrl) { if (this.config.feedUrl) {
wrapper.className = "small bright"; wrapper.className = "small bright";
wrapper.innerHTML = this.translate("configuration_changed"); wrapper.innerHTML = this.translate("MODULE_CONFIG_CHANGED", { MODULE_NAME: "Newsfeed" });
return wrapper; return wrapper;
} }
@@ -99,7 +99,7 @@ Module.register("newsfeed", {
if (this.newsItems.length > 0) { if (this.newsItems.length > 0) {
// this.config.showFullArticle is a run-time configuration, triggered by optional notifications // this.config.showFullArticle is a run-time configuration, triggered by optional notifications
if (!this.config.showFullArticle && (this.config.showSourceTitle || this.config.showPublishDate)) { if (!this.config.showFullArticle && (this.config.showSourceTitle || this.config.showPublishDate)) {
var sourceAndTimestamp = document.createElement("div"); const sourceAndTimestamp = document.createElement("div");
sourceAndTimestamp.className = "newsfeed-source light small dimmed"; sourceAndTimestamp.className = "newsfeed-source light small dimmed";
if (this.config.showSourceTitle && this.newsItems[this.activeItem].sourceTitle !== "") { if (this.config.showSourceTitle && this.newsItems[this.activeItem].sourceTitle !== "") {
@@ -157,22 +157,22 @@ Module.register("newsfeed", {
} }
if (!this.config.showFullArticle) { if (!this.config.showFullArticle) {
var title = document.createElement("div"); const title = document.createElement("div");
title.className = "newsfeed-title bright medium light" + (!this.config.wrapTitle ? " no-wrap" : ""); title.className = "newsfeed-title bright medium light" + (!this.config.wrapTitle ? " no-wrap" : "");
title.innerHTML = this.newsItems[this.activeItem].title; title.innerHTML = this.newsItems[this.activeItem].title;
wrapper.appendChild(title); wrapper.appendChild(title);
} }
if (this.isShowingDescription) { if (this.isShowingDescription) {
var description = document.createElement("div"); const description = document.createElement("div");
description.className = "newsfeed-desc small light" + (!this.config.wrapDescription ? " no-wrap" : ""); description.className = "newsfeed-desc small light" + (!this.config.wrapDescription ? " no-wrap" : "");
var txtDesc = this.newsItems[this.activeItem].description; const txtDesc = this.newsItems[this.activeItem].description;
description.innerHTML = this.config.truncDescription ? (txtDesc.length > this.config.lengthDescription ? txtDesc.substring(0, this.config.lengthDescription) + "..." : txtDesc) : txtDesc; description.innerHTML = this.config.truncDescription ? (txtDesc.length > this.config.lengthDescription ? txtDesc.substring(0, this.config.lengthDescription) + "..." : txtDesc) : txtDesc;
wrapper.appendChild(description); wrapper.appendChild(description);
} }
if (this.config.showFullArticle) { if (this.config.showFullArticle) {
var fullArticle = document.createElement("iframe"); const fullArticle = document.createElement("iframe");
fullArticle.className = ""; fullArticle.className = "";
fullArticle.style.width = "100vw"; fullArticle.style.width = "100vw";
// very large height value to allow scrolling // very large height value to allow scrolling
@@ -332,17 +332,6 @@ Module.register("newsfeed", {
}, this.config.updateInterval); }, this.config.updateInterval);
}, },
/* capitalizeFirstLetter(string)
* Capitalizes the first character of a string.
*
* argument string string - Input string.
*
* return string - Capitalized output string.
*/
capitalizeFirstLetter: function (string) {
return string.charAt(0).toUpperCase() + string.slice(1);
},
resetDescrOrFullArticleAndTimer: function () { resetDescrOrFullArticleAndTimer: function () {
this.isShowingDescription = this.config.showDescription; this.isShowingDescription = this.config.showDescription;
this.config.showFullArticle = false; this.config.showFullArticle = false;
@@ -356,7 +345,7 @@ Module.register("newsfeed", {
}, },
notificationReceived: function (notification, payload, sender) { notificationReceived: function (notification, payload, sender) {
var before = this.activeItem; const before = this.activeItem;
if (notification === "ARTICLE_NEXT") { if (notification === "ARTICLE_NEXT") {
this.activeItem++; this.activeItem++;
if (this.activeItem >= this.newsItems.length) { if (this.activeItem >= this.newsItems.length) {

View File

@@ -1,10 +1,9 @@
/* Magic Mirror /* Magic Mirror
* Fetcher * Node Helper: Newsfeed - NewsfeedFetcher
* *
* By Michael Teeuw https://michaelteeuw.nl * By Michael Teeuw https://michaelteeuw.nl
* MIT Licensed. * MIT Licensed.
*/ */
const Log = require("../../../js/logger.js"); const Log = require("../../../js/logger.js");
const FeedMe = require("feedme"); const FeedMe = require("feedme");
const request = require("request"); const request = require("request");
@@ -17,39 +16,39 @@ const iconv = require("iconv-lite");
* attribute reloadInterval number - Reload interval in milliseconds. * attribute reloadInterval number - Reload interval in milliseconds.
* attribute logFeedWarnings boolean - Log warnings when there is an error parsing a news article. * attribute logFeedWarnings boolean - Log warnings when there is an error parsing a news article.
*/ */
const NewsfeedFetcher = function (url, reloadInterval, encoding, logFeedWarnings) {
const self = this;
let reloadTimer = null;
let items = [];
let fetchFailedCallback = function () {};
let itemsReceivedCallback = function () {};
var Fetcher = function (url, reloadInterval, encoding, logFeedWarnings) {
var self = this;
if (reloadInterval < 1000) { if (reloadInterval < 1000) {
reloadInterval = 1000; reloadInterval = 1000;
} }
var reloadTimer = null;
var items = [];
var fetchFailedCallback = function () {};
var itemsReceivedCallback = function () {};
/* private methods */ /* private methods */
/* fetchNews() /* fetchNews()
* Request the new items. * Request the new items.
*/ */
var fetchNews = function () { const fetchNews = function () {
clearTimeout(reloadTimer); clearTimeout(reloadTimer);
reloadTimer = null; reloadTimer = null;
items = []; items = [];
var parser = new FeedMe(); const parser = new FeedMe();
parser.on("item", function (item) { parser.on("item", function (item) {
var title = item.title; const title = item.title;
var description = item.description || item.summary || item.content || ""; let description = item.description || item.summary || item.content || "";
var pubdate = item.pubdate || item.published || item.updated || item["dc:date"]; const pubdate = item.pubdate || item.published || item.updated || item["dc:date"];
var url = item.url || item.link || ""; const url = item.url || item.link || "";
if (title && pubdate) { if (title && pubdate) {
var regex = /(<([^>]+)>)/gi; const regex = /(<([^>]+)>)/gi;
description = description.toString().replace(regex, ""); description = description.toString().replace(regex, "");
items.push({ items.push({
@@ -77,10 +76,17 @@ var Fetcher = function (url, reloadInterval, encoding, logFeedWarnings) {
scheduleTimer(); scheduleTimer();
}); });
var nodeVersion = Number(process.version.match(/^v(\d+\.\d+)/)[1]); const nodeVersion = Number(process.version.match(/^v(\d+\.\d+)/)[1]);
var headers = { "User-Agent": "Mozilla/5.0 (Node.js " + nodeVersion + ") MagicMirror/" + global.version + " (https://github.com/MichMich/MagicMirror/)", "Cache-Control": "max-age=0, no-cache, no-store, must-revalidate", Pragma: "no-cache" }; const opts = {
headers: {
"User-Agent": "Mozilla/5.0 (Node.js " + nodeVersion + ") MagicMirror/" + global.version + " (https://github.com/MichMich/MagicMirror/)",
"Cache-Control": "max-age=0, no-cache, no-store, must-revalidate",
Pragma: "no-cache"
},
encoding: null
};
request({ uri: url, encoding: null, headers: headers }) request(url, opts)
.on("error", function (error) { .on("error", function (error) {
fetchFailedCallback(self, error); fetchFailedCallback(self, error);
scheduleTimer(); scheduleTimer();
@@ -92,7 +98,7 @@ var Fetcher = function (url, reloadInterval, encoding, logFeedWarnings) {
/* scheduleTimer() /* scheduleTimer()
* Schedule the timer for the next update. * Schedule the timer for the next update.
*/ */
var scheduleTimer = function () { const scheduleTimer = function () {
clearTimeout(reloadTimer); clearTimeout(reloadTimer);
reloadTimer = setTimeout(function () { reloadTimer = setTimeout(function () {
fetchNews(); fetchNews();
@@ -148,4 +154,4 @@ var Fetcher = function (url, reloadInterval, encoding, logFeedWarnings) {
}; };
}; };
module.exports = Fetcher; module.exports = NewsfeedFetcher;

View File

@@ -7,7 +7,7 @@
const NodeHelper = require("node_helper"); const NodeHelper = require("node_helper");
const validUrl = require("valid-url"); const validUrl = require("valid-url");
const Fetcher = require("./fetcher.js"); const NewsfeedFetcher = require("./newsfeedfetcher.js");
const Log = require("../../../js/logger"); const Log = require("../../../js/logger");
module.exports = NodeHelper.create({ module.exports = NodeHelper.create({
@@ -32,37 +32,35 @@ module.exports = NodeHelper.create({
* attribute config object - A configuration object containing reload interval in milliseconds. * attribute config object - A configuration object containing reload interval in milliseconds.
*/ */
createFetcher: function (feed, config) { createFetcher: function (feed, config) {
var self = this; const url = feed.url || "";
const encoding = feed.encoding || "UTF-8";
var url = feed.url || ""; const reloadInterval = feed.reloadInterval || config.reloadInterval || 5 * 60 * 1000;
var encoding = feed.encoding || "UTF-8";
var reloadInterval = feed.reloadInterval || config.reloadInterval || 5 * 60 * 1000;
if (!validUrl.isUri(url)) { if (!validUrl.isUri(url)) {
self.sendSocketNotification("INCORRECT_URL", url); this.sendSocketNotification("INCORRECT_URL", url);
return; return;
} }
var fetcher; let fetcher;
if (typeof self.fetchers[url] === "undefined") { if (typeof this.fetchers[url] === "undefined") {
Log.log("Create new news fetcher for url: " + url + " - Interval: " + reloadInterval); Log.log("Create new news fetcher for url: " + url + " - Interval: " + reloadInterval);
fetcher = new Fetcher(url, reloadInterval, encoding, config.logFeedWarnings); fetcher = new NewsfeedFetcher(url, reloadInterval, encoding, config.logFeedWarnings);
fetcher.onReceive(function (fetcher) { fetcher.onReceive(() => {
self.broadcastFeeds(); this.broadcastFeeds();
}); });
fetcher.onError(function (fetcher, error) { fetcher.onError((fetcher, error) => {
self.sendSocketNotification("FETCH_ERROR", { this.sendSocketNotification("FETCH_ERROR", {
url: fetcher.url(), url: fetcher.url(),
error: error error: error
}); });
}); });
self.fetchers[url] = fetcher; this.fetchers[url] = fetcher;
} else { } else {
Log.log("Use existing news fetcher for url: " + url); Log.log("Use existing news fetcher for url: " + url);
fetcher = self.fetchers[url]; fetcher = this.fetchers[url];
fetcher.setReloadInterval(reloadInterval); fetcher.setReloadInterval(reloadInterval);
fetcher.broadcastItems(); fetcher.broadcastItems();
} }

View File

@@ -1,3 +0,0 @@
{
"configuration_changed": "Die Konfigurationsoptionen für das Newsfeed-Modul haben sich geändert. \nBitte überprüfen Sie die Dokumentation."
}

View File

@@ -1,3 +0,0 @@
{
"configuration_changed": "The configuration options for the newsfeed module have changed.\nPlease check the documentation."
}

View File

@@ -1,3 +0,0 @@
{
"configuration_changed": "Las opciones de configuración para el módulo de suministro de noticias han cambiado. \nVerifique la documentación."
}

View File

@@ -1,3 +0,0 @@
{
"configuration_changed": "Les options de configuration du module newsfeed ont changé. \nVeuillez consulter la documentation."
}

View File

@@ -1,29 +1,15 @@
const expect = require("chai").expect; const expect = require("chai").expect;
describe("Functions into modules/default/newsfeed/newsfeed.js", function () { describe("Functions into modules/default/newsfeed/newsfeed.js", function () {
// Fake for use by newsletter.js
Module = {}; Module = {};
Module.definitions = {}; Module.definitions = {};
Module.register = function (name, moduleDefinition) { Module.register = function (name, moduleDefinition) {
Module.definitions[name] = moduleDefinition; Module.definitions[name] = moduleDefinition;
}; };
// load newsfeed.js before(function () {
require("../../../modules/default/newsfeed/newsfeed.js"); // load newsfeed.js
require("../../../modules/default/newsfeed/newsfeed.js");
describe("capitalizeFirstLetter", function () {
const words = {
rodrigo: "Rodrigo",
"123m": "123m",
"magic mirror": "Magic mirror",
",a": ",a",
ñandú: "Ñandú",
".!": ".!"
};
Object.keys(words).forEach((word) => {
it(`for ${word} should return ${words[word]}`, function () {
expect(Module.definitions.newsfeed.capitalizeFirstLetter(word)).to.equal(words[word]);
});
});
}); });
}); });

View File

@@ -26,6 +26,8 @@
"NW": "NW", "NW": "NW",
"NNW": "NNW", "NNW": "NNW",
"MODULE_CONFIG_CHANGED": "Die Konfigurationsoptionen für das {MODULE_NAME} Modul haben sich geändert. \nBitte überprüfen Sie die Dokumentation.",
"UPDATE_NOTIFICATION": "Aktualisierung für MagicMirror² verfügbar.", "UPDATE_NOTIFICATION": "Aktualisierung für MagicMirror² verfügbar.",
"UPDATE_NOTIFICATION_MODULE": "Aktualisierung für das {MODULE_NAME} Modul verfügbar.", "UPDATE_NOTIFICATION_MODULE": "Aktualisierung für das {MODULE_NAME} Modul verfügbar.",
"UPDATE_INFO_SINGLE": "Die aktuelle Installation ist {COMMIT_COUNT} Commit hinter dem {BRANCH_NAME} Branch.", "UPDATE_INFO_SINGLE": "Die aktuelle Installation ist {COMMIT_COUNT} Commit hinter dem {BRANCH_NAME} Branch.",

View File

@@ -26,6 +26,8 @@
"NW": "NW", "NW": "NW",
"NNW": "NNW", "NNW": "NNW",
"MODULE_CONFIG_CHANGED": "The configuration options for the {MODULE_NAME} module have changed.\nPlease check the documentation.",
"UPDATE_NOTIFICATION": "MagicMirror² update available.", "UPDATE_NOTIFICATION": "MagicMirror² update available.",
"UPDATE_NOTIFICATION_MODULE": "Update available for {MODULE_NAME} module.", "UPDATE_NOTIFICATION_MODULE": "Update available for {MODULE_NAME} module.",
"UPDATE_INFO_SINGLE": "The current installation is {COMMIT_COUNT} commit behind on the {BRANCH_NAME} branch.", "UPDATE_INFO_SINGLE": "The current installation is {COMMIT_COUNT} commit behind on the {BRANCH_NAME} branch.",

View File

@@ -26,6 +26,8 @@
"NW": "NO", "NW": "NO",
"NNW": "NNO", "NNW": "NNO",
"MODULE_CONFIG_CHANGED": "Las opciones de configuración para el módulo {MODULE_NAME} han cambiado. \nVerifique la documentación.",
"UPDATE_NOTIFICATION": "MagicMirror² actualización disponible.", "UPDATE_NOTIFICATION": "MagicMirror² actualización disponible.",
"UPDATE_NOTIFICATION_MODULE": "Disponible una actualización para el módulo {MODULE_NAME}.", "UPDATE_NOTIFICATION_MODULE": "Disponible una actualización para el módulo {MODULE_NAME}.",
"UPDATE_INFO_SINGLE": "Tu actual instalación está {COMMIT_COUNT} commit cambios detrás de la rama {BRANCH_NAME}.", "UPDATE_INFO_SINGLE": "Tu actual instalación está {COMMIT_COUNT} commit cambios detrás de la rama {BRANCH_NAME}.",

View File

@@ -26,6 +26,8 @@
"NW": "NO", "NW": "NO",
"NNW": "NNO", "NNW": "NNO",
"MODULE_CONFIG_CHANGED": "Les options de configuration du module {MODULE_NAME} ont changé. \nVeuillez consulter la documentation.",
"UPDATE_NOTIFICATION": "Une mise à jour de MagicMirror² est disponible", "UPDATE_NOTIFICATION": "Une mise à jour de MagicMirror² est disponible",
"UPDATE_NOTIFICATION_MODULE": "Une mise à jour est disponible pour le module {MODULE_NAME} .", "UPDATE_NOTIFICATION_MODULE": "Une mise à jour est disponible pour le module {MODULE_NAME} .",
"UPDATE_INFO_SINGLE": "L'installation actuelle est {COMMIT_COUNT} commit en retard sur la branche {BRANCH_NAME} .", "UPDATE_INFO_SINGLE": "L'installation actuelle est {COMMIT_COUNT} commit en retard sur la branche {BRANCH_NAME} .",