Allow the subscription to multiple news feeds in one newsfeed instance.

This commit is contained in:
Michael Teeuw
2016-04-20 14:39:38 +02:00
parent 3b1f1a41dc
commit fd500ac411
5 changed files with 192 additions and 45 deletions

View File

@@ -56,7 +56,13 @@ var config = {
module: 'newsfeed', module: 'newsfeed',
position: 'bottom_bar', position: 'bottom_bar',
config: { config: {
feedUrl: 'http://www.nytimes.com/services/xml/rss/nyt/HomePage.xml', feeds: [
{
title: "New York Times",
url: "http://www.nytimes.com/services/xml/rss/nyt/HomePage.xml"
}
],
showSourceTitle: true,
showPublishDate: true showPublishDate: true
} }
}, },

View File

@@ -14,6 +14,18 @@ modules: [
// The config property is optional. // The config property is optional.
// If no config is set, an example calendar is shown. // If no config is set, an example calendar is shown.
// See 'Configuration options' for more information. // See 'Configuration options' for more information.
feeds: [
{
title: "New York Times",
url: "http://www.nytimes.com/services/xml/rss/nyt/HomePage.xml",
},
{
title: "BBC
",
url: "http://feeds.bbci.co.uk/news/video_and_audio/news_front_page/rss.xml?edition=uk",
},
]
} }
} }
] ]
@@ -35,12 +47,25 @@ The following properties can be configured:
<tbody> <tbody>
<tr> <tr>
<td><code>feedUrl</code></td> <td><code>feeds</code></td>
<td>The url of the feed used for the headlines.<br> <td>An array of feed urls that will be used as source.<br>
<br><b>Default value:</b> <code>'http://www.nytimes.com/services/xml/rss/nyt/HomePage.xml'</code> More info about this object can be found below.
<br><b>Default value:</b> <code>[
{
title: "New York Times",
url: "http://www.nytimes.com/services/xml/rss/nyt/HomePage.xml",
}
]</code>
</td> </td>
</tr> </tr>
<tr>
<td><code>showSourceTitle</code></td>
<td>Display the title of the source.<br>
<br><b>Possible values:</b> <code>true</code> or <code>false</code>
<br><b>Default value:</b> <code>true</code>
</td>
</tr>
<tr> <tr>
<td><code>showPublishDate</code></td> <td><code>showPublishDate</code></td>
<td>Display the publish date of an headline.<br> <td>Display the publish date of an headline.<br>
@@ -77,9 +102,40 @@ The following properties can be configured:
<br><b>Default value:</b> <code>2000</code> (2.5 seconds) <br><b>Default value:</b> <code>2000</code> (2.5 seconds)
</td> </td>
</tr> </tr>
</tbody>
</table>
The `feeds` property contains an array with multiple objects. These objects have the following properties:
<table width="100%">
<!-- why, markdown... -->
<thead>
<tr>
<th>Option</th>
<th width="100%">Description</th>
</tr>
<thead>
<tbody>
<tr>
<td><code>title</code></td>
<td>The name of the feed source to be displayed above the news items.<br>
<br>This property is optional.
</td>
</tr>
<tr>
<td><code>url</code></td>
<td>The url of the feed used for the headlines.<br>
<br><b>Example:</b> <code>'http://www.nytimes.com/services/xml/rss/nyt/HomePage.xml'</code>
</td>
</tr>
<tr> <tr>
<td><code>encoding</code></td> <td><code>encoding</code></td>
<td>The encoding of the news feed.<br> <td>The encoding of the news feed.<br>
<br>This property is optional.
<br><b>Possible values:</b><code>'UTF-8'</code>, <code>'ISO-8859-1'</code>, etc ... <br><b>Possible values:</b><code>'UTF-8'</code>, <code>'ISO-8859-1'</code>, etc ...
<br><b>Default value:</b> <code>'UTF-8'</code> <br><b>Default value:</b> <code>'UTF-8'</code>
</td> </td>

View File

