Răsfoiți Sursa

update to use the v6 api

phyzical 9 luni în urmă
părinte
comite
78db177e7a
3 a modificat fișierele cu 157 adăugiri și 63 ștergeri
  1. 2 1
      .gitignore
  2. 123 48
      api/homepage/pihole.php
  3. 32 14
      js/functions.js

+ 2 - 1
.gitignore

@@ -190,4 +190,5 @@ api/pages/custom/*.php
 /plugins/images/cache/tautulli-movie.svg
 /plugins/images/cache/tautulli-windows.svg
 /plugins/images/cache/tautulli-samsung.svg
-/plugins/images/cache/tautulli-chrome.svg
+/plugins/images/cache/tautulli-chrome.svg
+.vscode

+ 123 - 48
api/homepage/pihole.php

@@ -22,7 +22,7 @@ trait PiHoleHomepageItem
 					$this->settingsOption('auth', 'homepagePiholeAuth'),
 				],
 				'Connection' => [
-					$this->settingsOption('multiple-url', 'piholeURL', ['help' => 'Please make sure to use local IP address and port and to include \'/admin/\' at the end of the URL. You can add multiple Pi-holes by comma separating the URLs.', 'placeholder' => 'http(s)://hostname:port/admin/']),
+					$this->settingsOption('multiple-url', 'piholeURL', ['help' => 'Please make sure to use local IP address and port at the end of the URL. You can add multiple Pi-holes by comma separating the URLs.', 'placeholder' => 'http(s)://hostname:port/']),
 					$this->settingsOption('multiple-token', 'piholeToken'),
 				],
 				'Misc' => [
@@ -48,36 +48,10 @@ trait PiHoleHomepageItem
 		$errors = '';
 		$list = $this->csvHomepageUrlToken($this->config['piholeURL'], $this->config['piholeToken']);
 		foreach ($list as $key => $value) {
-			$url = $value['url'] . '/api.php?status';
-			if ($value['token'] !== '' && $value['token'] !== null) {
-				$url = $url . '&auth=' . $value['token'];
-			}
-			$ip = $this->qualifyURL($url, true)['host'];
-			try {
-				$response = Requests::get($url, [], []);
-				if ($response->success) {
-					$test = $this->testAndFormatString($response->body);
-					if (($test['type'] !== 'json')) {
-						$errors .= $ip . ': Response was not JSON';
-						$failed = true;
-					} else {
-						if (!isset($test['data']['status'])) {
-							$errors .= $ip . ': Missing API Token';
-							$failed = true;
-						}
-					}
-				}
-				if (!$response->success) {
-					$errors .= $ip . ': Unknown Failure';
-					$failed = true;
-				}
-			} catch (Requests_Exception $e) {
-				$failed = true;
-				$errors .= $ip . ': ' . $e->getMessage();
-				$this->setLoggerChannel('PiHole')->error($e);
-			};
+			$response = $this->getAuth($value['url'], $value['token']);
+			$errors = $response["errors"];
 		}
-		if ($failed) {
+		if ($errors != '') {
 			$this->setAPIResponse('error', $errors, 500);
 			return false;
 		} else {
@@ -120,6 +94,120 @@ trait PiHoleHomepageItem
 		}
 	}
 
+	public function getAuth($base_url, $token)
+	{
+		$sid = null;
+		if ($token === '' || $token === null) {
+			$errors .= $base_url . ': Missing API Token';
+			$this->setAPIResponse('error', $errors, 500);
+			return $errors;
+		}
+		try {
+			$sid = $this->doRequest($base_url, "createAuth", [], ['password' => $token]);
+			$this->cleanSessions($base_url, $sid);
+		} catch (Requests_Exception $e) {
+			$errors .= $ip . ': ' . $e->getMessage();
+			$this->setLoggerChannel('PiHole')->error($e);
+		};
+
+		return ["errors" => $errors, "sid" => $sid];
+	}
+
+	public function cleanSessions($base_url, $sid)
+	{
+		$sessions = $this->doRequest($base_url, "getAuths", ["sid" => $sid]);
+		foreach ($sessions as $session) {
+			//  Skip if not right user agent, skip if current session
+			if ($session['user_agent'] != 'Organizr' || $session['current_session'] == '1') {
+				continue;
+			}
+			$this->doRequest($base_url,"deleteAuth", ["sid" => $sid],  $session['id']);
+		}
+	}
+
+	public function endpoints($endpoint)
+	{
+		return [
+			"createAuth" => [
+				"type" => "post",
+				"urlHandler" => function() {
+					return "auth";
+				},
+				"responseHandler" => function($payload) {
+					return $payload['session']['sid'];
+				},
+				"payloadHandler" => function($data) {
+					return json_encode($data);
+				}
+			],
+			"getAuths" => [
+				"type" => "get",
+				"urlHandler" => function() {
+					return "auth/sessions";
+				},
+				"responseHandler" => function($payload) {
+					return $payload['sessions'];
+				}
+			],
+			"deleteAuth" => [
+				"type" => "delete",
+				"urlHandler" => function($id) {
+					return "auth/session/$id";
+				},
+			],
+			"get24HourStatsSummary" => [
+				"type" => "get",
+				"urlHandler" => function() {
+					$nowUnixTimestamp = time();
+					$oneDayAgoUnixTimestamp = $nowUnixTimestamp - (24 * 60 * 60);
+					return "stats/database/summary?from=$oneDayAgoUnixTimestamp&until=$nowUnixTimestamp";
+				}
+			],
+			"get24HourBlockedDomains" => [
+				"type" => "get",
+				"urlHandler" => function() {
+					$nowUnixTimestamp = time();
+					$oneDayAgoUnixTimestamp = $nowUnixTimestamp - (24 * 60 * 60);
+					return "stats/database/top_domains?from=$oneDayAgoUnixTimestamp&until=$nowUnixTimestamp&blocked=true&count=1000";
+				},
+				"responseHandler" => function($payload) {
+					return array_map(
+						function($item) {
+							return $item['domain'];
+						}, $payload['domains']
+					);
+					
+				}
+			],
+		][$endpoint];
+	}
+
+	public function doRequest($baseUrl, $endpoint, $headers = [], $data = null)
+	{
+		$endpointDictionary = $this->endpoints($endpoint);
+		$urlHandler = $endpointDictionary['urlHandler'];
+		$payloadHandler = $endpointDictionary['payloadHandler'] ?? function() {
+			return null;
+		};
+		$requestType = $endpointDictionary['type'];
+		$responseHandler = $endpointDictionary['responseHandler'] ?? function($payload) {
+			return $payload;
+		};
+		$url = $this->qualifyURL("$baseUrl/api/{$urlHandler($data)}");
+		$headers = $headers + ["User-Agent" => 'Organizr'];
+		try {
+			$response = Requests::$requestType($url, $headers, $payloadHandler($data));
+			
+			if ($response->success) {
+				$processedResponse = $responseHandler($this->testAndFormatString($response->body)["data"]);
+			}
+		} catch (Requests_Exception $e) {
+				$this->setResponse(500, $e->getMessage());
+				$this->setLoggerChannel('PiHole')->error($e);
+			};
+		return $processedResponse ?? [];
+	}
+
 	public function getPiholeHomepageStats()
 	{
 		if (!$this->homepageItemPermissions($this->piholeHomepagePermissions('main'), true)) {
@@ -128,24 +216,11 @@ trait PiHoleHomepageItem
 		$api = [];
 		$list = $this->csvHomepageUrlToken($this->config['piholeURL'], $this->config['piholeToken']);
 		foreach ($list as $key => $value) {
-			$url = $value['url'] . '/api.php?summaryRaw';
-			if ($value['token'] !== '' && $value['token'] !== null) {
-				$url = $url . '&auth=' . $value['token'];
-			}
-			try {
-				$response = Requests::get($url, [], []);
-				if ($response->success) {
-					@$piholeResults = json_decode($response->body, true);
-					if (is_array($piholeResults)) {
-						$ip = $this->qualifyURL($url, true)['host'];
-						$api['data'][$ip] = $piholeResults;
-					}
-				}
-			} catch (Requests_Exception $e) {
-				$this->setResponse(500, $e->getMessage());
-				$this->setLoggerChannel('PiHole')->error($e);
-				return false;
-			};
+			$base_url = $value['url'];
+			$sid = $this->getAuth($base_url, $value['token'])["sid"];
+			$stats = $this->doRequest($base_url, "get24HourStatsSummary", ["sid" => $sid]);
+			$stats["domains_being_blocked"] = $this->doRequest($base_url, "get24HourBlockedDomains", ["sid" => $sid]);
+			$api['data'][$base_url] = $stats;
 		}
 		$api['options']['combine'] = $this->config['homepagePiholeCombine'];
 		$api['options']['title'] = $this->config['piholeHeaderToggle'];

+ 32 - 14
js/functions.js

@@ -7872,6 +7872,23 @@ function buildPiholeItem(array){
     .inline-block {
         display: inline-block;
     }
+
+    ul.multi-column {
+        column-count: 1;
+        column-gap: 2em;
+    }
+
+    @media (min-width: 650px) {
+        ul.multi-column {
+            column-count: 3;
+        }
+    }
+
+    @media (min-width: 1200px) {
+        ul.multi-column {
+            column-count: 5;
+        }
+    }
     </style>
     `;
     var length = Object.keys(array['data']).length;
@@ -7879,11 +7896,11 @@ function buildPiholeItem(array){
     var totalQueries = function(data) {
 
         var card = `
-        <div class="col-lg-3 col-md-6 col-sm-6 col-xs-12">
+        <div class="col-lg-4 col-md-6 col-sm-6 col-xs-12">
             <div class="card text-white mb-3 pihole-stat bg-green">
                 <div class="card-body">
                     <div class="inline-block">
-                        <p class="d-inline mr-1">Total queries</p>`;
+                        <p class="d-inline mr-1">Total queries (last 24 hours)</p>`;
         for(var key in data) {
             var e = data[key];
             if(typeof e['FTLnotrunning'] == 'undefined'){
@@ -7892,7 +7909,7 @@ function buildPiholeItem(array){
 	            }
 				let value = 'Error';
 				if(e.length == undefined){
-					value = e['dns_queries_today'].toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
+                    value = e['sum_queries'].toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
 				}
 	            card += `<h3 data-toggle="tooltip" data-placement="right" title="`+key+`">`+value+`</h3>`;
 
@@ -7909,11 +7926,11 @@ function buildPiholeItem(array){
     };
     var totalBlocked = function(data) {
         var card = `
-        <div class="col-lg-3 col-md-6 col-sm-6 col-xs-12">
+        <div class="col-lg-4 col-md-6 col-sm-6 col-xs-12">
             <div class="card bg-inverse text-white mb-3 pihole-stat bg-aqua">
                 <div class="card-body">
                     <div class="inline-block">
-                        <p class="d-inline mr-1">Queries Blocked</p>`;
+                        <p class="d-inline mr-1">Queries Blocked (last 24 hours)</p>`;
         for(var key in data) {
             var e = data[key];
 	        if(typeof e['FTLnotrunning'] == 'undefined') {
@@ -7922,7 +7939,7 @@ function buildPiholeItem(array){
 		        }
 		        let value = 'Error';
 		        if(e.length == undefined){
-			        value = e['ads_blocked_today'].toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
+                    value = e['sum_blocked'].toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
 		        }
 		        card += `<h3 data-toggle="tooltip" data-placement="right" title="`+key+`">`+value+`</h3>`;
 			}
@@ -7938,11 +7955,11 @@ function buildPiholeItem(array){
     };
     var percentBlocked = function(data) {
         var card = `
-        <div class="col-lg-3 col-md-6 col-sm-6 col-xs-12">
+        <div class="col-lg-4 col-md-6 col-sm-6 col-xs-12">
             <div class="card bg-inverse text-white mb-3 pihole-stat bg-yellow">
                 <div class="card-body">
                     <div class="inline-block">
-                        <p class="d-inline mr-1">Percent Blocked</p>`;
+                        <p class="d-inline mr-1">Percent Blocked (last 24 hours)</p>`;
         for(var key in data) {
             var e = data[key];
 	        if(typeof e['FTLnotrunning'] == 'undefined') {
@@ -7951,7 +7968,7 @@ function buildPiholeItem(array){
 		        }
 		        let value = 'Error';
 		        if(e.length == undefined){
-			        value = e['ads_percentage_today'].toFixed(1)
+                    value = e['percent_blocked'].toFixed(1)
 		        }
 		        card += `<h3 data-toggle="tooltip" data-placement="right" title="`+key+`">`+value+`</h3>`;
 	        }
@@ -7967,11 +7984,11 @@ function buildPiholeItem(array){
     };
     var domainsBlocked = function(data) {
         var card = `
-        <div class="col-lg-3 col-md-6 col-sm-6 col-xs-12">
+        <div class="col-lg-12 col-md-12 col-sm-12 col-xs-12">
             <div class="card bg-inverse text-white mb-3 pihole-stat bg-red">
                 <div class="card-body">
                     <div class="inline-block">
-                        <p class="d-inline mr-1">Domains on Blocklist</p>`;
+                        <p class="d-inline mr-1">Domains on Blocklist (last 24 hours)</p>`;
         for(var key in data) {
             var e = data[key];
 	        if(typeof e['FTLnotrunning'] == 'undefined') {
@@ -7979,10 +7996,11 @@ function buildPiholeItem(array){
 			        card += `<p class="d-inline text-muted">(${key})</p>`;
 		        }
 		        let value = 'Error';
-		        if(e.length == undefined){
-			        value = e['domains_being_blocked'].toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")
+                    value = e['domains_being_blocked'].map(function (x) {
+                        return `<li>${x.toString()}</li>`;
+                    }).join("");
 		        }
-		        card += `<h3 data-toggle="tooltip" data-placement="right" title="`+key+`">`+value+`</h3>`;
+                card += `<ul class="multi-column" data-toggle="tooltip" title="` + key + `">` + value + `</ul>`;
 	        }
         }
         card += `