Skip to content

Commit

Permalink
Review (#32)
Browse files Browse the repository at this point in the history
* Fix typo

* Update

* Update URL + format

* Replace request by fetch
  • Loading branch information
KristjanESPERANTO authored Feb 27, 2024
1 parent 14b515b commit 6da9e8c
Show file tree
Hide file tree
Showing 5 changed files with 88 additions and 92 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/format-code.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
91 changes: 45 additions & 46 deletions MMM-pihole-stats.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* Magic Mirror
/* MagicMirror²
* Module: Pi-Hole Stats
*
* By Sheya Bernstein https://github.com/sheyabernstein/MMM-pihole-stats
Expand All @@ -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;
Expand All @@ -51,88 +50,88 @@ 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...");
wrapper.className = "dimmed light";
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;
Expand All @@ -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 || [];
},
});
28 changes: 14 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# MMM-pihole-stats

Pi-hole stats module for MagicMirror<sup>2</sup>
Pi-hole stats module for MagicMirror².

## Screenshots

Expand All @@ -14,35 +14,29 @@ Without `config.showSources` enabled:

## Dependencies

- [MagicMirror<sup>2</sup>](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.<br>
`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.
config: {
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** |
Expand All @@ -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.
50 changes: 25 additions & 25 deletions node_helper.js
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -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);
Expand All @@ -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);
}
},
});
});
9 changes: 3 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
@@ -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",
Expand All @@ -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"
}

0 comments on commit 6da9e8c

Please sign in to comment.