pihole6api 0.1.0__py3-none-any.whl → 0.1.1__py3-none-any.whl
Sign up to get free protection for your applications and to get access to all the features.
- pihole6api/config.py +47 -0
- pihole6api/metrics.py +148 -38
- {pihole6api-0.1.0.dist-info → pihole6api-0.1.1.dist-info}/METADATA +1 -1
- {pihole6api-0.1.0.dist-info → pihole6api-0.1.1.dist-info}/RECORD +7 -7
- {pihole6api-0.1.0.dist-info → pihole6api-0.1.1.dist-info}/LICENSE +0 -0
- {pihole6api-0.1.0.dist-info → pihole6api-0.1.1.dist-info}/WHEEL +0 -0
- {pihole6api-0.1.0.dist-info → pihole6api-0.1.1.dist-info}/top_level.txt +0 -0
pihole6api/config.py
CHANGED
@@ -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}")
|
pihole6api/metrics.py
CHANGED
@@ -11,68 +11,178 @@ class PiHole6Metrics:
|
|
11
11
|
"""Get activity graph data"""
|
12
12
|
return self.connection.get("history")
|
13
13
|
|
14
|
-
def get_history_clients(self):
|
15
|
-
"""
|
16
|
-
|
14
|
+
def get_history_clients(self, clients=20):
|
15
|
+
"""
|
16
|
+
Get per-client activity graph data
|
17
17
|
|
18
|
-
|
19
|
-
"""
|
20
|
-
|
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)
|
21
22
|
|
22
|
-
def
|
23
|
-
"""
|
24
|
-
|
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)
|
25
42
|
|
26
43
|
# Query API Endpoints
|
27
|
-
def get_queries(self):
|
28
|
-
"""
|
29
|
-
|
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
|
+
|
30
68
|
|
31
69
|
def get_query_suggestions(self):
|
32
70
|
"""Get query filter suggestions"""
|
33
71
|
return self.connection.get("queries/suggestions")
|
34
72
|
|
35
73
|
# Stats Database API Endpoints
|
36
|
-
def get_stats_database_query_types(self):
|
37
|
-
"""
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
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)
|
43
83
|
|
44
|
-
def
|
45
|
-
"""
|
46
|
-
|
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)
|
47
93
|
|
48
|
-
def
|
49
|
-
"""
|
50
|
-
|
94
|
+
def get_stats_database_top_clients(self, start, end, blocked=None, count=None):
|
95
|
+
"""
|
96
|
+
Get top clients (long-term database).
|
51
97
|
|
52
|
-
|
53
|
-
|
54
|
-
|
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)
|
55
139
|
|
56
140
|
# Stats API Endpoints
|
57
141
|
def get_stats_query_types(self):
|
58
142
|
"""Get current query types"""
|
59
143
|
return self.connection.get("stats/query_types")
|
60
144
|
|
61
|
-
def get_stats_recent_blocked(self):
|
62
|
-
"""
|
63
|
-
|
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)
|
64
154
|
|
65
155
|
def get_stats_summary(self):
|
66
156
|
"""Get an overview of Pi-hole activity"""
|
67
157
|
return self.connection.get("stats/summary")
|
68
158
|
|
69
|
-
def get_stats_top_clients(self):
|
70
|
-
"""
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
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)
|
76
186
|
|
77
187
|
def get_stats_upstreams(self):
|
78
188
|
"""Get upstream destinations"""
|
@@ -2,7 +2,7 @@ pihole6api/__init__.py,sha256=OKDAH2I6UjXcBmcj6rn5aNg5J60GCUBVFJ-_t83GiVQ,898
|
|
2
2
|
pihole6api/actions.py,sha256=8CBkr8nYfT8yfdCO6F9M9nompaYcFdsaYGiEa1eVDCw,693
|
3
3
|
pihole6api/client.py,sha256=IgUjiBUx_EFzQujgQZcX2h9dfDfI83aVeipUeStHWY0,1855
|
4
4
|
pihole6api/client_management.py,sha256=opPYGrjuW6SiwuxuvoOxnqjpmflU2znKHsqFbGSS3Gg,2439
|
5
|
-
pihole6api/config.py,sha256=
|
5
|
+
pihole6api/config.py,sha256=NdBHOudz147oIs5YVR3U4WLvqk3hU3HlZHnshy1NK4g,4680
|
6
6
|
pihole6api/conn.py,sha256=sYjS8Gvk2GuA482eyvFknTKgeeesLnS5ylI9I4yUNRo,4581
|
7
7
|
pihole6api/dhcp.py,sha256=1A3z-3q9x51-6MOC3JMl7yR_5pHmRxZtMWtPqzWxYm0,629
|
8
8
|
pihole6api/dns_control.py,sha256=mxV3AIuGCsx0-1ibpMXor9QUGd_fDFfeaUENPhIK_TY,853
|
@@ -10,10 +10,10 @@ pihole6api/domain_management.py,sha256=vxhQSG5F8EFDGqtiNkF0H_KOWFMerXaAuJZT0nMa8
|
|
10
10
|
pihole6api/ftl_info.py,sha256=e9W9vwkF8nHzjVlHpIMe-55qhhQngMj0swMlp2QNvPg,2540
|
11
11
|
pihole6api/group_management.py,sha256=MGHwegw-b9U9PIA-IBzqT-a1kYkpXyjfSXJJJjkyTxc,2225
|
12
12
|
pihole6api/list_management.py,sha256=B98FdgsIZhfRJHRxtRmwWsRPJ4rGlhvN-9gFEGdbb-c,3396
|
13
|
-
pihole6api/metrics.py,sha256=
|
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.1.dist-info/LICENSE,sha256=hpO6J6J9O1VZxZeHQTxKMTmuobaHbApiZxp279I4xNU,1062
|
16
|
+
pihole6api-0.1.1.dist-info/METADATA,sha256=GzNFEKppAIpUn6xgmxZPoMhrmtRkMzNgFIOVhKqXkbo,3839
|
17
|
+
pihole6api-0.1.1.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
|
18
|
+
pihole6api-0.1.1.dist-info/top_level.txt,sha256=Qrh46lxEC54rBR8T53em-tuZLWbmi1SDwL1rOhsgrME,11
|
19
|
+
pihole6api-0.1.1.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|