From 179367f0120bd02749a891aa2a46fb63615eea7e Mon Sep 17 00:00:00 2001 From: Simon Date: Sun, 6 Oct 2024 20:17:29 +0200 Subject: [PATCH 1/8] Started to implement datetime for last successful update Bumped requirements.txt --- config.example.json | 5 ++++- owl/dns_functions.py | 19 +++++++++++++++---- owl/template.html.jinja | 3 +++ requirements.txt | 6 +++--- 4 files changed, 25 insertions(+), 8 deletions(-) diff --git a/config.example.json b/config.example.json index 6a7344d..3001e3e 100644 --- a/config.example.json +++ b/config.example.json @@ -3,7 +3,10 @@ "ENABLE_WEBSERVER": true, "WEBSERVER_PORT": 8000, "NOTIFY_SERVER": "https:///", - "ENABLE_NOTIFICATIONS": false, + "NOTIFICATIONS": { + "ENABLE_NOTIFICATIONS": true, + "ENABLE_NOTIFICATION_NO_CHANGE": false + }, "ZONE_ID": "your_zone_id", "USER_EMAIL": "name.lastname@mail.com", "API_KEY": "your_CF_API_key", diff --git a/owl/dns_functions.py b/owl/dns_functions.py index 85488dd..de7a62b 100644 --- a/owl/dns_functions.py +++ b/owl/dns_functions.py @@ -4,9 +4,10 @@ from .notifications import Notifier from .config import load_config from .webserver import write_to_template +from datetime import datetime -if load_config('./config.json')['ENABLE_NOTIFICATIONS']: +if load_config('./config.json')['NOTIFICATIONS']['ENABLE_NOTIFICATIONS']: notification_service = Notifier() else: notification_service = None @@ -92,11 +93,17 @@ def update_all_ip(current_ip): check = compare_ip(current_ip, domain_ip) domain['OLD_IP'] = domain_ip if check: - print(f"\tIP for domain: {domain['RECORD_NAME']} is {domain_ip} which is the current public IP {current_ip}. No Update necessary!") if notification_service: - notification_service.send_success(f"\tIP for domain: {domain['RECORD_NAME']} is {domain_ip} which is the current public IP {current_ip}. No Update necessary!") + if data['NOTIFICATIONS']['ENABLE_NOTIFICATION_NO_CHANGE']: + print(f"\tIP for domain: {domain['RECORD_NAME']} is {domain_ip} which is the current public IP {current_ip}. No Update necessary!") + notification_service.send_success(f"\tIP for domain: {domain['RECORD_NAME']} is {domain_ip} which is the current public IP {current_ip}. No Update necessary!") + else: + print(f"\tIP for domain: {domain['RECORD_NAME']} is {domain_ip} which is the current public IP {current_ip}. No Update necessary! No Notification send due to configuration!") domain['NEW_IP'] = domain_ip domain['RESULT'] = f"No change" + ### Placeholder + ### Needs some work to load time from last successful update + domain['LAST_UPDATE'] = datetime.now() else: print(f"\tUpdating DynDNS IP for domain: {domain['RECORD_NAME']}...") response = set_ip(cf, domain, current_ip) @@ -107,6 +114,7 @@ def update_all_ip(current_ip): notification_service.send_success(f"IP for domain {domain['RECORD_NAME']} was successfully set to {current_ip}. Old IP was {domain_ip}") domain['NEW_IP'] = current_ip domain['RESULT'] = f"Update successfull" + domain['LAST_UPDATE'] = datetime.now() else: print(f"\tThere was an error, see below for more details") print(f"\tResponse code was: {response.status_code}") @@ -115,12 +123,15 @@ def update_all_ip(current_ip): print(f"\tResponse json is: {response.json()}") domain['NEW_IP'] = f"Not set" domain['RESULT'] = f"Error" + ### Placeholder + ### Needs some work to load time from last successful update + domain['LAST_UPDATE'] = datetime.now() print('\tDone!') print(f"{'':#<40}") # Updating index.html - + date_of_last_update = datetime.now() write_to_template(data['domains']) print('\tUpdating index.html...') diff --git a/owl/template.html.jinja b/owl/template.html.jinja index f0041e4..6d31cb6 100644 --- a/owl/template.html.jinja +++ b/owl/template.html.jinja @@ -40,6 +40,9 @@
{{ domain['RESULT'] }}
+
+ {{ domain['LAST_UPDATE'] }} +
{% endfor %} diff --git a/requirements.txt b/requirements.txt index 9f91dba..6cc6908 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,8 +1,8 @@ -certifi==2024.6.2 +certifi==2024.8.30 charset-normalizer==3.3.2 -idna==3.7 +idna==3.10 Jinja2==3.1.4 MarkupSafe==2.1.5 pydig==0.4.0 requests==2.32.3 -urllib3==2.2.1 +urllib3==2.2.3 From 4e397073fb68f3af55f9c1964adbbf73b12aadb2 Mon Sep 17 00:00:00 2001 From: Simon Date: Fri, 11 Oct 2024 20:08:48 +0200 Subject: [PATCH 2/8] Added function to get Cloudflare meta data for dns records, use last modified entry for webserver table Changed jinja template and added addiotnal row for date --- owl/dns_functions.py | 39 +++++++++++++++++++++++++++++++++++---- owl/template.html.jinja | 3 +++ 2 files changed, 38 insertions(+), 4 deletions(-) diff --git a/owl/dns_functions.py b/owl/dns_functions.py index de7a62b..88cb6f7 100644 --- a/owl/dns_functions.py +++ b/owl/dns_functions.py @@ -103,7 +103,8 @@ def update_all_ip(current_ip): domain['RESULT'] = f"No change" ### Placeholder ### Needs some work to load time from last successful update - domain['LAST_UPDATE'] = datetime.now() + domain_info = get_current_dns_entry_from_cf(cf, domain) + domain['LAST_UPDATE'] = domain_info['result']['modified_on'] else: print(f"\tUpdating DynDNS IP for domain: {domain['RECORD_NAME']}...") response = set_ip(cf, domain, current_ip) @@ -114,7 +115,8 @@ def update_all_ip(current_ip): notification_service.send_success(f"IP for domain {domain['RECORD_NAME']} was successfully set to {current_ip}. Old IP was {domain_ip}") domain['NEW_IP'] = current_ip domain['RESULT'] = f"Update successfull" - domain['LAST_UPDATE'] = datetime.now() + domain_info = get_current_dns_entry_from_cf(cf, domain) + domain['LAST_UPDATE'] = domain_info['result']['modified_on'] else: print(f"\tThere was an error, see below for more details") print(f"\tResponse code was: {response.status_code}") @@ -125,19 +127,47 @@ def update_all_ip(current_ip): domain['RESULT'] = f"Error" ### Placeholder ### Needs some work to load time from last successful update - domain['LAST_UPDATE'] = datetime.now() + domain_info = get_current_dns_entry_from_cf(cf, domain) + domain['LAST_UPDATE'] = domain_info['result']['modified_on'] print('\tDone!') print(f"{'':#<40}") # Updating index.html - date_of_last_update = datetime.now() write_to_template(data['domains']) print('\tUpdating index.html...') print('\tDone!') print(f"{'':#<40}") +def get_current_dns_entry_from_cf(cloudflare, domain): + zone_id = cloudflare['ZONE_ID'] + api_key = cloudflare['API_KEY'] + user_email = cloudflare['USER_EMAIL'] + + record_id = domain['RECORD_ID'] + record_name = domain['RECORD_NAME'] + + print(f"\tCloudflare Zone ID is: {zone_id}") + print(f"\tCloudflare API Key is: {api_key}") + print(f"\tRecord ID is: {record_id}") + print(f"\tRecord Name is: {record_name}") + + url = ( + "https://api.cloudflare.com/client/v4/zones/%(zone_id)s/dns_records/%(record_id)s" + % {"zone_id": zone_id, "record_id": record_id} + ) + + headers = { + "X-Auth-Email": user_email, + "X-Auth-Key": api_key, + "Content-Type": "application/json", + } + + response = requests.get(url, headers=headers) + # print(response.status_code) + return response.json() + if __name__ == '__main__': @@ -147,3 +177,4 @@ def update_all_ip(current_ip): update_all_ip(ip) print(f"\tDone updating, sleep until next CRON schedule...") + diff --git a/owl/template.html.jinja b/owl/template.html.jinja index 6d31cb6..98c919c 100644 --- a/owl/template.html.jinja +++ b/owl/template.html.jinja @@ -25,6 +25,9 @@
Result
+
+ Last update on +
{% for domain in domain_list %}
From a90ff151c9eac0fefa399c04a2fd52527c358e73 Mon Sep 17 00:00:00 2001 From: Simon Date: Fri, 11 Oct 2024 20:40:17 +0200 Subject: [PATCH 3/8] Add proper TZ handling, updated config.example.json --- config.example.json | 1 + owl/dns_functions.py | 13 +++++++++---- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/config.example.json b/config.example.json index 3001e3e..1870424 100644 --- a/config.example.json +++ b/config.example.json @@ -1,4 +1,5 @@ { + "TIMEZONE": "Europe/Berlin", "PUBLIC_IP_CHECK": "CLOUDFLARE", "ENABLE_WEBSERVER": true, "WEBSERVER_PORT": 8000, diff --git a/owl/dns_functions.py b/owl/dns_functions.py index 88cb6f7..160d40d 100644 --- a/owl/dns_functions.py +++ b/owl/dns_functions.py @@ -4,8 +4,10 @@ from .notifications import Notifier from .config import load_config from .webserver import write_to_template -from datetime import datetime +from datetime import datetime, timezone +from zoneinfo import ZoneInfo +TIMEZONE = ZoneInfo(load_config('./config.json')['TIMEZONE']) if load_config('./config.json')['NOTIFICATIONS']['ENABLE_NOTIFICATIONS']: notification_service = Notifier() @@ -104,7 +106,8 @@ def update_all_ip(current_ip): ### Placeholder ### Needs some work to load time from last successful update domain_info = get_current_dns_entry_from_cf(cf, domain) - domain['LAST_UPDATE'] = domain_info['result']['modified_on'] + last_update = datetime.strptime(domain_info['result']['modified_on'], "%Y-%m-%dT%H:%M:%S.%fZ").replace(tzinfo=timezone.utc) + domain['LAST_UPDATE'] = last_update.astimezone(TIMEZONE).strftime("%d.%m.%Y at %H:%M:%S") else: print(f"\tUpdating DynDNS IP for domain: {domain['RECORD_NAME']}...") response = set_ip(cf, domain, current_ip) @@ -116,7 +119,8 @@ def update_all_ip(current_ip): domain['NEW_IP'] = current_ip domain['RESULT'] = f"Update successfull" domain_info = get_current_dns_entry_from_cf(cf, domain) - domain['LAST_UPDATE'] = domain_info['result']['modified_on'] + last_update = datetime.strptime(domain_info['result']['modified_on'], "%Y-%m-%dT%H:%M:%S.%fZ").replace(tzinfo=timezone.utc) + domain['LAST_UPDATE'] = last_update.astimezone(TIMEZONE).strftime("%d.%m.%Y at %H:%M:%S") else: print(f"\tThere was an error, see below for more details") print(f"\tResponse code was: {response.status_code}") @@ -128,7 +132,8 @@ def update_all_ip(current_ip): ### Placeholder ### Needs some work to load time from last successful update domain_info = get_current_dns_entry_from_cf(cf, domain) - domain['LAST_UPDATE'] = domain_info['result']['modified_on'] + last_update = datetime.strptime(domain_info['result']['modified_on'], "%Y-%m-%dT%H:%M:%S.%fZ").replace(tzinfo=timezone.utc) + domain['LAST_UPDATE'] = last_update.astimezone(TIMEZONE).strftime("%d.%m.%Y at %H:%M:%S") print('\tDone!') print(f"{'':#<40}") From 179b81c03a116d06f5bfb3f87c7a70f3155bb3ed Mon Sep 17 00:00:00 2001 From: Simon Date: Fri, 18 Oct 2024 23:36:55 +0200 Subject: [PATCH 4/8] Bump requirements.txt --- requirements.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/requirements.txt b/requirements.txt index 6cc6908..936cd1a 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,8 +1,8 @@ certifi==2024.8.30 -charset-normalizer==3.3.2 +charset-normalizer==3.4.0 idna==3.10 Jinja2==3.1.4 -MarkupSafe==2.1.5 +MarkupSafe==3.0.2 pydig==0.4.0 requests==2.32.3 urllib3==2.2.3 From 9661914090e275cdde3a2c7b834f627a013ec825 Mon Sep 17 00:00:00 2001 From: Simon Date: Fri, 18 Oct 2024 23:40:59 +0200 Subject: [PATCH 5/8] Update Logo to v0.5 --- owl/owl_logo.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/owl/owl_logo.py b/owl/owl_logo.py index 0b13335..88f3c94 100644 --- a/owl/owl_logo.py +++ b/owl/owl_logo.py @@ -6,13 +6,13 @@ def print_owl(): print(r""" - # _____ _ _ _____ ____ __ __ _ ___ _ _ - # | __ \ | \ | | / ____| / __ \\ \ / /| | / _ \ | || | - # | | | || \| || (___ | | | |\ \ /\ / / | | __ __| | | || || |_ - # | | | || . ` | \___ \ | | | | \ \/ \/ / | | \ \ / /| | | ||__ _| - # | |__| || |\ | ____) | | |__| | \ /\ / | |____ \ V / | |_| |_ | | - # |_____/ |_| \_||_____/ \____/ \/ \/ |______| \_/ \___/(_) |_| - +# _____ _ _ _____ ____ __ __ _ ___ _____ +# | __ \ | \ | | / ____| / __ \\ \ / /| | / _ \ | ____| +# | | | || \| || (___ | | | |\ \ /\ / / | | __ __| | | | | |__ +# | | | || . ` | \___ \ | | | | \ \/ \/ / | | \ \ / /| | | | |___ \ +# | |__| || |\ | ____) | | |__| | \ /\ / | |____ \ V / | |_| |_ ___) | +# |_____/ |_| \_||_____/ \____/ \/ \/ |______| \_/ \___/(_)|____/ + From a2563b6750b8fa25ffd487f65f26c519656c4704 Mon Sep 17 00:00:00 2001 From: Simon Date: Fri, 18 Oct 2024 23:52:53 +0200 Subject: [PATCH 6/8] Update owl_logo.py for new config.json format Update import in notifications.py --- owl/notifications.py | 2 +- owl/owl_logo.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/owl/notifications.py b/owl/notifications.py index ae1fe1b..48dbcd3 100644 --- a/owl/notifications.py +++ b/owl/notifications.py @@ -1,5 +1,5 @@ import requests -from .config import load_config +from owl.config import load_config class Notifier: diff --git a/owl/owl_logo.py b/owl/owl_logo.py index 88f3c94..d65a29c 100644 --- a/owl/owl_logo.py +++ b/owl/owl_logo.py @@ -46,7 +46,7 @@ def starting_message(): def send_start_notification(): - if load_config('./config.json')['ENABLE_NOTIFICATIONS']: + if load_config('./config.json')['NOTIFICATIONS']['ENABLE_NOTIFICATIONS']: notification_service = Notifier() notification_service.send_success(f"\tStarting DNS-Owl service!") From 5cb49850a5b7bcb43ba4b6954accfae3646ae63b Mon Sep 17 00:00:00 2001 From: Simon Date: Fri, 18 Oct 2024 23:53:54 +0200 Subject: [PATCH 7/8] Update imports --- owl/dns_functions.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/owl/dns_functions.py b/owl/dns_functions.py index 160d40d..5dad2f0 100644 --- a/owl/dns_functions.py +++ b/owl/dns_functions.py @@ -1,9 +1,9 @@ import requests import pydig import json -from .notifications import Notifier -from .config import load_config -from .webserver import write_to_template +from owl.notifications import Notifier +from owl.config import load_config +from owl.webserver import write_to_template from datetime import datetime, timezone from zoneinfo import ZoneInfo From 823862bea37d826955de1c25a35710b2a01baf32 Mon Sep 17 00:00:00 2001 From: Simon_Bot Date: Fri, 18 Oct 2024 21:58:12 +0000 Subject: [PATCH 8/8] Version 0.5.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index d94a1bf..12ad79e 100644 --- a/package.json +++ b/package.json @@ -1,4 +1,4 @@ { "name": "dns-owl", - "version": "0.4.1" + "version": "0.5.0" } \ No newline at end of file