diff --git a/modules/default/calendar/calendarfetcher.js b/modules/default/calendar/calendarfetcher.js index 4788c9d5..d731905b 100644 --- a/modules/default/calendar/calendarfetcher.js +++ b/modules/default/calendar/calendarfetcher.js @@ -1,51 +1,49 @@ /* Magic Mirror * Node Helper: Calendar - CalendarFetcher * - * By Michael Teeuw http://michaelteeuw.nl + * By Michael Teeuw https://michaelteeuw.nl * MIT Licensed. */ +const Log = require("../../../js/logger.js"); +const ical = require("./vendor/ical.js"); +const moment = require("moment"); -var ical = require("./vendor/ical.js"); -var moment = require("moment"); - -var CalendarFetcher = function(url, reloadInterval, excludedEvents, maximumNumberOfDays, auth, includePastEvents) { +var CalendarFetcher = function (url, reloadInterval, excludedEvents, maximumNumberOfDays, auth, includePastEvents) { var self = this; var reloadTimer = null; var events = []; - var fetchFailedCallback = function() {}; - var eventsReceivedCallback = function() {}; + var fetchFailedCallback = function () {}; + var eventsReceivedCallback = function () {}; /* fetchCalendar() * Initiates calendar fetch. */ - var fetchCalendar = function() { - + var fetchCalendar = function () { clearTimeout(reloadTimer); reloadTimer = null; - nodeVersion = Number(process.version.match(/^v(\d+\.\d+)/)[1]); + var nodeVersion = Number(process.version.match(/^v(\d+\.\d+)/)[1]); var opts = { headers: { - "User-Agent": "Mozilla/5.0 (Node.js "+ nodeVersion + ") MagicMirror/" + global.version + " (https://github.com/MichMich/MagicMirror/)" + "User-Agent": "Mozilla/5.0 (Node.js " + nodeVersion + ") MagicMirror/" + global.version + " (https://github.com/MichMich/MagicMirror/)" }, gzip: true }; if (auth) { - if(auth.method === "bearer"){ + if (auth.method === "bearer") { opts.auth = { bearer: auth.pass }; - } else { opts.auth = { user: auth.user, pass: auth.pass }; - if(auth.method === "digest"){ + if (auth.method === "digest") { opts.auth.sendImmediately = false; } else { opts.auth.sendImmediately = true; @@ -53,36 +51,36 @@ var CalendarFetcher = function(url, reloadInterval, excludedEvents, maximumNumbe } } - ical.fromURL(url, opts, function(err, data) { + ical.fromURL(url, opts, function (err, data) { if (err) { fetchFailedCallback(self, err); scheduleTimer(); return; } - // console.log(data); - newEvents = []; + var newEvents = []; // limitFunction doesn't do much limiting, see comment re: the dates array in rrule section below as to why we need to do the filtering ourselves - var limitFunction = function(date, i) {return true;}; + var limitFunction = function (date, i) { + return true; + }; - var eventDate = function(event, time) { - return (event[time].length === 8) ? moment(event[time], "YYYYMMDD") : moment(new Date(event[time])); + var eventDate = function (event, time) { + return event[time].length === 8 ? moment(event[time], "YYYYMMDD") : moment(new Date(event[time])); }; for (var e in data) { var event = data[e]; var now = new Date(); var today = moment().startOf("day").toDate(); - var future = moment().startOf("day").add(maximumNumberOfDays, "days").subtract(1,"seconds").toDate(); // Subtract 1 second so that events that start on the middle of the night will not repeat. + var future = moment().startOf("day").add(maximumNumberOfDays, "days").subtract(1, "seconds").toDate(); // Subtract 1 second so that events that start on the middle of the night will not repeat. var past = today; if (includePastEvents) { past = moment().startOf("day").subtract(maximumNumberOfDays, "days").toDate(); } - // FIXME: - // Ugly fix to solve the facebook birthday issue. + // FIXME: Ugly fix to solve the facebook birthday issue. // Otherwise, the recurring events only show the birthday for next year. var isFacebookBirthday = false; if (typeof event.uid !== "undefined") { @@ -92,13 +90,12 @@ var CalendarFetcher = function(url, reloadInterval, excludedEvents, maximumNumbe } if (event.type === "VEVENT") { - var startDate = eventDate(event, "start"); var endDate; if (typeof event.end !== "undefined") { endDate = eventDate(event, "end"); - } else if(typeof event.duration !== "undefined") { - dur=moment.duration(event.duration); + } else if (typeof event.duration !== "undefined") { + var dur = moment.duration(event.duration); endDate = startDate.clone().add(dur); } else { if (!isFacebookBirthday) { @@ -176,8 +173,7 @@ var CalendarFetcher = function(url, reloadInterval, excludedEvents, maximumNumbe var addedEvents = 0; // can cause problems with e.g. birthdays before 1900 - if(rule.options && rule.origOptions && rule.origOptions.dtstart && rule.origOptions.dtstart.getFullYear() < 1900 || - rule.options && rule.options.dtstart && rule.options.dtstart.getFullYear() < 1900){ + if ((rule.options && rule.origOptions && rule.origOptions.dtstart && rule.origOptions.dtstart.getFullYear() < 1900) || (rule.options && rule.options.dtstart && rule.options.dtstart.getFullYear() < 1900)) { rule.origOptions.dtstart.setYear(1900); rule.options.dtstart.setYear(1900); } @@ -188,7 +184,7 @@ var CalendarFetcher = function(url, reloadInterval, excludedEvents, maximumNumbe var pastLocal = moment(past).subtract(past.getTimezoneOffset(), "minutes").toDate(); var futureLocal = moment(future).subtract(future.getTimezoneOffset(), "minutes").toDate(); var datesLocal = rule.between(pastLocal, futureLocal, true, limitFunction); - var dates = datesLocal.map(function(dateLocal) { + var dates = datesLocal.map(function (dateLocal) { var date = moment(dateLocal).add(dateLocal.getTimezoneOffset(), "minutes").toDate(); return date; }); @@ -200,17 +196,14 @@ var CalendarFetcher = function(url, reloadInterval, excludedEvents, maximumNumbe // because the logic below will filter out any recurrences that don"t actually belong within // our display range. // Would be great if there was a better way to handle this. - if (event.recurrences != undefined) - { + if (event.recurrences !== undefined) { var pastMoment = moment(past); var futureMoment = moment(future); - for (var r in event.recurrences) - { + for (var r in event.recurrences) { // Only add dates that weren't already in the range we added from the rrule so that // we don"t double-add those events. - if (moment(new Date(r)).isBetween(pastMoment, futureMoment) != true) - { + if (moment(new Date(r)).isBetween(pastMoment, futureMoment) !== true) { dates.push(new Date(r)); } } @@ -222,29 +215,27 @@ var CalendarFetcher = function(url, reloadInterval, excludedEvents, maximumNumbe // ical.js started returning recurrences and exdates as ISOStrings without time information. // .toISOString().substring(0,10) is the method they use to calculate keys, so we'll do the same // (see https://github.com/peterbraden/ical.js/pull/84 ) - var dateKey = date.toISOString().substring(0,10); + var dateKey = date.toISOString().substring(0, 10); var curEvent = event; var showRecurrence = true; startDate = moment(date); // For each date that we"re checking, it"s possible that there is a recurrence override for that one day. - if ((curEvent.recurrences != undefined) && (curEvent.recurrences[dateKey] != undefined)) - { + if (curEvent.recurrences !== undefined && curEvent.recurrences[dateKey] !== undefined) { // We found an override, so for this recurrence, use a potentially different title, start date, and duration. curEvent = curEvent.recurrences[dateKey]; startDate = moment(curEvent.start); duration = parseInt(moment(curEvent.end).format("x")) - parseInt(startDate.format("x")); } // If there"s no recurrence override, check for an exception date. Exception dates represent exceptions to the rule. - else if ((curEvent.exdate != undefined) && (curEvent.exdate[dateKey] != undefined)) - { + else if (curEvent.exdate !== undefined && curEvent.exdate[dateKey] !== undefined) { // This date is an exception date, which means we should skip it in the recurrence pattern. showRecurrence = false; } endDate = moment(parseInt(startDate.format("x")) + duration, "x"); - if (startDate.format("x") == endDate.format("x")) { + if (startDate.format("x") === endDate.format("x")) { endDate = endDate.endOf("day"); } @@ -277,29 +268,28 @@ var CalendarFetcher = function(url, reloadInterval, excludedEvents, maximumNumbe } // end recurring event parsing } else { - // console.log("Single event ..."); // Single event. - var fullDayEvent = (isFacebookBirthday) ? true : isFullDayEvent(event); + var fullDayEvent = isFacebookBirthday ? true : isFullDayEvent(event); if (includePastEvents) { + // Past event is too far in the past, so skip. if (endDate < past) { - //console.log("Past event is too far in the past. So skip: " + title); continue; } } else { + // It's not a fullday event, and it is in the past, so skip. if (!fullDayEvent && endDate < new Date()) { - //console.log("It's not a fullday event, and it is in the past. So skip: " + title); continue; } + // It's a fullday event, and it is before today, So skip. if (fullDayEvent && endDate <= today) { - //console.log("It's a fullday event, and it is before today. So skip: " + title); continue; } } + // It exceeds the maximumNumberOfDays limit, so skip. if (startDate > future) { - //console.log("It exceeds the maximumNumberOfDays limit. So skip: " + title); continue; } @@ -307,13 +297,12 @@ var CalendarFetcher = function(url, reloadInterval, excludedEvents, maximumNumbe continue; } - // adjust start date so multiple day events will be displayed as happening today even though they started some days ago already + // Adjust start date so multiple day events will be displayed as happening today even though they started some days ago already if (fullDayEvent && startDate <= today) { startDate = moment(today); } // Every thing is good. Add it to the list. - newEvents.push({ title: title, startDate: startDate.format("x"), @@ -324,16 +313,14 @@ var CalendarFetcher = function(url, reloadInterval, excludedEvents, maximumNumbe geo: geo, description: description }); - } } } - newEvents.sort(function(a, b) { + newEvents.sort(function (a, b) { return a.startDate - b.startDate; }); - //console.log(newEvents); events = newEvents; self.broadcastEvents(); @@ -344,10 +331,9 @@ var CalendarFetcher = function(url, reloadInterval, excludedEvents, maximumNumbe /* scheduleTimer() * Schedule the timer for the next update. */ - var scheduleTimer = function() { - //console.log('Schedule update timer.'); + var scheduleTimer = function () { clearTimeout(reloadTimer); - reloadTimer = setTimeout(function() { + reloadTimer = setTimeout(function () { fetchCalendar(); }, reloadInterval); }; @@ -359,7 +345,7 @@ var CalendarFetcher = function(url, reloadInterval, excludedEvents, maximumNumbe * * return bool - The event is a fullday event. */ - var isFullDayEvent = function(event) { + var isFullDayEvent = function (event) { if (event.start.length === 8 || event.start.dateOnly) { return true; } @@ -367,7 +353,7 @@ var CalendarFetcher = function(url, reloadInterval, excludedEvents, maximumNumbe var start = event.start || 0; var startDate = new Date(start); var end = event.end || 0; - if (((end - start) % (24 * 60 * 60 * 1000)) === 0 && startDate.getHours() === 0 && startDate.getMinutes() === 0) { + if ((end - start) % (24 * 60 * 60 * 1000) === 0 && startDate.getHours() === 0 && startDate.getMinutes() === 0) { // Is 24 hours, and starts on the middle of the night. return true; } @@ -384,7 +370,7 @@ var CalendarFetcher = function(url, reloadInterval, excludedEvents, maximumNumbe * * return bool - The event should be filtered out */ - var timeFilterApplies = function(now, endDate, filter) { + var timeFilterApplies = function (now, endDate, filter) { if (filter) { var until = filter.split(" "), value = parseInt(until[0]), @@ -398,16 +384,16 @@ var CalendarFetcher = function(url, reloadInterval, excludedEvents, maximumNumbe }; /* getTitleFromEvent(event) - * Gets the title from the event. - * - * argument event object - The event object to check. - * - * return string - The title of the event, or "Event" if no title is found. - */ + * Gets the title from the event. + * + * argument event object - The event object to check. + * + * return string - The title of the event, or "Event" if no title is found. + */ var getTitleFromEvent = function (event) { var title = "Event"; if (event.summary) { - title = (typeof event.summary.val !== "undefined") ? event.summary.val : event.summary; + title = typeof event.summary.val !== "undefined" ? event.summary.val : event.summary; } else if (event.description) { title = event.description; } @@ -436,15 +422,15 @@ var CalendarFetcher = function(url, reloadInterval, excludedEvents, maximumNumbe /* startFetch() * Initiate fetchCalendar(); */ - this.startFetch = function() { + this.startFetch = function () { fetchCalendar(); }; /* broadcastItems() * Broadcast the existing events. */ - this.broadcastEvents = function() { - //console.log('Broadcasting ' + events.length + ' events.'); + this.broadcastEvents = function () { + Log.info("Calendar-Fetcher: Broadcasting " + events.length + " events."); eventsReceivedCallback(self); }; @@ -453,7 +439,7 @@ var CalendarFetcher = function(url, reloadInterval, excludedEvents, maximumNumbe * * argument callback function - The on success callback. */ - this.onReceive = function(callback) { + this.onReceive = function (callback) { eventsReceivedCallback = callback; }; @@ -462,7 +448,7 @@ var CalendarFetcher = function(url, reloadInterval, excludedEvents, maximumNumbe * * argument callback function - The on error callback. */ - this.onError = function(callback) { + this.onError = function (callback) { fetchFailedCallback = callback; }; @@ -471,7 +457,7 @@ var CalendarFetcher = function(url, reloadInterval, excludedEvents, maximumNumbe * * return string - The url of this fetcher. */ - this.url = function() { + this.url = function () { return url; }; @@ -480,7 +466,7 @@ var CalendarFetcher = function(url, reloadInterval, excludedEvents, maximumNumbe * * return array - The current available events for this fetcher. */ - this.events = function() { + this.events = function () { return events; }; }; diff --git a/modules/default/calendar/node_helper.js b/modules/default/calendar/node_helper.js index 263b526a..5248919b 100644 --- a/modules/default/calendar/node_helper.js +++ b/modules/default/calendar/node_helper.js @@ -1,30 +1,26 @@ /* Magic Mirror * Node Helper: Calendar * - * By Michael Teeuw http://michaelteeuw.nl + * By Michael Teeuw https://michaelteeuw.nl * MIT Licensed. */ -var NodeHelper = require("node_helper"); -var validUrl = require("valid-url"); -var CalendarFetcher = require("./calendarfetcher.js"); +const NodeHelper = require("node_helper"); +const validUrl = require("valid-url"); +const CalendarFetcher = require("./calendarfetcher.js"); +const Log = require("../../../js/logger"); module.exports = NodeHelper.create({ // Override start method. - start: function() { - var events = []; - + start: function () { + Log.log("Starting node helper for: " + this.name); this.fetchers = []; - - console.log("Starting node helper for: " + this.name); - }, // Override socketNotificationReceived method. - socketNotificationReceived: function(notification, payload) { + socketNotificationReceived: function (notification, payload) { if (notification === "ADD_CALENDAR") { - //console.log('ADD_CALENDAR: '); - this.createFetcher(payload.url, payload.fetchInterval, payload.excludedEvents, payload.maximumEntries, payload.maximumNumberOfDays, payload.auth, payload.broadcastPastEvents); + this.createFetcher(payload.url, payload.fetchInterval, payload.excludedEvents, payload.maximumNumberOfDays, payload.auth, payload.broadcastPastEvents, payload.id); } }, @@ -35,42 +31,40 @@ module.exports = NodeHelper.create({ * attribute url string - URL of the news feed. * attribute reloadInterval number - Reload interval in milliseconds. */ - - createFetcher: function(url, fetchInterval, excludedEvents, maximumEntries, maximumNumberOfDays, auth, broadcastPastEvents) { + createFetcher: function (url, fetchInterval, excludedEvents, maximumNumberOfDays, auth, broadcastPastEvents, identifier) { var self = this; if (!validUrl.isUri(url)) { - self.sendSocketNotification("INCORRECT_URL", {url: url}); + self.sendSocketNotification("INCORRECT_URL", { id: identifier, url: url }); return; } var fetcher; - if (typeof self.fetchers[url] === "undefined") { - console.log("Create new calendar fetcher for url: " + url + " - Interval: " + fetchInterval); + if (typeof self.fetchers[identifier + url] === "undefined") { + Log.log("Create new calendar fetcher for url: " + url + " - Interval: " + fetchInterval); fetcher = new CalendarFetcher(url, fetchInterval, excludedEvents, maximumNumberOfDays, auth, broadcastPastEvents); - fetcher.onReceive(function(fetcher) { - //console.log('Broadcast events.'); - //console.log(fetcher.events()); - + fetcher.onReceive(function (fetcher) { self.sendSocketNotification("CALENDAR_EVENTS", { + id: identifier, url: fetcher.url(), events: fetcher.events() }); }); - fetcher.onError(function(fetcher, error) { - console.error("Calendar Error. Could not fetch calendar: ", fetcher.url(), error); + fetcher.onError(function (fetcher, error) { + Log.error("Calendar Error. Could not fetch calendar: ", fetcher.url(), error); self.sendSocketNotification("FETCH_ERROR", { + id: identifier, url: fetcher.url(), error: error }); }); - self.fetchers[url] = fetcher; + self.fetchers[identifier + url] = fetcher; } else { - //console.log('Use existing news fetcher for url: ' + url); - fetcher = self.fetchers[url]; + Log.log("Use existing calendar fetcher for url: " + url); + fetcher = self.fetchers[identifier + url]; fetcher.broadcastEvents(); }