From a502e6387fe63aec2c6e52f1c9f514199670bd02 Mon Sep 17 00:00:00 2001
From: anima
Date: Fri, 7 Mar 2025 18:22:35 +0100
Subject: [PATCH] add basic config handling and custom dns mgmt
---
PiholeAPI.py | 126 +++++++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 123 insertions(+), 3 deletions(-)
diff --git a/PiholeAPI.py b/PiholeAPI.py
index bcccfb4..ad8de48 100644
--- a/PiholeAPI.py
+++ b/PiholeAPI.py
@@ -38,7 +38,7 @@ class PiholeAPI:
headers = dict()
# check if http method valid
- valid_methods = ['GET', 'POST', 'PUT', 'DELETE']
+ valid_methods = ['GET', 'POST', 'PUT', 'PATCH', 'DELETE']
if method not in valid_methods:
logging.error(f'http {method=} is none of {valid_methods=}')
return False
@@ -275,11 +275,131 @@ class PiholeAPI:
data = self.__query('stats/upstreams')
print(data)
+ #
+ ## confg methods
+ #
+ def get_config(self, element: str = None) -> dict | None:
+ """Get current configuration of your Pi-hole.
+
+ Can be use to modify and dump back via self.patch_config(config)
+
+ Args:
+ element (str, optional): define sub elements of config. Defaults to None.
+
+ Returns:
+ dict | None: if successfull : dict with config (sub elements)
+ """
+ if element:
+ data = self.__query(f'config/{element}')
+ else:
+ data = self.__query('config')
+
+ return data
+
+ def patch_config(self, config: dict) -> bool:
+ """Change configuration of your Pi-hole
+
+ Args:
+ config (dict): new config to push
+
+ Returns:
+ bool: true if query send successfull
+ """
+ if not 'config' in config.keys():
+ return False
+ payload = config
+ data = self.__query('config', 'PATCH', payload=payload)
+ if data:
+ return True
+ return False
+
+ def get_dns_host(self, host: list[str, str], match_ip: bool = True, match_fqdn: bool = True) -> list[list[str, str]] | None:
+ """get specific dns host from custom dns records
+
+ Args:
+ host (list[str, str]): list with [ip, fqdn]
+ match_ip (bool, optional): controls if ip will be check. Defaults to True.
+ match_fqdn (bool, optional): controls if fqdn will be check. Defaults to True.
+
+ Returns:
+ list[list[str, str]] | None: list with results of found hosts [[ip, fqdn], [ip, fqdn]]
+ """
+ if isinstance(host, list) and len(host) != 2:
+ return None
+ data = self.get_config('dns/hosts')
+ if not data:
+ return None
+
+ results = list()
+ for entry in data['config']['dns']['hosts']:
+ entry_host = entry.split(' ')
+ if (not match_ip or entry_host[0] == host[0]) and (not match_fqdn or entry_host[1] == host[1]):
+ results.append(entry_host)
+
+ return results
+
+ def add_dns_host(self, host: list[str, str]) -> bool:
+ """add a new custom dns record
+
+ Args:
+ host (list[str, str]): list with [ip, fqdn]
+
+ Returns:
+ bool: True if new entry exists or new created
+ """
+ if not isinstance(host, list) and len(host) != 2:
+ return False
+ data = self.get_config('dns/hosts')
+ if not data:
+ return False
+
+ create_new = True
+ results = self.get_dns_host(host)
+ if results:
+ for result in results:
+ if result == host:
+ create_new = False
+
+ if create_new:
+ data['config']['dns']['hosts'].append(' '.join(host))
+ return self.patch_config(data)
+ else:
+ return True
+
+ def remove_dns_host(self, host: list[str, str], match_ip: bool = True, match_fqdn: bool = True) -> bool:
+ """remove given host
+
+ Args:
+ host (list[str, str]): list with [ip, fqdn]
+ match_ip (bool, optional): controls if ip will be check. Defaults to True.
+ match_fqdn (bool, optional): controls if fqdn will be check. Defaults to True.
+
+ Returns:
+ bool: True if host(s) successfull removed
+ """
+ if not isinstance(host, list) and len(host) != 2:
+ return False
+ data = self.get_config('dns/hosts')
+ if not data:
+ return False
+
+ hosts = data['config']['dns']['hosts'][::]
+ for entry in data['config']['dns']['hosts']:
+ entry_host = entry.split(' ')
+ if (not match_ip or entry_host[0] == host[0]) and (not match_fqdn or entry_host[1] == host[1]):
+ hosts.remove(entry)
+
+ data['config']['dns']['hosts'] = hosts
+ return self.patch_config(data)
+
+
def main():
pi = PiholeAPI()
pi.clear_sessions()
- pi.get_upstrams()
-
+ config = pi.get_config()
+ print(config)
+ hosts = pi.get_dns_host(['', 'myhost.example.org'], match_fqdn=False)
+ print(hosts)
if __name__ == '__main__':
main()
\ No newline at end of file