pihole6api 0.1.1__py3-none-any.whl → 0.1.3__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pihole6api/client.py +5 -1
- pihole6api/conn.py +47 -14
- {pihole6api-0.1.1.dist-info → pihole6api-0.1.3.dist-info}/METADATA +3 -3
- {pihole6api-0.1.1.dist-info → pihole6api-0.1.3.dist-info}/RECORD +7 -7
- {pihole6api-0.1.1.dist-info → pihole6api-0.1.3.dist-info}/LICENSE +0 -0
- {pihole6api-0.1.1.dist-info → pihole6api-0.1.3.dist-info}/WHEEL +0 -0
- {pihole6api-0.1.1.dist-info → pihole6api-0.1.3.dist-info}/top_level.txt +0 -0
pihole6api/client.py
CHANGED
@@ -41,4 +41,8 @@ class PiHole6Client:
|
|
41
41
|
:param full: Boolean flag to get the full dataset.
|
42
42
|
:return: API response containing PADD summary.
|
43
43
|
"""
|
44
|
-
return self.connection.get("padd", params={"full": str(full).lower()})
|
44
|
+
return self.connection.get("padd", params={"full": str(full).lower()})
|
45
|
+
|
46
|
+
def close_session(self):
|
47
|
+
"""Close the Pi-hole session by calling the exit method in the connection."""
|
48
|
+
return self.connection.exit()
|
pihole6api/conn.py
CHANGED
@@ -2,6 +2,7 @@ import requests
|
|
2
2
|
import urllib3
|
3
3
|
from urllib.parse import urljoin
|
4
4
|
import warnings
|
5
|
+
import time
|
5
6
|
|
6
7
|
# Suppress InsecureRequestWarning
|
7
8
|
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
|
@@ -25,22 +26,43 @@ class PiHole6Connection:
|
|
25
26
|
self._authenticate()
|
26
27
|
|
27
28
|
def _authenticate(self):
|
28
|
-
"""Authenticate with the Pi-hole API and store session ID and CSRF token.
|
29
|
+
"""Authenticate with the Pi-hole API and store session ID and CSRF token.
|
30
|
+
|
31
|
+
Retries up to three times (with a one-second pause between attempts)
|
32
|
+
before raising an exception.
|
33
|
+
"""
|
29
34
|
auth_url = urljoin(self.base_url, "auth")
|
30
35
|
payload = {"password": self.password}
|
36
|
+
max_attempts = 3
|
37
|
+
last_exception = None
|
31
38
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
39
|
+
for attempt in range(1, max_attempts + 1):
|
40
|
+
response = requests.post(auth_url, json=payload, verify=False)
|
41
|
+
try:
|
42
|
+
if response.status_code == 200:
|
43
|
+
data = response.json()
|
44
|
+
if "session" in data and data["session"]["valid"]:
|
45
|
+
self.session_id = data["session"]["sid"]
|
46
|
+
self.csrf_token = data["session"]["csrf"]
|
47
|
+
self.validity = data["session"]["validity"]
|
48
|
+
return # Successful authentication
|
49
|
+
else:
|
50
|
+
last_exception = Exception("Authentication failed: Invalid session response")
|
51
|
+
else:
|
52
|
+
# Try to extract an error message from the response
|
53
|
+
try:
|
54
|
+
error_msg = response.json().get("error", {}).get("message", "Unknown error")
|
55
|
+
except (json.decoder.JSONDecodeError, ValueError):
|
56
|
+
error_msg = f"HTTP {response.status_code}: {response.reason}"
|
57
|
+
last_exception = Exception(f"Authentication failed: {error_msg}")
|
58
|
+
except Exception as e:
|
59
|
+
last_exception = e
|
60
|
+
|
61
|
+
if attempt < max_attempts:
|
62
|
+
time.sleep(1) # Pause before retrying
|
63
|
+
|
64
|
+
# All attempts failed; raise the last captured exception.
|
65
|
+
raise last_exception
|
44
66
|
|
45
67
|
def _get_headers(self):
|
46
68
|
"""Return headers including the authentication SID and CSRF token."""
|
@@ -124,4 +146,15 @@ class PiHole6Connection:
|
|
124
146
|
|
125
147
|
def patch(self, endpoint, data=None):
|
126
148
|
"""Send a PATCH request."""
|
127
|
-
return self._do_call("PATCH", endpoint, data=data)
|
149
|
+
return self._do_call("PATCH", endpoint, data=data)
|
150
|
+
|
151
|
+
def exit(self):
|
152
|
+
"""Delete the current session."""
|
153
|
+
response = self.delete("auth")
|
154
|
+
|
155
|
+
# Clear stored session info
|
156
|
+
self.session_id = None
|
157
|
+
self.csrf_token = None
|
158
|
+
self.validity = None
|
159
|
+
|
160
|
+
return response
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.2
|
2
2
|
Name: pihole6api
|
3
|
-
Version: 0.1.
|
3
|
+
Version: 0.1.3
|
4
4
|
Summary: Python API Client for Pi-hole 6
|
5
5
|
Author-email: Shane Barbetta <shane@barbetta.me>
|
6
6
|
License: MIT
|
@@ -23,7 +23,7 @@ Description-Content-Type: text/markdown
|
|
23
23
|
License-File: LICENSE
|
24
24
|
Requires-Dist: requests>=2.26.0
|
25
25
|
|
26
|
-
# pihole6api
|
26
|
+
# 🍓 pihole6api
|
27
27
|
|
28
28
|
This package provides a simple, modular SDK for the PiHole 6 REST API.
|
29
29
|
|
@@ -55,7 +55,7 @@ pip install -e .
|
|
55
55
|
### Initialize the Client
|
56
56
|
|
57
57
|
```python
|
58
|
-
from pihole6api
|
58
|
+
from pihole6api import PiHole6Client
|
59
59
|
client = PiHole6Client("https://your-pihole.local/", "your-password")
|
60
60
|
```
|
61
61
|
|
@@ -1,9 +1,9 @@
|
|
1
1
|
pihole6api/__init__.py,sha256=OKDAH2I6UjXcBmcj6rn5aNg5J60GCUBVFJ-_t83GiVQ,898
|
2
2
|
pihole6api/actions.py,sha256=8CBkr8nYfT8yfdCO6F9M9nompaYcFdsaYGiEa1eVDCw,693
|
3
|
-
pihole6api/client.py,sha256=
|
3
|
+
pihole6api/client.py,sha256=HYdRh3CSZJ0srbkpjIVnLo-iy1avqKDUne5ji2Aq394,2013
|
4
4
|
pihole6api/client_management.py,sha256=opPYGrjuW6SiwuxuvoOxnqjpmflU2znKHsqFbGSS3Gg,2439
|
5
5
|
pihole6api/config.py,sha256=NdBHOudz147oIs5YVR3U4WLvqk3hU3HlZHnshy1NK4g,4680
|
6
|
-
pihole6api/conn.py,sha256=
|
6
|
+
pihole6api/conn.py,sha256=qqC-PO6a2RR_dluhSeu_RMeo6TpA8_Xlg5CA2FTwG7Y,5825
|
7
7
|
pihole6api/dhcp.py,sha256=1A3z-3q9x51-6MOC3JMl7yR_5pHmRxZtMWtPqzWxYm0,629
|
8
8
|
pihole6api/dns_control.py,sha256=mxV3AIuGCsx0-1ibpMXor9QUGd_fDFfeaUENPhIK_TY,853
|
9
9
|
pihole6api/domain_management.py,sha256=vxhQSG5F8EFDGqtiNkF0H_KOWFMerXaAuJZT0nMa8ec,3492
|
@@ -12,8 +12,8 @@ pihole6api/group_management.py,sha256=MGHwegw-b9U9PIA-IBzqT-a1kYkpXyjfSXJJJjkyTx
|
|
12
12
|
pihole6api/list_management.py,sha256=B98FdgsIZhfRJHRxtRmwWsRPJ4rGlhvN-9gFEGdbb-c,3396
|
13
13
|
pihole6api/metrics.py,sha256=czNyx9tUf2yZi_HnUpqykrtW51c042Rxq3zFl2_GjLY,7379
|
14
14
|
pihole6api/network_info.py,sha256=u5NIteFoI-yav05eE6v81-9gs3MeZVBlNCSBS5gzCT8,1006
|
15
|
-
pihole6api-0.1.
|
16
|
-
pihole6api-0.1.
|
17
|
-
pihole6api-0.1.
|
18
|
-
pihole6api-0.1.
|
19
|
-
pihole6api-0.1.
|
15
|
+
pihole6api-0.1.3.dist-info/LICENSE,sha256=hpO6J6J9O1VZxZeHQTxKMTmuobaHbApiZxp279I4xNU,1062
|
16
|
+
pihole6api-0.1.3.dist-info/METADATA,sha256=JMgYTLowrNI52DPCEaVpBIqiD4NHBX9av86qJLQ8-wg,3837
|
17
|
+
pihole6api-0.1.3.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
|
18
|
+
pihole6api-0.1.3.dist-info/top_level.txt,sha256=Qrh46lxEC54rBR8T53em-tuZLWbmi1SDwL1rOhsgrME,11
|
19
|
+
pihole6api-0.1.3.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|