mirror of
https://github.com/MichMich/MagicMirror.git
synced 2025-06-27 11:50:00 +00:00
## [2.30.0] - 2025-01-01 Thanks to: @xsorifc28, @HeikoGr, @bugsounet, @khassel, @KristjanESPERANTO, @rejas, @sdetweil. > ⚠️ This release needs nodejs version `v20` or `v22 or higher`, minimum version is `v20.18.1` ### Added - [core] Add wayland and windows start options to `package.json` (#3594) - [docs] Add step for npm publishing in release process (#3595) - [core] Add GitHub workflow to run spellcheck a few days before each release (#3623) - [core] Add test flag to `index.html` to pass to module js for test mode detection (needed by #3630) - [core] Add export on animation names (#3644) - [compliments] Add support for refreshing remote compliments file, and test cases (#3630) - [linter] Re-add `eslint-plugin-import`now that it supports ESLint v9 (#3586) - [linter] Re-activate `eslint-plugin-package-json` to lint `package.json` (#3643) - [linter] Add linting for markdown files (#3646) - [linter] Add some handy ESLint rules. - [calendar] Add ability to display end date for full date events, where end is not same day (showEnd=true) (#3650) - [core] Add text to the config.js.sample file about the locale variable (#3654, #3655) - [core] Add fetch timeout for all node_helpers (thru undici, forces node 20.18.1 minimum) to help on slower systems. (#3660) (3661) ### Changed - [core] Run code style checks in workflow only once (#3648) - [core] Fix animations export #3644 only on server side (#3649) - [core] Use project URL in fallback config (#3656) - [core] Fix Access Denied crash writing js/positions.js (on synology nas) #3651. new message, MM starts, but no modules showing (#3652) - [linter] Switch to 'npx' for lint-staged in pre-commit hook (#3658) ### Removed - [tests] Remove `node-pty` and `drivelist` from rebuilded test (#3575) - [deps] Remove `@eslint/js` dependency. Already installed with `eslint` in deep (#3636) ### Updated - [repo] Reactivate `stale.yaml` as GitHub action to mark issues as stale after 60 days and close them 7 days later (if no activity) (#3577, #3580, #3581) - [core] Update electron dependency to v32 (test electron rebuild) and all other dependencies too (#3657) - [tests] All test configs have been updated to allow full external access, allowing for easier debugging (especially when running as a container) - [core] Run and test with node 23 (#3588) - [workflow] delete exception `allow-ghsas: GHSA-8hc4-vh64-cxmj` in `dep-review.yaml` (#3659) ### Fixed - [updatenotification] Fix pm2 using detection when pm2 script is inside or outside MagicMirror root folder (#3576) (#3605) (#3626) (#3628) - [core] Fix loading node_helper of modules: avoid black screen, display errors and continue loading with next module (#3578) - [weather] Change default value for weatherEndpoint of provider openweathermap to "/onecall" (#3574) - [tests] Fix electron tests with mock dates, the mock on server side was missing (#3597) - [tests] Fix testcases with hard coded Date.now (#3597) - [core] Fix missing `basePath` where `location.host` is used (#3613) - [compliments] croner library changed filenames used in latest version (#3624) - [linter] Fix ESLint ignore pattern which caused that default modules not to be linted (#3632) - [core] Fix module path in case of sub/sub folder is used and use path.resolve for resolve `moduleFolder` and `defaultModuleFolder` in app.js (#3653) - [calendar] Update to resolve issues #3098 #3144 #3351 #3422 #3443 #3467 #3537 related to timezone changes - [calendar] Fix #3267 (styles array), also fixes event with both exdate AND recurrence(and testcase) - [calendar] Fix showEndsOnlyWithDuration not working, #3598, applies ONLY to full day events - [calendar] Fix showEnd for Full Day events (#3602) - [tests] Suppress "module is not defined" in e2e tests (#3647) - [calendar] Fix #3267 (styles array, really this time!) - [core] Fix #3662 js/positions.js created incorrectly --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: Michael Teeuw <michael@xonaymedia.nl> Co-authored-by: Kristjan ESPERANTO <35647502+KristjanESPERANTO@users.noreply.github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Karsten Hassel <hassel@gmx.de> Co-authored-by: Ross Younger <crazyscot@gmail.com> Co-authored-by: Veeck <github@veeck.de> Co-authored-by: Bugsounet - Cédric <github@bugsounet.fr> Co-authored-by: jkriegshauser <joshuakr@nvidia.com> Co-authored-by: illimarkangur <116028111+illimarkangur@users.noreply.github.com> Co-authored-by: vppencilsharpener <tim.pray@gmail.com> Co-authored-by: veeck <michael.veeck@nebenan.de> Co-authored-by: Paranoid93 <6515818+Paranoid93@users.noreply.github.com> Co-authored-by: Brian O'Connor <btoconnor@users.noreply.github.com> Co-authored-by: WallysWellies <59727507+WallysWellies@users.noreply.github.com> Co-authored-by: Jason Stieber <jrstieber@gmail.com> Co-authored-by: jargordon <50050429+jargordon@users.noreply.github.com> Co-authored-by: Daniel <32464403+dkallen78@users.noreply.github.com> Co-authored-by: Ryan Williams <65094007+ryan-d-williams@users.noreply.github.com> Co-authored-by: Panagiotis Skias <panagiotis.skias@gmail.com> Co-authored-by: Marc Landis <dirk.rettschlag@gmail.com> Co-authored-by: HeikoGr <20295490+HeikoGr@users.noreply.github.com> Co-authored-by: Pedro Lamas <pedrolamas@gmail.com> Co-authored-by: veeck <gitkraken@veeck.de>
141 lines
3.8 KiB
JavaScript
141 lines
3.8 KiB
JavaScript
const https = require("node:https");
|
|
const ical = require("node-ical");
|
|
const Log = require("logger");
|
|
const NodeHelper = require("node_helper");
|
|
const CalendarFetcherUtils = require("./calendarfetcherutils");
|
|
|
|
/**
|
|
*
|
|
* @param {string} url The url of the calendar to fetch
|
|
* @param {number} reloadInterval Time in ms the calendar is fetched again
|
|
* @param {string[]} excludedEvents An array of words / phrases from event titles that will be excluded from being shown.
|
|
* @param {number} maximumEntries The maximum number of events fetched.
|
|
* @param {number} maximumNumberOfDays The maximum number of days an event should be in the future.
|
|
* @param {object} auth The object containing options for authentication against the calendar.
|
|
* @param {boolean} includePastEvents If true events from the past maximumNumberOfDays will be fetched too
|
|
* @param {boolean} selfSignedCert If true, the server certificate is not verified against the list of supplied CAs.
|
|
* @class
|
|
*/
|
|
const CalendarFetcher = function (url, reloadInterval, excludedEvents, maximumEntries, maximumNumberOfDays, auth, includePastEvents, selfSignedCert) {
|
|
let reloadTimer = null;
|
|
let events = [];
|
|
|
|
let fetchFailedCallback = function () {};
|
|
let eventsReceivedCallback = function () {};
|
|
|
|
/**
|
|
* Initiates calendar fetch.
|
|
*/
|
|
const fetchCalendar = () => {
|
|
clearTimeout(reloadTimer);
|
|
reloadTimer = null;
|
|
const nodeVersion = Number(process.version.match(/^v(\d+\.\d+)/)[1]);
|
|
let httpsAgent = null;
|
|
let headers = {
|
|
"User-Agent": `Mozilla/5.0 (Node.js ${nodeVersion}) MagicMirror/${global.version}`
|
|
};
|
|
|
|
if (selfSignedCert) {
|
|
httpsAgent = new https.Agent({
|
|
rejectUnauthorized: false
|
|
});
|
|
}
|
|
if (auth) {
|
|
if (auth.method === "bearer") {
|
|
headers.Authorization = `Bearer ${auth.pass}`;
|
|
} else {
|
|
headers.Authorization = `Basic ${Buffer.from(`${auth.user}:${auth.pass}`).toString("base64")}`;
|
|
}
|
|
}
|
|
|
|
fetch(url, { headers: headers, agent: httpsAgent })
|
|
.then(NodeHelper.checkFetchStatus)
|
|
.then((response) => response.text())
|
|
.then((responseData) => {
|
|
let data = [];
|
|
|
|
try {
|
|
data = ical.parseICS(responseData);
|
|
Log.debug(`parsed data=${JSON.stringify(data, null, 2)}`);
|
|
events = CalendarFetcherUtils.filterEvents(data, {
|
|
excludedEvents,
|
|
includePastEvents,
|
|
maximumEntries,
|
|
maximumNumberOfDays
|
|
});
|
|
} catch (error) {
|
|
fetchFailedCallback(this, error);
|
|
scheduleTimer();
|
|
return;
|
|
}
|
|
this.broadcastEvents();
|
|
scheduleTimer();
|
|
})
|
|
.catch((error) => {
|
|
fetchFailedCallback(this, error);
|
|
scheduleTimer();
|
|
});
|
|
};
|
|
|
|
/**
|
|
* Schedule the timer for the next update.
|
|
*/
|
|
const scheduleTimer = function () {
|
|
clearTimeout(reloadTimer);
|
|
reloadTimer = setTimeout(function () {
|
|
fetchCalendar();
|
|
}, reloadInterval);
|
|
};
|
|
|
|
/* public methods */
|
|
|
|
/**
|
|
* Initiate fetchCalendar();
|
|
*/
|
|
this.startFetch = function () {
|
|
fetchCalendar();
|
|
};
|
|
|
|
/**
|
|
* Broadcast the existing events.
|
|
*/
|
|
this.broadcastEvents = function () {
|
|
Log.info(`Calendar-Fetcher: Broadcasting ${events.length} events from ${url}.`);
|
|
eventsReceivedCallback(this);
|
|
};
|
|
|
|
/**
|
|
* Sets the on success callback
|
|
* @param {Function} callback The on success callback.
|
|
*/
|
|
this.onReceive = function (callback) {
|
|
eventsReceivedCallback = callback;
|
|
};
|
|
|
|
/**
|
|
* Sets the on error callback
|
|
* @param {Function} callback The on error callback.
|
|
*/
|
|
this.onError = function (callback) {
|
|
fetchFailedCallback = callback;
|
|
};
|
|
|
|
/**
|
|
* Returns the url of this fetcher.
|
|
* @returns {string} The url of this fetcher.
|
|
*/
|
|
this.url = function () {
|
|
return url;
|
|
};
|
|
|
|
/**
|
|
* Returns current available events for this fetcher.
|
|
* @returns {object[]} The current available events for this fetcher.
|
|
*/
|
|
this.events = function () {
|
|
return events;
|
|
};
|
|
};
|
|
|
|
module.exports = CalendarFetcher;
|