Skip to content

Commit 944b4c4

Browse files
author
Nikolai
committed
Use Wikipedia main sites with specific CSS selectors to get data
1 parent 343af6a commit 944b4c4

File tree

3 files changed

+48
-32
lines changed

3 files changed

+48
-32
lines changed

EventService.js

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
* MIT Licensed.
66
*/
77

8-
const https = require('https');
8+
const { https } = require('follow-redirects');
99

1010
/**
1111
* Service object to fetch XML data from Wikipedia.
@@ -15,23 +15,23 @@ class EventService {
1515
/*
1616
* ### Instance ###
1717
*/
18-
_xml = '';
18+
_html = '';
1919
_resolve = null;
2020
_reject = null;
2121

2222
/*
2323
* ### Listener ###
2424
*/
2525
_onData(chunk) {
26-
this._xml += chunk;
26+
this._html += chunk;
2727
}
2828

2929
_onError(error) {
3030
this._reject(error);
3131
}
3232

3333
_onEnd() {
34-
this._resolve(this._xml);
34+
this._resolve(this._html);
3535
}
3636

3737
_onResponse(response) {
@@ -48,7 +48,7 @@ class EventService {
4848
_promiseExecutor(language) {
4949

5050
// Wiki URL
51-
const url = `https://${language}.wikipedia.org/w/api.php?action=featuredfeed&feed=onthisday`;
51+
const url = `https://${language}.wikipedia.org`;
5252

5353
// Request data
5454
https.get(url, response => this._onResponse(response));
@@ -57,7 +57,7 @@ class EventService {
5757
/*
5858
* ### Public API ###
5959
*/
60-
async getXml(language) {
60+
async getHtml(language) {
6161

6262
// Create and return promise
6363
return new Promise((resolve, reject) => {

MMM-OnThisDay.js

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,9 @@ const moduleDefinition = {
2121
requiresVersion: '2.1.0', // Required version of MagicMirror
2222

2323
/**
24-
* Available languages, means that there is data to fetch for the node_helper at
25-
* https://${language}.wikipedia.org/w/api.php?action=featuredfeed&feed=onthisday
24+
* Available languages.
2625
*/
27-
availableLanguages: ['en', 'de'],
26+
availableLanguages: ['en', 'de', 'fr'],
2827
usedLanguage: 'en', // Fallback
2928

3029
/**
@@ -52,6 +51,7 @@ const moduleDefinition = {
5251
return {
5352
en: 'translation/en.json',
5453
de: 'translation/de.json',
54+
//fr: 'TODO'
5555
}
5656
},
5757

@@ -112,13 +112,9 @@ const moduleDefinition = {
112112
return;
113113
}
114114

115-
// Set title
115+
// Set content
116116
this.title = payload.title;
117-
118-
// Unescape
119-
const domParser = new DOMParser();
120-
const doc = domParser.parseFromString(payload.events, 'text/html');
121-
this.events = doc.documentElement.textContent;
117+
this.events = payload.events;
122118

123119
// Update module
124120
Log.info('Update DOM with new title and events ...');

node_helper.js

Lines changed: 37 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,24 @@
77

88
const NodeHelper = require('node_helper');
99
const EventService = require('./EventService');
10+
const { JSDOM } = require('jsdom');
1011
const Log = require('./LoggerProxy');
11-
const xmlParser = require('fast-xml-parser');
12+
13+
// CSS selector to find event list on language specific Wikipedia main site
14+
const LANGUAGE_SPECIFIC_EVENT_SELECTOR = {
15+
en: {
16+
title: '#mp-otd > p',
17+
events: '#mp-otd > ul'
18+
},
19+
de: {
20+
title: '#ereignisse > .hauptseite-box-title',
21+
events: '#ereignisse > .hauptseite-box-content > ul:first-of-type'
22+
},
23+
fr: {
24+
title: '.portail-droite > .accueil_2017_cadre:nth-child(2) .mw-headline',
25+
events: '.portail-droite > .accueil_2017_cadre:nth-child(2) > ul'
26+
},
27+
};
1228

1329
module.exports = NodeHelper.create({
1430

@@ -28,34 +44,38 @@ module.exports = NodeHelper.create({
2844
loadEvents: async function(language) {
2945
Log.log('Load events ...');
3046

31-
// Get xml
47+
// Get HTML
3248
const eventService = new EventService();
33-
const xml = await eventService.getXml(language);
49+
const html = await eventService.getHtml(language);
3450

3551
// Return parsed data
36-
return this.parseEvents(xml);
52+
return this.parseEvents(html, language);
3753
},
3854

39-
parseEvents: function(xml) {
40-
Log.log('Parse XML data ...');
55+
parseEvents: function(html, language) {
56+
Log.log('Parse HTML data ...');
4157

42-
// Parse XML data to json
43-
const json = xmlParser.parse(xml);
58+
// Create dom
59+
const dom = new JSDOM(html);
60+
const document = dom.window.document;
61+
62+
// Get title
63+
const titleSelector = LANGUAGE_SPECIFIC_EVENT_SELECTOR[language].title;
64+
const title = document.querySelector(titleSelector);
65+
66+
// Get events
67+
const eventsSelector = LANGUAGE_SPECIFIC_EVENT_SELECTOR[language].events;
68+
const events = document.querySelector(eventsSelector);
4469

4570
// Check data
46-
if (!json || !json.rss || !json.rss.channel || !json.rss.channel.item) {
47-
Log.log('Could not parse XML.')
71+
if (!events) {
72+
Log.log('Could not find events in HTML.')
4873
return {};
4974
}
5075

51-
// Get last item
52-
const items = json.rss.channel.item
53-
const itemsCount = items.length;
54-
const item = items[itemsCount - 1];
55-
5676
return {
57-
title: item.title,
58-
events: item.description,
77+
title: title ? title.innerHTML : null,
78+
events: events.outerHTML,
5979
};
6080
},
6181
});

0 commit comments

Comments
 (0)