pihole6api 0.1.0__tar.gz → 0.1.2__tar.gz
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-0.1.0/src/pihole6api.egg-info → pihole6api-0.1.2}/PKG-INFO +3 -3
- {pihole6api-0.1.0 → pihole6api-0.1.2}/README.md +3 -3
- {pihole6api-0.1.0 → pihole6api-0.1.2}/pyproject.toml +1 -1
- {pihole6api-0.1.0 → pihole6api-0.1.2}/src/pihole6api/client.py +5 -1
- {pihole6api-0.1.0 → pihole6api-0.1.2}/src/pihole6api/config.py +47 -0
- {pihole6api-0.1.0 → pihole6api-0.1.2}/src/pihole6api/conn.py +12 -1
- pihole6api-0.1.2/src/pihole6api/metrics.py +189 -0
- {pihole6api-0.1.0 → pihole6api-0.1.2/src/pihole6api.egg-info}/PKG-INFO +3 -3
- pihole6api-0.1.0/src/pihole6api/metrics.py +0 -79
- {pihole6api-0.1.0 → pihole6api-0.1.2}/LICENSE +0 -0
- {pihole6api-0.1.0 → pihole6api-0.1.2}/setup.cfg +0 -0
- {pihole6api-0.1.0 → pihole6api-0.1.2}/src/pihole6api/__init__.py +0 -0
- {pihole6api-0.1.0 → pihole6api-0.1.2}/src/pihole6api/actions.py +0 -0
- {pihole6api-0.1.0 → pihole6api-0.1.2}/src/pihole6api/client_management.py +0 -0
- {pihole6api-0.1.0 → pihole6api-0.1.2}/src/pihole6api/dhcp.py +0 -0
- {pihole6api-0.1.0 → pihole6api-0.1.2}/src/pihole6api/dns_control.py +0 -0
- {pihole6api-0.1.0 → pihole6api-0.1.2}/src/pihole6api/domain_management.py +0 -0
- {pihole6api-0.1.0 → pihole6api-0.1.2}/src/pihole6api/ftl_info.py +0 -0
- {pihole6api-0.1.0 → pihole6api-0.1.2}/src/pihole6api/group_management.py +0 -0
- {pihole6api-0.1.0 → pihole6api-0.1.2}/src/pihole6api/list_management.py +0 -0
- {pihole6api-0.1.0 → pihole6api-0.1.2}/src/pihole6api/network_info.py +0 -0
- {pihole6api-0.1.0 → pihole6api-0.1.2}/src/pihole6api.egg-info/SOURCES.txt +0 -0
- {pihole6api-0.1.0 → pihole6api-0.1.2}/src/pihole6api.egg-info/dependency_links.txt +0 -0
- {pihole6api-0.1.0 → pihole6api-0.1.2}/src/pihole6api.egg-info/requires.txt +0 -0
- {pihole6api-0.1.0 → pihole6api-0.1.2}/src/pihole6api.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.2
|
2
2
|
Name: pihole6api
|
3
|
-
Version: 0.1.
|
3
|
+
Version: 0.1.2
|
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,4 +1,4 @@
|
|
1
|
-
# pihole6api
|
1
|
+
# 🍓 pihole6api
|
2
2
|
|
3
3
|
This package provides a simple, modular SDK for the PiHole 6 REST API.
|
4
4
|
|
@@ -30,7 +30,7 @@ pip install -e .
|
|
30
30
|
### Initialize the Client
|
31
31
|
|
32
32
|
```python
|
33
|
-
from pihole6api
|
33
|
+
from pihole6api import PiHole6Client
|
34
34
|
client = PiHole6Client("https://your-pihole.local/", "your-password")
|
35
35
|
```
|
36
36
|
|
@@ -109,4 +109,4 @@ client.actions.restart_dns()
|
|
109
109
|
|
110
110
|
## License
|
111
111
|
|
112
|
-
This project is license under the [MIT license](LICENSE).
|
112
|
+
This project is license under the [MIT license](LICENSE).
|
@@ -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()
|
@@ -1,4 +1,5 @@
|
|
1
1
|
import json
|
2
|
+
import urllib.parse
|
2
3
|
|
3
4
|
class PiHole6Configuration:
|
4
5
|
def __init__(self, connection):
|
@@ -77,3 +78,49 @@ class PiHole6Configuration:
|
|
77
78
|
:return: API response confirming the deletion.
|
78
79
|
"""
|
79
80
|
return self.connection.delete(f"config/{element}/{value}")
|
81
|
+
|
82
|
+
def add_local_a_record(self, host, ip):
|
83
|
+
"""
|
84
|
+
Add a local A record to Pi-hole.
|
85
|
+
|
86
|
+
:param host: The hostname (e.g., "foo.dev")
|
87
|
+
:param ip: The IP address (e.g., "192.168.1.1")
|
88
|
+
:return: API response
|
89
|
+
"""
|
90
|
+
encoded_value = urllib.parse.quote(f"{ip} {host}")
|
91
|
+
return self.connection.put(f"config/dns/hosts/{encoded_value}")
|
92
|
+
|
93
|
+
def remove_local_a_record(self, host, ip):
|
94
|
+
"""
|
95
|
+
Remove a local A record from Pi-hole.
|
96
|
+
|
97
|
+
:param host: The hostname (e.g., "foo.dev")
|
98
|
+
:param ip: The IP address (e.g., "192.168.1.1")
|
99
|
+
:return: API response
|
100
|
+
"""
|
101
|
+
encoded_value = urllib.parse.quote(f"{ip} {host}")
|
102
|
+
return self.connection.delete(f"config/dns/hosts/{encoded_value}")
|
103
|
+
|
104
|
+
def add_local_cname(self, host, target, ttl=300):
|
105
|
+
"""
|
106
|
+
Add a local CNAME record to Pi-hole.
|
107
|
+
|
108
|
+
:param host: The CNAME alias (e.g., "bar.xyz")
|
109
|
+
:param target: The target hostname (e.g., "foo.dev")
|
110
|
+
:param ttl: Time-to-live for the record (default: 300)
|
111
|
+
:return: API response
|
112
|
+
"""
|
113
|
+
encoded_value = urllib.parse.quote(f"{host},{target},{ttl}")
|
114
|
+
return self.connection.put(f"config/dns/cnameRecords/{encoded_value}")
|
115
|
+
|
116
|
+
def remove_local_cname(self, host, target, ttl=300):
|
117
|
+
"""
|
118
|
+
Remove a local CNAME record from Pi-hole.
|
119
|
+
|
120
|
+
:param host: The CNAME alias (e.g., "bar.xyz")
|
121
|
+
:param target: The target hostname (e.g., "foo.dev")
|
122
|
+
:param ttl: Time-to-live for the record (default: 300)
|
123
|
+
:return: API response
|
124
|
+
"""
|
125
|
+
encoded_value = urllib.parse.quote(f"{host},{target},{ttl}")
|
126
|
+
return self.connection.delete(f"config/dns/cnameRecords/{encoded_value}")
|
@@ -124,4 +124,15 @@ class PiHole6Connection:
|
|
124
124
|
|
125
125
|
def patch(self, endpoint, data=None):
|
126
126
|
"""Send a PATCH request."""
|
127
|
-
return self._do_call("PATCH", endpoint, data=data)
|
127
|
+
return self._do_call("PATCH", endpoint, data=data)
|
128
|
+
|
129
|
+
def exit(self):
|
130
|
+
"""Delete the current session."""
|
131
|
+
response = self.delete("auth")
|
132
|
+
|
133
|
+
# Clear stored session info
|
134
|
+
self.session_id = None
|
135
|
+
self.csrf_token = None
|
136
|
+
self.validity = None
|
137
|
+
|
138
|
+
return response
|
@@ -0,0 +1,189 @@
|
|
1
|
+
class PiHole6Metrics:
|
2
|
+
def __init__(self, connection):
|
3
|
+
"""
|
4
|
+
Handles Pi-hole metrics and stats API endpoints.
|
5
|
+
:param connection: Instance of PiHole6Connection for API requests.
|
6
|
+
"""
|
7
|
+
self.connection = connection
|
8
|
+
|
9
|
+
# History API Endpoints
|
10
|
+
def get_history(self):
|
11
|
+
"""Get activity graph data"""
|
12
|
+
return self.connection.get("history")
|
13
|
+
|
14
|
+
def get_history_clients(self, clients=20):
|
15
|
+
"""
|
16
|
+
Get per-client activity graph data
|
17
|
+
|
18
|
+
:param num: Number of clients to return, 0 will return all clients
|
19
|
+
"""
|
20
|
+
params = {"n": clients}
|
21
|
+
return self.connection.get("history/clients", params=params)
|
22
|
+
|
23
|
+
def get_history_database(self, start, end):
|
24
|
+
"""
|
25
|
+
Get long-term activity graph data
|
26
|
+
|
27
|
+
:param start: Start date in unix timestamp format
|
28
|
+
:param end: End date in unix timestamp format
|
29
|
+
"""
|
30
|
+
params = {"from": start, "until": end}
|
31
|
+
return self.connection.get("history/database", params=params)
|
32
|
+
|
33
|
+
def get_history_database_clients(self, start, end):
|
34
|
+
"""
|
35
|
+
Get per-client long-term activity graph data
|
36
|
+
|
37
|
+
:param start: Start date in unix timestamp format
|
38
|
+
:param end: End date in unix timestamp format
|
39
|
+
"""
|
40
|
+
params = {"from": start, "until": end}
|
41
|
+
return self.connection.get("history/database/clients", params=params)
|
42
|
+
|
43
|
+
# Query API Endpoints
|
44
|
+
def get_queries(self, n=100, from_ts=None, until_ts=None, upstream=None, domain=None, client=None, cursor=None):
|
45
|
+
"""
|
46
|
+
Get query log with optional filtering parameters.
|
47
|
+
|
48
|
+
:param int n: Number of queries to retrieve (default: 100).
|
49
|
+
:param int from_ts: Unix timestamp to filter queries from this time onward (optional).
|
50
|
+
:param int until_ts: Unix timestamp to filter queries up to this time (optional).
|
51
|
+
:param str upstream: Filter queries sent to a specific upstream destination (optional).
|
52
|
+
:param str domain: Filter queries for specific domains, supports wildcards `*` (optional).
|
53
|
+
:param str client: Filter queries originating from a specific client (optional).
|
54
|
+
:param str cursor: Cursor for pagination to fetch the next chunk of results (optional).
|
55
|
+
"""
|
56
|
+
params = {
|
57
|
+
"n": n,
|
58
|
+
"from": from_ts,
|
59
|
+
"until": until_ts,
|
60
|
+
"upstream": upstream,
|
61
|
+
"domain": domain,
|
62
|
+
"client": client,
|
63
|
+
"cursor": cursor
|
64
|
+
}
|
65
|
+
params = {k: v for k, v in params.items() if v is not None}
|
66
|
+
return self.connection.get("queries", params=params)
|
67
|
+
|
68
|
+
|
69
|
+
def get_query_suggestions(self):
|
70
|
+
"""Get query filter suggestions"""
|
71
|
+
return self.connection.get("queries/suggestions")
|
72
|
+
|
73
|
+
# Stats Database API Endpoints
|
74
|
+
def get_stats_database_query_types(self, start, end):
|
75
|
+
"""
|
76
|
+
Get query types (long-term database)
|
77
|
+
|
78
|
+
:param start: Start date in unix timestamp format
|
79
|
+
:param end: End date in unix timestamp format
|
80
|
+
"""
|
81
|
+
params = {"from": start, "until": end}
|
82
|
+
return self.connection.get("stats/database/query_types", params=params)
|
83
|
+
|
84
|
+
def get_stats_database_summary(self, start, end):
|
85
|
+
"""
|
86
|
+
Get database content details
|
87
|
+
|
88
|
+
:param start: Start date in unix timestamp format
|
89
|
+
:param end: End date in unix timestamp format
|
90
|
+
"""
|
91
|
+
params = {"from": start, "until": end}
|
92
|
+
return self.connection.get("stats/database/summary", params=params)
|
93
|
+
|
94
|
+
def get_stats_database_top_clients(self, start, end, blocked=None, count=None):
|
95
|
+
"""
|
96
|
+
Get top clients (long-term database).
|
97
|
+
|
98
|
+
:param int start: Start date in Unix timestamp format.
|
99
|
+
:param int end: End date in Unix timestamp format.
|
100
|
+
:param bool blocked: Return information about permitted or blocked queries (optional).
|
101
|
+
:param int count: Number of requested items (optional).
|
102
|
+
"""
|
103
|
+
params = {
|
104
|
+
"from": start,
|
105
|
+
"until": end,
|
106
|
+
"blocked": str(blocked).lower() if blocked is not None else None,
|
107
|
+
"count": count
|
108
|
+
}
|
109
|
+
params = {k: v for k, v in params.items() if v is not None}
|
110
|
+
return self.connection.get("stats/database/top_clients", params=params)
|
111
|
+
|
112
|
+
def get_stats_database_top_domains(self, start, end, blocked=None, count=None):
|
113
|
+
"""
|
114
|
+
Get top domains (long-term database)
|
115
|
+
|
116
|
+
:param int start: Start date in Unix timestamp format.
|
117
|
+
:param int end: End date in Unix timestamp format.
|
118
|
+
:param bool blocked: Return information about permitted or blocked queries (optional).
|
119
|
+
:param int count: Number of requested items (optional).
|
120
|
+
"""
|
121
|
+
params = {
|
122
|
+
"from": start,
|
123
|
+
"until": end,
|
124
|
+
"blocked": str(blocked).lower() if blocked is not None else None,
|
125
|
+
"count": count
|
126
|
+
}
|
127
|
+
params = {k: v for k, v in params.items() if v is not None}
|
128
|
+
return self.connection.get("stats/database/top_domains", params=params)
|
129
|
+
|
130
|
+
def get_stats_database_upstreams(self, start, end):
|
131
|
+
"""
|
132
|
+
Get upstream metrics (long-term database)
|
133
|
+
|
134
|
+
:param start: Start date in unix timestamp format
|
135
|
+
:param end: End date in unix timestamp format
|
136
|
+
"""
|
137
|
+
params = {"from": start, "until": end}
|
138
|
+
return self.connection.get("stats/database/upstreams", params=params)
|
139
|
+
|
140
|
+
# Stats API Endpoints
|
141
|
+
def get_stats_query_types(self):
|
142
|
+
"""Get current query types"""
|
143
|
+
return self.connection.get("stats/query_types")
|
144
|
+
|
145
|
+
def get_stats_recent_blocked(self, count=None):
|
146
|
+
"""
|
147
|
+
Get most recently blocked domain
|
148
|
+
|
149
|
+
:param int count: Number of requested items (optional).
|
150
|
+
"""
|
151
|
+
params = {"count": count}
|
152
|
+
params = {k: v for k, v in params.items() if v is not None}
|
153
|
+
return self.connection.get("stats/recent_blocked", params=params)
|
154
|
+
|
155
|
+
def get_stats_summary(self):
|
156
|
+
"""Get an overview of Pi-hole activity"""
|
157
|
+
return self.connection.get("stats/summary")
|
158
|
+
|
159
|
+
def get_stats_top_clients(self, blocked=None, count=None):
|
160
|
+
"""
|
161
|
+
Get top clients
|
162
|
+
|
163
|
+
:param bool blocked: Return information about permitted or blocked queries (optional).
|
164
|
+
:param int count: Number of requested items (optional).
|
165
|
+
"""
|
166
|
+
params = {
|
167
|
+
"blocked": str(blocked).lower() if blocked is not None else None,
|
168
|
+
"count": count
|
169
|
+
}
|
170
|
+
params = {k: v for k, v in params.items() if v is not None}
|
171
|
+
return self.connection.get("stats/top_clients", params=params)
|
172
|
+
|
173
|
+
def get_stats_top_domains(self, blocked=None, count=None):
|
174
|
+
"""
|
175
|
+
Get top domains
|
176
|
+
|
177
|
+
:param bool blocked: Return information about permitted or blocked queries (optional).
|
178
|
+
:param int count: Number of requested items (optional).
|
179
|
+
"""
|
180
|
+
params = {
|
181
|
+
"blocked": str(blocked).lower() if blocked is not None else None,
|
182
|
+
"count": count
|
183
|
+
}
|
184
|
+
params = {k: v for k, v in params.items() if v is not None}
|
185
|
+
return self.connection.get("stats/top_domains", params=params)
|
186
|
+
|
187
|
+
def get_stats_upstreams(self):
|
188
|
+
"""Get upstream destinations"""
|
189
|
+
return self.connection.get("stats/upstreams")
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.2
|
2
2
|
Name: pihole6api
|
3
|
-
Version: 0.1.
|
3
|
+
Version: 0.1.2
|
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,79 +0,0 @@
|
|
1
|
-
class PiHole6Metrics:
|
2
|
-
def __init__(self, connection):
|
3
|
-
"""
|
4
|
-
Handles Pi-hole metrics and stats API endpoints.
|
5
|
-
:param connection: Instance of PiHole6Connection for API requests.
|
6
|
-
"""
|
7
|
-
self.connection = connection
|
8
|
-
|
9
|
-
# History API Endpoints
|
10
|
-
def get_history(self):
|
11
|
-
"""Get activity graph data"""
|
12
|
-
return self.connection.get("history")
|
13
|
-
|
14
|
-
def get_history_clients(self):
|
15
|
-
"""Get per-client activity graph data"""
|
16
|
-
return self.connection.get("history/clients")
|
17
|
-
|
18
|
-
def get_history_database(self):
|
19
|
-
"""Get long-term activity graph data"""
|
20
|
-
return self.connection.get("history/database")
|
21
|
-
|
22
|
-
def get_history_database_clients(self):
|
23
|
-
"""Get per-client long-term activity graph data"""
|
24
|
-
return self.connection.get("history/database/clients")
|
25
|
-
|
26
|
-
# Query API Endpoints
|
27
|
-
def get_queries(self):
|
28
|
-
"""Get query log"""
|
29
|
-
return self.connection.get("queries")
|
30
|
-
|
31
|
-
def get_query_suggestions(self):
|
32
|
-
"""Get query filter suggestions"""
|
33
|
-
return self.connection.get("queries/suggestions")
|
34
|
-
|
35
|
-
# Stats Database API Endpoints
|
36
|
-
def get_stats_database_query_types(self):
|
37
|
-
"""Get query types (long-term database)"""
|
38
|
-
return self.connection.get("stats/database/query_types")
|
39
|
-
|
40
|
-
def get_stats_database_summary(self):
|
41
|
-
"""Get database content details"""
|
42
|
-
return self.connection.get("stats/database/summary")
|
43
|
-
|
44
|
-
def get_stats_database_top_clients(self):
|
45
|
-
"""Get top clients (long-term database)"""
|
46
|
-
return self.connection.get("stats/database/top_clients")
|
47
|
-
|
48
|
-
def get_stats_database_top_domains(self):
|
49
|
-
"""Get top domains (long-term database)"""
|
50
|
-
return self.connection.get("stats/database/top_domains")
|
51
|
-
|
52
|
-
def get_stats_database_upstreams(self):
|
53
|
-
"""Get upstream metrics (long-term database)"""
|
54
|
-
return self.connection.get("stats/database/upstreams")
|
55
|
-
|
56
|
-
# Stats API Endpoints
|
57
|
-
def get_stats_query_types(self):
|
58
|
-
"""Get current query types"""
|
59
|
-
return self.connection.get("stats/query_types")
|
60
|
-
|
61
|
-
def get_stats_recent_blocked(self):
|
62
|
-
"""Get most recently blocked domain"""
|
63
|
-
return self.connection.get("stats/recent_blocked")
|
64
|
-
|
65
|
-
def get_stats_summary(self):
|
66
|
-
"""Get an overview of Pi-hole activity"""
|
67
|
-
return self.connection.get("stats/summary")
|
68
|
-
|
69
|
-
def get_stats_top_clients(self):
|
70
|
-
"""Get top clients"""
|
71
|
-
return self.connection.get("stats/top_clients")
|
72
|
-
|
73
|
-
def get_stats_top_domains(self):
|
74
|
-
"""Get top domains"""
|
75
|
-
return self.connection.get("stats/top_domains")
|
76
|
-
|
77
|
-
def get_stats_upstreams(self):
|
78
|
-
"""Get upstream destinations"""
|
79
|
-
return self.connection.get("stats/upstreams")
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|