diff --git a/.github/workflows/format-code.yml b/.github/workflows/format-code.yml
index f4f3913..eb5a091 100644
--- a/.github/workflows/format-code.yml
+++ b/.github/workflows/format-code.yml
@@ -10,7 +10,7 @@ jobs:
steps:
- name: Checkout Repository
- uses: actions/checkout@v2
+ uses: actions/checkout@v4
- name: Format Code with Prettier
run: npx prettier --write "**/*.js" --tab-width
diff --git a/MMM-pihole-stats.js b/MMM-pihole-stats.js
index 7a6e402..560836a 100644
--- a/MMM-pihole-stats.js
+++ b/MMM-pihole-stats.js
@@ -1,4 +1,4 @@
-/* Magic Mirror
+/* MagicMirror²
* Module: Pi-Hole Stats
*
* By Sheya Bernstein https://github.com/sheyabernstein/MMM-pihole-stats
@@ -23,22 +23,21 @@ Module.register("MMM-pihole-stats", {
initialLoadDelay: 0,
},
- formatInt: function (n) {
+ formatInt (n) {
return n.toLocaleString();
},
- formatFloat: function (n) {
+ formatFloat (n) {
if (this.config.floatingPoints) {
- let x = 10 ** this.config.floatingPoints;
+ const x = 10 ** this.config.floatingPoints;
return Math.round(parseFloat(n) * x) / x;
- } else {
- return n;
}
+ return n;
},
// Define start sequence.
- start: function () {
- Log.info("Starting module: " + this.name);
+ start () {
+ Log.info(`Starting module: ${this.name}`);
this.domains_being_blocked = null;
this.dns_queries_today = null;
@@ -51,8 +50,8 @@ Module.register("MMM-pihole-stats", {
},
// Override dom generator.
- getDom: function () {
- let wrapper = document.createElement("div");
+ getDom () {
+ const wrapper = document.createElement("div");
if (!this.loaded) {
wrapper.innerHTML = this.translate("LOADING...");
@@ -60,79 +59,79 @@ Module.register("MMM-pihole-stats", {
return wrapper;
}
- let header = document.createElement("div");
+ const header = document.createElement("div");
header.className = "small bright";
- header.innerHTML =
- this.formatInt(this.ads_blocked_today) +
- " ads blocked today. (" +
- this.formatFloat(this.ads_percentage_today) +
- "%)";
+ header.innerHTML
+ = `${this.formatInt(this.ads_blocked_today)}
+ ads blocked today. (
+ ${this.formatFloat(this.ads_percentage_today)}
+ %)`;
wrapper.appendChild(header);
if (this.top_sources && Object.keys(this.top_sources).length) {
- let table = document.createElement("table");
+ const table = document.createElement("table");
table.className = "xsmall light";
wrapper.appendChild(table);
- let thead = document.createElement("thead");
+ const thead = document.createElement("thead");
table.appendChild(thead);
- let row = document.createElement("tr");
+ const row = document.createElement("tr");
thead.appendChild(row);
- let sourceCell = document.createElement("th");
+ const sourceCell = document.createElement("th");
sourceCell.innerHTML = "Client";
row.appendChild(sourceCell);
- let countCell = document.createElement("th");
+ const countCell = document.createElement("th");
countCell.innerHTML = "Requests";
row.appendChild(countCell);
- let tbody = document.createElement("tbody");
+ const tbody = document.createElement("tbody");
table.appendChild(tbody);
for (let source in this.top_sources) {
- let adCount = this.top_sources[source];
+ const adCount = this.top_sources[source];
if (this.config.showSourceHostnameOnly) {
source = source.split("|")[0];
}
- let row = document.createElement("tr");
+ const row = document.createElement("tr");
tbody.appendChild(row);
- let sourceCell = document.createElement("td");
+ const sourceCell = document.createElement("td");
sourceCell.innerHTML = source;
row.appendChild(sourceCell);
- let countCell = document.createElement("td");
+ const countCell = document.createElement("td");
countCell.innerHTML = this.formatInt(adCount);
row.appendChild(countCell);
}
}
- let footer = document.createElement("div");
+ const footer = document.createElement("div");
footer.className = "xsmall";
- footer.innerHTML =
- this.formatInt(this.dns_queries_today) +
- " DNS queries, " +
- this.formatInt(this.domains_being_blocked) +
- " domains blacklisted.";
+ footer.innerHTML
+ = `${this.formatInt(this.dns_queries_today)}
+ DNS queries,
+ ${this.formatInt(this.domains_being_blocked)}
+ domains blacklisted.`;
wrapper.appendChild(footer);
return wrapper;
},
- updateStats: function () {
- Log.info(this.name + ": Getting data");
+ updateStats () {
+ Log.info(`${this.name}: Getting data`);
this.sendSocketNotification("GET_PIHOLE", {
- config: this.config,
+ config: this.config
});
},
// Handle node helper response
- socketNotificationReceived: function (notification, payload) {
+ socketNotificationReceived (notification, payload) {
if (notification === "PIHOLE_DATA") {
this.processSummary(payload);
this.loaded = true;
@@ -143,37 +142,37 @@ Module.register("MMM-pihole-stats", {
this.updateDom(this.config.animationSpeed);
},
- scheduleUpdate: function (delay) {
+ scheduleUpdate (delay) {
let nextLoad = this.config.updateInterval;
if (typeof delay !== "undefined" && delay >= 0) {
nextLoad = delay;
}
- let self = this;
- setTimeout(function () {
+ const self = this;
+ setTimeout(() => {
self.updateStats();
self.scheduleUpdate(self.config.updateInterval);
}, nextLoad);
},
- processSummary: function (data) {
+ processSummary (data) {
if (!data) {
// Did not receive usable new data.
return;
}
- this.domains_being_blocked = data["domains_being_blocked"] || "0";
- this.dns_queries_today = data["dns_queries_today"] || "0";
- this.ads_blocked_today = data["ads_blocked_today"] || "0";
- this.ads_percentage_today = data["ads_percentage_today"] || "0.0";
+ this.domains_being_blocked = data.domains_being_blocked || "0";
+ this.dns_queries_today = data.dns_queries_today || "0";
+ this.ads_blocked_today = data.ads_blocked_today || "0";
+ this.ads_percentage_today = data.ads_percentage_today || "0.0";
},
- processSources: function (data) {
+ processSources (data) {
if (!data) {
// Did not receive usable new data.
return;
}
- this.top_sources = data["top_sources"] || [];
+ this.top_sources = data.top_sources || [];
},
});
diff --git a/README.md b/README.md
index 98bbf91..13a3c4a 100755
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
# MMM-pihole-stats
-Pi-hole stats module for MagicMirror2
+Pi-hole stats module for MagicMirror².
## Screenshots
@@ -14,21 +14,19 @@ Without `config.showSources` enabled:
## Dependencies
-- [MagicMirror2](https://github.com/MichMich/MagicMirror)
+- [MagicMirror²](https://github.com/MagicMirrorOrg/MagicMirror)
- [Pi-hole](https://pi-hole.net)
## Installation
-1. Clone this repo into `~/MagicMirror/modules` directory.
- `git clone https://github.com/sheyabernstein/MMM-pihole-stats.git`
-2. Run `npm install` in the cloned module directory
-3. Obtain an API token from your PiHole installation by navigating to [http://pi.hole/admin/settings.php?tab=api](http://pi.hole/admin/settings.php?tab=api) and clicking `Show API token`
-4. Configure your `~/MagicMirror/config/config.js`
-
+1. Clone this repo into `~/MagicMirror/modules` directory.
+ `git clone https://github.com/sheyabernstein/MMM-pihole-stats`
+2. Obtain an API token from your PiHole installation by navigating to [http://pi.hole/admin/settings.php?tab=api](http://pi.hole/admin/settings.php?tab=api) and clicking `Show API token`
+3. Configure your `~/MagicMirror/config/config.js`
Here is an example entry for `config.js`:
-```
+```js
{
module: "MMM-pihole-stats",
position: "top_left", // Or any valid MagicMirror position.
@@ -36,13 +34,9 @@ Here is an example entry for `config.js`:
apiToken: "0123456789abcdef"
// See 'Configuration options' for more information.
}
-}
+},
```
-> Feb 27, 2024 update: This module now requires `npm install` when installing.
-
-> Sep 27, 2020 update: Configuring the Pi-hole server to allow CORS is no longer needed.
-
## Configuration Options
| **Option** | **Default** | **Description** |
@@ -55,3 +49,9 @@ Here is an example entry for `config.js`:
| `updateInterval` | `600000` | Time in ms to wait until updating |
| `retryDelay` | `30000` | Time in ms to wait before retry |
| `floatingPoints` | `2` | Format floating point numbers to decimal points, e.g. `2` to format to 5.55. Setting this to `0` will show unlimited decimal points |
+
+## Notes
+
+- Feb 28, 2024 update: This module needs no external packages anymore.
+- Feb 27, 2024 update: This module now requires `npm install` when installing.
+- Sep 27, 2020 update: Configuring the Pi-hole server to allow CORS is no longer needed.
diff --git a/node_helper.js b/node_helper.js
index 63c09a2..8f49883 100644
--- a/node_helper.js
+++ b/node_helper.js
@@ -1,42 +1,38 @@
const Log = require("logger");
-const request = require("request");
const NodeHelper = require("node_helper");
module.exports = NodeHelper.create({
- start: function () {
- Log.info("Starting node_helper for module [" + this.name + "]");
+ start () {
+ Log.info(`Starting node_helper for module [${this.name}]`);
},
- socketNotificationReceived: function (notification, payload) {
+ socketNotificationReceived (notification, payload) {
if (notification === "GET_PIHOLE") {
- let config = payload.config;
+ const config = payload.config;
if (!this.isValidURL(config.apiURL)) {
- Log.error(this.name + ": The apiURL is not a valid URL");
+ Log.error(`${this.name}: The apiURL is not a valid URL`);
return;
}
- Log.info("Notification: " + notification + " Payload: " + payload);
+ Log.debug(`Notification: ${notification} Payload: ${payload}`);
this.getPiholeData(config, { summary: 1 }, "PIHOLE_DATA");
if (config.showSources && config.sourcesCount > 0) {
if (config.showSources && !config.apiToken) {
- Log.error(
- this.name +
- ": Can't load sources because the apiKey is not set.",
- );
+ Log.error(`${this.name}: Can't load sources because the apiKey is not set.`);
} else {
this.getPiholeData(
config,
{ getQuerySources: config.sourcesCount },
- "PIHOLE_SOURCES",
+ "PIHOLE_SOURCES"
);
}
}
}
},
- isValidURL: function (url) {
+ isValidURL (url) {
try {
new URL(url);
return true;
@@ -45,11 +41,11 @@ module.exports = NodeHelper.create({
}
},
- buildURL: function (config, params) {
+ buildURL (config, params) {
params = params || {};
if (config.apiToken && !params.hasOwnProperty("auth")) {
- params["auth"] = config.apiToken;
+ params.auth = config.apiToken;
}
const url = new URL(config.apiURL);
@@ -58,22 +54,26 @@ module.exports = NodeHelper.create({
return url.toString();
},
- getPiholeData: function (config, params, notification) {
+ async getPiholeData (config, params, notification) {
const self = this,
url = self.buildURL(config, params),
headers = { Referer: url };
this.sendSocketNotification("LOADING_PIHOLE_URL", url);
- request({ url, headers, json: true }, (error, response, data) => {
-Log.info('url', url)
-//Log.info('response', response.statusCode)
-//Log.info('data', data)
- if (error) {
- Log.error(self.name + " ERROR:", error);
- } else {
+ try {
+ const response = await fetch(url, { headers });
+ if (!response.ok) {
+ throw new Error(`HTTP error! status: ${response.status}`);
+ }
+ if (response.headers.get('content-type').includes('application/json')) {
+ const data = await response.json();
self.sendSocketNotification(notification, data);
+ } else {
+ throw new Error(`Expected JSON but received ${response.headers.get('content-type')}`);
}
- });
+ } catch (error) {
+ Log.error(self.name + " ERROR:", error);
+ }
},
-});
+});
\ No newline at end of file
diff --git a/package.json b/package.json
index b14203e..6ca1358 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
{
- "name": "MMMM-pihole-stats",
+ "name": "mmm-pihole-stats",
"version": "1.0.0",
- "description": "Pi-hole stats module for MagicMirror2",
+ "description": "Pi-hole stats module for MagicMirror².",
"main": "MMM-pihole-stats.js",
"repository": {
"type": "git",
@@ -17,8 +17,5 @@
"bugs": {
"url": "https://github.com/sheyabernstein/MMM-pihole-stats/issues"
},
- "homepage": "https://github.com/sheyabernstein/MMM-pihole-stats#readme",
- "dependencies": {
- "request": "^2.81.0"
- }
+ "homepage": "https://github.com/sheyabernstein/MMM-pihole-stats#readme"
}