From 2c6faa7c4e8f9caf65343998eaad759f70a0f530 Mon Sep 17 00:00:00 2001 From: dgtlmoon Date: Wed, 31 Aug 2022 15:49:13 +0200 Subject: [PATCH] Cleaner separation of watch/global notification settings (#894) --- changedetectionio/forms.py | 2 + changedetectionio/model/Watch.py | 1 + changedetectionio/static/js/watch-settings.js | 33 +++++--- changedetectionio/store.py | 24 ++++++ changedetectionio/templates/edit.html | 6 +- changedetectionio/tests/test_notification.py | 80 +++++++++++++++++++ changedetectionio/update_worker.py | 4 +- 7 files changed, 137 insertions(+), 13 deletions(-) diff --git a/changedetectionio/forms.py b/changedetectionio/forms.py index f5a10283..13d576a4 100644 --- a/changedetectionio/forms.py +++ b/changedetectionio/forms.py @@ -355,6 +355,8 @@ class watchForm(commonSettingsForm): filter_failure_notification_send = BooleanField( 'Send a notification when the filter can no longer be found on the page', default=False) + notification_use_default = BooleanField('Use default/system notification settings', default=True) + def validate(self, **kwargs): if not super().validate(): return False diff --git a/changedetectionio/model/Watch.py b/changedetectionio/model/Watch.py index c59dd1da..b8e48196 100644 --- a/changedetectionio/model/Watch.py +++ b/changedetectionio/model/Watch.py @@ -35,6 +35,7 @@ class model(dict): 'notification_title': default_notification_title, 'notification_body': default_notification_body, 'notification_format': default_notification_format, + 'notification_use_default': True, # Use default for new 'notification_muted': False, 'css_filter': '', 'last_error': False, diff --git a/changedetectionio/static/js/watch-settings.js b/changedetectionio/static/js/watch-settings.js index b45ca95d..249f2e4c 100644 --- a/changedetectionio/static/js/watch-settings.js +++ b/changedetectionio/static/js/watch-settings.js @@ -1,7 +1,7 @@ -$(document).ready(function() { - function toggle() { +$(document).ready(function () { + function toggle_fetch_backend() { if ($('input[name="fetch_backend"]:checked').val() == 'html_webdriver') { - if(playwright_enabled) { + if (playwright_enabled) { // playwright supports headers, so hide everything else // See #664 $('#requests-override-options #request-method').hide(); @@ -13,12 +13,8 @@ $(document).ready(function() { // selenium/webdriver doesnt support anything afaik, hide it all $('#requests-override-options').hide(); } - - $('#webdriver-override-options').show(); - } else { - $('#requests-override-options').show(); $('#requests-override-options *:hidden').show(); $('#webdriver-override-options').hide(); @@ -26,8 +22,27 @@ $(document).ready(function() { } $('input[name="fetch_backend"]').click(function (e) { - toggle(); + toggle_fetch_backend(); }); - toggle(); + toggle_fetch_backend(); + function toggle_default_notifications() { + var n=$('#notification_urls, #notification_title, #notification_body, #notification_format'); + if ($('#notification_use_default').is(':checked')) { + $('#notification-field-group').fadeOut(); + $(n).each(function (e) { + $(this).attr('readonly', true); + }); + } else { + $('#notification-field-group').show(); + $(n).each(function (e) { + $(this).attr('readonly', false); + }); + } + } + + $('#notification_use_default').click(function (e) { + toggle_default_notifications(); + }); + toggle_default_notifications(); }); diff --git a/changedetectionio/store.py b/changedetectionio/store.py index 80cac7a4..01b40b4d 100644 --- a/changedetectionio/store.py +++ b/changedetectionio/store.py @@ -535,4 +535,28 @@ class ChangeDetectionStore: del(watch['last_changed']) except: continue + return + + + def update_5(self): + + from changedetectionio.notification import ( + default_notification_body, + default_notification_format, + default_notification_title, + ) + + for uuid, watch in self.data['watching'].items(): + try: + # If it's all the same to the system settings, then prefer system notification settings + # include \r\n -> \n incase they already hit submit and the browser put \r in + if watch.get('notification_body').replace('\r\n', '\n') == default_notification_body.replace('\r\n', '\n') and \ + watch.get('notification_format') == default_notification_format and \ + watch.get('notification_title').replace('\r\n', '\n') == default_notification_title.replace('\r\n', '\n') and \ + watch.get('notification_urls') == self.__data['settings']['application']['notification_urls']: + watch['notification_use_default'] = True + else: + watch['notification_use_default'] = False + except: + continue return \ No newline at end of file diff --git a/changedetectionio/templates/edit.html b/changedetectionio/templates/edit.html index 1d18c4d8..47cb7815 100644 --- a/changedetectionio/templates/edit.html +++ b/changedetectionio/templates/edit.html @@ -135,9 +135,11 @@ User-Agent: wonderbra 1.0") }}
- Note: These settings override the global settings for this watch.
-
+
+ {{ render_checkbox_field(form.notification_use_default) }} +
+
{{ render_common_settings_form(form, current_base_url, emailprefix) }}
diff --git a/changedetectionio/tests/test_notification.py b/changedetectionio/tests/test_notification.py index 29b7e00d..2a620e50 100644 --- a/changedetectionio/tests/test_notification.py +++ b/changedetectionio/tests/test_notification.py @@ -71,6 +71,7 @@ def test_check_notification(client, live_server): "url": test_url, "tag": "my tag", "title": "my title", + # No 'notification_use_default' here, so it's effectively False/off "headers": "", "fetch_backend": "html_requests"}) @@ -215,3 +216,82 @@ def test_notification_validation(client, live_server): url_for("form_delete", uuid="all"), follow_redirects=True ) + +# Check that the default VS watch specific notification is hit +def test_check_notification_use_default(client, live_server): + set_original_response() + notification_url = url_for('test_notification_endpoint', _external=True).replace('http', 'json') + test_url = url_for('test_endpoint', _external=True) + + res = client.post( + url_for("form_quick_watch_add"), + data={"url": test_url, "tag": ''}, + follow_redirects=True + ) + assert b"Watch added" in res.data + + ## Setup the local one and enable it + res = client.post( + url_for("edit_page", uuid="first"), + data={"notification_urls": notification_url, + "notification_title": "watch-notification", + "notification_body": "watch-body", + 'notification_use_default': "True", + "notification_format": "Text", + "url": test_url, + "tag": "my tag", + "title": "my title", + "headers": "", + "fetch_backend": "html_requests"}, + follow_redirects=True + ) + + res = client.post( + url_for("settings_page"), + data={"application-notification_title": "global-notifications-title", + "application-notification_body": "global-notifications-body\n", + "application-notification_format": "Text", + "application-notification_urls": notification_url, + "requests-time_between_check-minutes": 180, + "fetch_backend": "html_requests" + }, + follow_redirects=True + ) + + # A change should by default trigger a notification of the global-notifications + time.sleep(1) + set_modified_response() + client.get(url_for("form_watch_checknow"), follow_redirects=True) + time.sleep(2) + with open("test-datastore/notification.txt", "r") as f: + assert 'global-notifications-title' in f.read() + + ## Setup the local one and enable it + res = client.post( + url_for("edit_page", uuid="first"), + data={"notification_urls": notification_url, + "notification_title": "watch-notification", + "notification_body": "watch-body", + # No 'notification_use_default' here, so it's effectively False/off = "dont use default, use this one" + "notification_format": "Text", + "url": test_url, + "tag": "my tag", + "title": "my title", + "headers": "", + "fetch_backend": "html_requests"}, + follow_redirects=True + ) + set_original_response() + + client.get(url_for("form_watch_checknow"), follow_redirects=True) + time.sleep(2) + assert os.path.isfile("test-datastore/notification.txt") + with open("test-datastore/notification.txt", "r") as f: + assert 'watch-notification' in f.read() + + + # cleanup for the next + client.get( + url_for("form_delete", uuid="all"), + follow_redirects=True + ) \ No newline at end of file diff --git a/changedetectionio/update_worker.py b/changedetectionio/update_worker.py index d56a9298..afe5c04f 100644 --- a/changedetectionio/update_worker.py +++ b/changedetectionio/update_worker.py @@ -41,7 +41,7 @@ class update_worker(threading.Thread): ) # Did it have any notification alerts to hit? - if len(watch['notification_urls']): + if not watch.get('notification_use_default') and len(watch['notification_urls']): print(">>> Notifications queued for UUID from watch {}".format(watch_uuid)) n_object['notification_urls'] = watch['notification_urls'] n_object['notification_title'] = watch['notification_title'] @@ -49,7 +49,7 @@ class update_worker(threading.Thread): n_object['notification_format'] = watch['notification_format'] # No? maybe theres a global setting, queue them all - elif len(self.datastore.data['settings']['application']['notification_urls']): + elif watch.get('notification_use_default') and len(self.datastore.data['settings']['application']['notification_urls']): print(">>> Watch notification URLs were empty, using GLOBAL notifications for UUID: {}".format(watch_uuid)) n_object['notification_urls'] = self.datastore.data['settings']['application']['notification_urls'] n_object['notification_title'] = self.datastore.data['settings']['application']['notification_title']