mirror of
https://github.com/Lissy93/dashy.git
synced 2025-09-25 02:38:03 +02:00
feat: add pi-hole-traffic-v6 widget and docs
This commit is contained in:
parent
f738cd2726
commit
8a0ec73ca7
@ -1852,7 +1852,7 @@ Shows top queries that were blocked and allowed by [Pi-Hole](https://pi-hole.net
|
||||
|
||||
### Pi Hole Queries v6
|
||||
|
||||
Shows top queries that were blocked and allowed by [Pi-Hole](https://pi-hole.net/).
|
||||
Shows top queries that were blocked and allowed by [Pi-Hole](https://pi-hole.net/). Use this version of the widget if you have a v6+ Pi-Hole instance.
|
||||
|
||||
<p align="center"><img width="400" src="https://i.ibb.co/pXR0bdQ/pi-hole-queries.png" /></p>
|
||||
|
||||
@ -1915,6 +1915,38 @@ Shows number of recent traffic, using allowed and blocked queries from [Pi-Hole]
|
||||
|
||||
---
|
||||
|
||||
### Pi Hole Recent Traffic v6
|
||||
|
||||
Shows number of recent traffic, using allowed and blocked queries from [Pi-Hole](https://pi-hole.net/). Use this version of the widget if you have a v6+ Pi-Hole instance.
|
||||
|
||||
<p align="center"><img width="500" src="https://i.ibb.co/7kdxxwx/pi-hole-recent-queries.png" /></p>
|
||||
|
||||
#### Options
|
||||
|
||||
**Field** | **Type** | **Required** | **Description**
|
||||
--- | --- | --- | ---
|
||||
**`hostname`** | `string` | Required | The URL to your Pi-Hole instance
|
||||
**`apiKey`** | `string` | Required | Your Pi-Hole web password or application password. It **IS** your Pi-Hole admin interface password **UNLESS** you have 2FA turned on (in contrast to the old widget). If you have 2FA turned on you will need to create an application password. Refer to Pi-Hole documentation for how to create an application password.
|
||||
|
||||
#### Example
|
||||
|
||||
```yaml
|
||||
- type: pi-hole-traffic-v6
|
||||
options:
|
||||
hostname: https://pi-hole.local
|
||||
apiKey: xxxxxxxxxxxxxxxxxxxxxxx
|
||||
```
|
||||
|
||||
#### Info
|
||||
|
||||
- **CORS**: 🟢 Enabled
|
||||
- **Auth**: 🔴 Required
|
||||
- **Price**: 🟢 Free
|
||||
- **Host**: Self-Hosted (see [GitHub - Pi-hole](https://github.com/pi-hole/pi-hole))
|
||||
- **Privacy**: _See [Pi-Hole Privacy Guide](https://pi-hole.net/privacy/)_
|
||||
|
||||
---
|
||||
|
||||
### Stat Ping Statuses
|
||||
|
||||
Displays the current and recent uptime of your running services, via a self-hosted instance of [StatPing](https://github.com/statping/statping)
|
||||
|
130
src/components/Widgets/PiHoleTrafficV6.vue
Normal file
130
src/components/Widgets/PiHoleTrafficV6.vue
Normal file
@ -0,0 +1,130 @@
|
||||
<template>
|
||||
<div :id="chartId" class="pi-hole-traffic"></div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import WidgetMixin from '@/mixins/WidgetMixin';
|
||||
import ChartingMixin from '@/mixins/ChartingMixin';
|
||||
|
||||
export default {
|
||||
mixins: [WidgetMixin, ChartingMixin],
|
||||
components: {},
|
||||
data() {
|
||||
return {
|
||||
csrfToken: null,
|
||||
sid: null,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
/* Let user select which comic to display: random, latest or a specific number */
|
||||
hostname() {
|
||||
const usersChoice = this.parseAsEnvVar(this.options.hostname);
|
||||
if (!usersChoice) this.error('You must specify the hostname for your Pi-Hole server');
|
||||
return usersChoice;
|
||||
},
|
||||
apiKey() {
|
||||
const usersChoice = this.parseAsEnvVar(this.options.apiKey);
|
||||
if (!usersChoice) this.error('App Password is required, please see the docs');
|
||||
return usersChoice;
|
||||
},
|
||||
authHeader() {
|
||||
return {
|
||||
'X-FTL-SID': this.sid,
|
||||
'X-FTL-CSRF': this.csrfToken,
|
||||
Accept: 'application/json',
|
||||
};
|
||||
},
|
||||
authEndpoint() {
|
||||
return `${this.hostname}/api/auth`;
|
||||
},
|
||||
historyEndpoint() {
|
||||
return `${this.hostname}/api/history`;
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
fetchData() {
|
||||
this.makeRequest(
|
||||
this.authEndpoint,
|
||||
{ 'Content-Type': 'application/json' },
|
||||
'POST',
|
||||
{ password: this.apiKey },
|
||||
)
|
||||
.then(this.processAuthData)
|
||||
.then(
|
||||
() => {
|
||||
if (!this.sid || !this.csrfToken) return;
|
||||
|
||||
this.fetchHistory().then((response) => {
|
||||
if (this.validate(response)) {
|
||||
this.processData(response);
|
||||
}
|
||||
});
|
||||
},
|
||||
);
|
||||
},
|
||||
processAuthData({ session }) {
|
||||
if (!session) {
|
||||
this.error('Missing session info in auth response');
|
||||
} else if (session.valid !== true) {
|
||||
this.error('Authentication failed: Invalid credentials or 2FA token required');
|
||||
} else {
|
||||
const { sid, csrf } = session;
|
||||
if (!sid || !csrf) {
|
||||
this.error('No CSRF token or SID received');
|
||||
} else {
|
||||
this.sid = sid;
|
||||
this.csrfToken = csrf;
|
||||
}
|
||||
}
|
||||
},
|
||||
fetchHistory() {
|
||||
return this.makeRequest(this.historyEndpoint, this.authHeader);
|
||||
},
|
||||
validate(data) {
|
||||
if (!data || !Array.isArray(data['history'])) {
|
||||
this.error('Got success, but found no results, possible authorization error');
|
||||
} else if (data.history.length < 1) {
|
||||
this.error('Request completed succesfully, but no data in Pi-Hole yet');
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
processData({ history }) {
|
||||
const timeData = [];
|
||||
const domainsData = [];
|
||||
const adsData = [];
|
||||
history.forEach(({ timestamp, total, blocked }) => {
|
||||
timeData.push(this.formatTime(timestamp * 1000));
|
||||
domainsData.push(total - blocked);
|
||||
adsData.push(blocked);
|
||||
});
|
||||
const chartData = {
|
||||
labels: timeData,
|
||||
datasets: [
|
||||
{ name: 'Queries', type: 'bar', values: domainsData },
|
||||
{ name: 'Ads Blocked', type: 'bar', values: adsData },
|
||||
],
|
||||
};
|
||||
this.generateChart(chartData);
|
||||
},
|
||||
generateChart(chartData) {
|
||||
return new this.Chart(`#${this.chartId}`, {
|
||||
title: 'Recent Queries & Ads',
|
||||
data: chartData,
|
||||
type: 'axis-mixed',
|
||||
height: this.chartHeight,
|
||||
colors: ['#20e253', '#f80363'],
|
||||
truncateLegends: true,
|
||||
lineOptions: {
|
||||
regionFill: 1,
|
||||
hideDots: 1,
|
||||
},
|
||||
axisOptions: {
|
||||
xIsSeries: true,
|
||||
xAxisMode: 'tick',
|
||||
},
|
||||
});
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
@ -107,6 +107,7 @@ const COMPAT = {
|
||||
'pi-hole-top-queries': 'PiHoleTopQueries',
|
||||
'pi-hole-top-queries-v6': 'PiHoleTopQueriesV6',
|
||||
'pi-hole-traffic': 'PiHoleTraffic',
|
||||
'pi-hole-traffic-v6': 'PiHoleTrafficV6',
|
||||
'proxmox-lists': 'Proxmox',
|
||||
'public-holidays': 'PublicHolidays',
|
||||
'public-ip': 'PublicIp',
|
||||
|
Loading…
x
Reference in New Issue
Block a user