@@ -46,11 +46,13 @@ var Fetcher = function(url, reloadInterval, encoding) {
var regex = /(<([^>]+)>)/ig; var regex = /(<([^>]+)>)/ig;
description = description.replace(regex, ""); description = description.replace(regex, "");
items.push({ if (item.title && description && item.pubdate) {
title: item.title, items.push({
description: description, title: item.title,
pubdate: item.pubdate, description: description,
}); pubdate: item.pubdate,
});
}
}); });
parser.on("end", function() { parser.on("end", function() {

View File

@@ -11,13 +11,19 @@ Module.register("newsfeed",{
// Default module config. // Default module config.
defaults: { defaults: {
feedUrl: "http://www.nytimes.com/services/xml/rss/nyt/HomePage.xml", feeds: [
{
title: "New York Times",
url: "http://www.nytimes.com/services/xml/rss/nyt/HomePage.xml",
encoding: "UTF-8" //ISO-8859-1
}
],
showSourceTitle: true,
showPublishDate: true, showPublishDate: true,
showDescription: false, showDescription: false,
reloadInterval: 5 * 60 * 1000, // every 5 minutes reloadInterval: 5 * 60 * 1000, // every 5 minutes
updateInterval: 10 * 1000, updateInterval: 10 * 1000,
animationSpeed: 2.5 * 1000, animationSpeed: 2.5 * 1000,
encoding: "UTF-8" //ISO-8859-1
}, },
// Define required scripts. // Define required scripts.
@@ -36,21 +42,20 @@ Module.register("newsfeed",{
this.loaded = false; this.loaded = false;
this.activeItem = 0; this.activeItem = 0;
this.fetchNews(); this.registerFeeds();
}, },
// Override socket notification handler. // Override socket notification handler.
socketNotificationReceived: function(notification, payload) { socketNotificationReceived: function(notification, payload) {
if (notification === "NEWS_ITEMS") { if (notification === "NEWS_ITEMS") {
if (payload.url === this.config.feedUrl) { this.generateFeed(payload);
this.newsItems = payload.items;
if (!this.loaded) {
this.scheduleUpdateInterval();
}
this.loaded = true; if (!this.loaded) {
this.scheduleUpdateInterval();
} }
this.loaded = true;
} }
}, },
@@ -58,12 +63,11 @@ Module.register("newsfeed",{
getDom: function() { getDom: function() {
var wrapper = document.createElement("div"); var wrapper = document.createElement("div");
// wrapper.className = "small"; if (this.config.feedUrl) {
// for (var n in this.newsItems) { wrapper.className = "small bright";
// var item = this.newsItems[n]; wrapper.innerHTML = "The configuration options for the newsfeed module have changed.<br>Please check the documentation.";
// wrapper.innerHTML += item.title + '<br>'; return wrapper;
// } }
// return wrapper;
if (this.activeItem >= this.newsItems.length) { if (this.activeItem >= this.newsItems.length) {
this.activeItem = 0; this.activeItem = 0;
@@ -71,12 +75,16 @@ Module.register("newsfeed",{
if (this.newsItems.length > 0) { if (this.newsItems.length > 0) {
if (this.config.showPublishDate) { if (this.config.showSourceTitle || this.config.showPublishDate) {
var timestamp = document.createElement("div"); var sourceAndTimestamp = document.createElement("div");
timestamp.className = "light small dimmed"; sourceAndTimestamp.className = "light small dimmed";
timestamp.innerHTML = this.capitalizeFirstLetter(moment(new Date(this.newsItems[this.activeItem].pubdate)).fromNow() + ":");
//timestamp.innerHTML = this.config.feedUrl; if (this.config.showSourceTitle && this.newsItems[this.activeItem].sourceTitle !== '') sourceAndTimestamp.innerHTML = this.newsItems[this.activeItem].sourceTitle;
wrapper.appendChild(timestamp); if (this.config.showSourceTitle && this.newsItems[this.activeItem].sourceTitle !== '' && this.config.showPublishDate) sourceAndTimestamp.innerHTML += ', ';
if (this.config.showPublishDate) sourceAndTimestamp.innerHTML += moment(new Date(this.newsItems[this.activeItem].pubdate)).fromNow();
if (this.config.showSourceTitle && this.newsItems[this.activeItem].sourceTitle !== '' || this.config.showPublishDate) sourceAndTimestamp.innerHTML += ':';
wrapper.appendChild(sourceAndTimestamp);
} }
var title = document.createElement("div"); var title = document.createElement("div");
@@ -99,16 +107,78 @@ Module.register("newsfeed",{
return wrapper; return wrapper;
}, },
/* fetchNews(compliments) /* registerFeeds()
* Requests new data from news proxy. * registers the feeds to be used by the backend.
*/ */
fetchNews: function() {
Log.log("Add news feed to fetcher: " + this.config.feedUrl); registerFeeds: function() {
this.sendSocketNotification("ADD_FEED", { for (var f in this.config.feeds) {
url: this.config.feedUrl, var feed = this.config.feeds[f];
reloadInterval: this.config.reloadInterval, this.sendSocketNotification("ADD_FEED", {
encoding: this.config.encoding feed: feed,
config: this.config
});
}
},
/* registerFeeds()
* Generate an ordered list of items for this configured module.
*
* attribute feeds object - An object with feeds returned by the nod helper.
*/
generateFeed: function(feeds) {
var newsItems = [];
for (var feed in feeds) {
var feedItems = feeds[feed];
if (this.subscribedToFeed(feed)) {
for (var i in feedItems) {
var item = feedItems[i];
item.sourceTitle = this.titleForFeed(feed);
newsItems.push(item);
}
}
}
newsItems.sort(function(a,b) {
var dateA = new Date(a.pubdate);
var dateB = new Date(b.pubdate);
return dateB - dateA;
}); });
this.newsItems = newsItems;
},
/* subscribedToFeed(feedUrl)
* Check if this module is configured to show this feed.
*
* attribute feedUrl string - Url of the feed to check.
*
* returns bool
*/
subscribedToFeed: function(feedUrl) {
for (var f in this.config.feeds) {
var feed = this.config.feeds[f];
if (feed.url === feedUrl) {
return true;
}
}
return false;
},
/* subscribedToFeed(feedUrl)
* Returns title for a specific feed Url.
*
* attribute feedUrl string - Url of the feed to check.
*
* returns string
*/
titleForFeed: function(feedUrl) {
for (var f in this.config.feeds) {
var feed = this.config.feeds[f];
if (feed.url === feedUrl) {
return feed.title || '';
}
}
return '';
}, },
/* scheduleUpdateInterval() /* scheduleUpdateInterval()

View File

@@ -13,14 +13,14 @@ module.exports = NodeHelper.create({
// Subclass start method. // Subclass start method.
start: function() { start: function() {
console.log("Starting module: " + this.name); console.log("Starting module: " + this.name);
this.fetchers = []; this.fetchers = [];
}, },
// Subclass socketNotificationReceived received. // Subclass socketNotificationReceived received.
socketNotificationReceived: function(notification, payload) { socketNotificationReceived: function(notification, payload) {
if (notification === "ADD_FEED") { if (notification === "ADD_FEED") {
this.createFetcher(payload.url, payload.reloadInterval, payload.encoding); this.createFetcher(payload.feed, payload.config);
return;
} }
}, },
@@ -32,9 +32,13 @@ module.exports = NodeHelper.create({
* attribute reloadInterval number - Reload interval in milliseconds. * attribute reloadInterval number - Reload interval in milliseconds.
*/ */
createFetcher: function(url, reloadInterval, encoding) { createFetcher: function(feed, config) {
var self = this; var self = this;
var url = feed.url || '';
var encoding = feed.encoding || 'UTF-8';
var reloadInterval = config.reloadInterval || 5 * 60 * 1000;
if (!validUrl.isUri(url)) { if (!validUrl.isUri(url)) {
self.sendSocketNotification("INCORRECT_URL", url); self.sendSocketNotification("INCORRECT_URL", url);
return; return;
@@ -46,10 +50,7 @@ module.exports = NodeHelper.create({
fetcher = new Fetcher(url, reloadInterval, encoding); fetcher = new Fetcher(url, reloadInterval, encoding);
fetcher.onReceive(function(fetcher) { fetcher.onReceive(function(fetcher) {
self.sendSocketNotification("NEWS_ITEMS", { self.broadcastFeeds();
url: fetcher.url(),
items: fetcher.items()
});
}); });
fetcher.onError(function(fetcher, error) { fetcher.onError(function(fetcher, error) {
@@ -68,5 +69,17 @@ module.exports = NodeHelper.create({
} }
fetcher.startFetch(); fetcher.startFetch();
},
/* broadcastFeeds()
* Creates an object with all feed items of the different registered feeds,
* and broadcasts these using sendSocketNotification.
*/
broadcastFeeds: function() {
var feeds = {};
for (var f in this.fetchers) {
feeds[f] = this.fetchers[f].items();
}
this.sendSocketNotification("NEWS_ITEMS", feeds);
} }
}); });