diff --git a/changedetectionio/__init__.py b/changedetectionio/__init__.py index ef37447d..e7b8f90e 100644 --- a/changedetectionio/__init__.py +++ b/changedetectionio/__init__.py @@ -415,6 +415,7 @@ def changedetection_app(config=None, datastore_o=None): 'trigger_text': form.trigger_text.data, 'notification_title': form.notification_title.data, 'notification_body': form.notification_body.data, + 'notification_format': form.notification_format.data, 'extract_title_as_title': form.extract_title_as_title.data } @@ -454,7 +455,8 @@ def changedetection_app(config=None, datastore_o=None): n_object = {'watch_url': form.url.data.strip(), 'notification_urls': form.notification_urls.data, 'notification_title': form.notification_title.data, - 'notification_body' : form.notification_body.data + 'notification_body' : form.notification_body.data, + 'notification_format' : form.notification_format.data, } notification_q.put(n_object) @@ -501,6 +503,7 @@ def changedetection_app(config=None, datastore_o=None): form.fetch_backend.data = datastore.data['settings']['application']['fetch_backend'] form.notification_title.data = datastore.data['settings']['application']['notification_title'] form.notification_body.data = datastore.data['settings']['application']['notification_body'] + form.notification_format.data = datastore.data['settings']['application']['notification_format'] form.base_url.data = datastore.data['settings']['application']['base_url'] # Password unset is a GET @@ -519,6 +522,7 @@ def changedetection_app(config=None, datastore_o=None): datastore.data['settings']['application']['fetch_backend'] = form.fetch_backend.data datastore.data['settings']['application']['notification_title'] = form.notification_title.data datastore.data['settings']['application']['notification_body'] = form.notification_body.data + datastore.data['settings']['application']['notification_format'] = form.notification_format.data datastore.data['settings']['application']['notification_urls'] = form.notification_urls.data datastore.data['settings']['application']['base_url'] = form.base_url.data @@ -526,7 +530,8 @@ def changedetection_app(config=None, datastore_o=None): n_object = {'watch_url': "Test from changedetection.io!", 'notification_urls': form.notification_urls.data, 'notification_title': form.notification_title.data, - 'notification_body': form.notification_body.data + 'notification_body': form.notification_body.data, + 'notification_format': form.notification_format.data, } notification_q.put(n_object) flash('Notifications queued.') diff --git a/changedetectionio/forms.py b/changedetectionio/forms.py index 99c2c53b..418bd5af 100644 --- a/changedetectionio/forms.py +++ b/changedetectionio/forms.py @@ -6,6 +6,8 @@ from wtforms.fields import html5 from changedetectionio import content_fetcher import re +from changedetectionio.notification import default_notification_format, valid_notification_formats + class StringListField(StringField): widget = widgets.TextArea() @@ -203,6 +205,7 @@ class commonSettingsForm(Form): notification_urls = StringListField('Notification URL List', validators=[validators.Optional(), ValidateAppRiseServers()]) notification_title = StringField('Notification Title', default='ChangeDetection.io Notification - {watch_url}', validators=[validators.Optional(), ValidateTokensList()]) notification_body = TextAreaField('Notification Body', default='{watch_url} had a change.', validators=[validators.Optional(), ValidateTokensList()]) + notification_format = SelectField('Notification Format', choices=valid_notification_formats.keys(), default=default_notification_format) trigger_check = BooleanField('Send test notification on save') fetch_backend = RadioField(u'Fetch Method', choices=content_fetcher.available_fetchers(), validators=[ValidateContentFetcherIsReady()]) extract_title_as_title = BooleanField('Extract from document and use as watch title', default=False) diff --git a/changedetectionio/notification.py b/changedetectionio/notification.py index 0a18fdba..96f18a90 100644 --- a/changedetectionio/notification.py +++ b/changedetectionio/notification.py @@ -1,5 +1,6 @@ import os import apprise +from apprise import NotifyFormat valid_tokens = { 'base_url': '', @@ -12,6 +13,13 @@ valid_tokens = { 'current_snapshot': '' } +valid_notification_formats = { + 'Text': NotifyFormat.TEXT, + 'Markdown': NotifyFormat.MARKDOWN, + 'HTML': NotifyFormat.HTML, +} + +default_notification_format = 'Text' def process_notification(n_object, datastore): import logging @@ -27,6 +35,11 @@ def process_notification(n_object, datastore): # Get the notification body from datastore n_body = n_object['notification_body'] n_title = n_object['notification_title'] + n_format = valid_notification_formats.get( + n_object['notification_format'], + valid_notification_formats[default_notification_format], + ) + # Insert variables into the notification content notification_parameters = create_notification_parameters(n_object, datastore) @@ -39,7 +52,8 @@ def process_notification(n_object, datastore): apobj.notify( body=n_body, - title=n_title + title=n_title, + body_format=n_format, ) # Notification title + body content parameters get created here. @@ -85,4 +99,4 @@ def create_notification_parameters(n_object, datastore): 'current_snapshot': n_object['current_snapshot'] if 'current_snapshot' in n_object else '' }) - return tokens \ No newline at end of file + return tokens diff --git a/changedetectionio/store.py b/changedetectionio/store.py index 6c0f84ce..23376657 100644 --- a/changedetectionio/store.py +++ b/changedetectionio/store.py @@ -47,6 +47,7 @@ class ChangeDetectionStore: # Custom notification content 'notification_title': None, 'notification_body': None, + 'notification_format': None, } } } @@ -73,6 +74,7 @@ class ChangeDetectionStore: 'notification_urls': [], # List of URLs to add to the notification Queue (Usually AppRise) 'notification_title': None, 'notification_body': None, + 'notification_format': None, 'css_filter': "", 'trigger_text': [], # List of text or regex to wait for until a change is detected 'fetch_backend': None, diff --git a/changedetectionio/templates/_common_fields.jinja b/changedetectionio/templates/_common_fields.jinja index 55573781..48c8ca35 100644 --- a/changedetectionio/templates/_common_fields.jinja +++ b/changedetectionio/templates/_common_fields.jinja @@ -24,6 +24,10 @@ {{ render_field(form.notification_body , rows=5) }} <span class="pure-form-message-inline">Body for all notifications</span> </div> + <div class="pure-control-group"> + {{ render_field(form.notification_format , rows=5) }} + <span class="pure-form-message-inline">Format for all notifications</span> + </div> <div class="pure-controls"> <span class="pure-form-message-inline"> These tokens can be used in the notification body and title to diff --git a/changedetectionio/tests/test_notification.py b/changedetectionio/tests/test_notification.py index 95be9a10..ca53dc1c 100644 --- a/changedetectionio/tests/test_notification.py +++ b/changedetectionio/tests/test_notification.py @@ -56,6 +56,7 @@ def test_check_notification(client, live_server): "Diff URL: {diff_url}\n" "Snapshot: {current_snapshot}\n" ":-)", + "notification_format": "Text", "url": test_url, "tag": "my tag", "title": "my title", @@ -181,6 +182,7 @@ def test_check_notification(client, live_server): url_for("settings_page"), data={"notification_title": "New ChangeDetection.io Notification - {watch_url}", "notification_body": "Rubbish: {rubbish}\n", + "notification_format": "Text", "notification_urls": "json://foobar.com", "minutes_between_check": 180, "fetch_backend": "html_requests" @@ -188,4 +190,4 @@ def test_check_notification(client, live_server): follow_redirects=True ) - assert bytes("is not a valid token".encode('utf-8')) in res.data \ No newline at end of file + assert bytes("is not a valid token".encode('utf-8')) in res.data diff --git a/changedetectionio/update_worker.py b/changedetectionio/update_worker.py index 7e38d531..ef31756e 100644 --- a/changedetectionio/update_worker.py +++ b/changedetectionio/update_worker.py @@ -87,6 +87,7 @@ class update_worker(threading.Thread): n_object['notification_urls'] = watch['notification_urls'] n_object['notification_title'] = watch['notification_title'] n_object['notification_body'] = watch['notification_body'] + n_object['notification_format'] = watch['notification_format'] self.notification_q.put(n_object) # No? maybe theres a global setting, queue them all @@ -95,6 +96,7 @@ class update_worker(threading.Thread): n_object['notification_urls'] = self.datastore.data['settings']['application']['notification_urls'] n_object['notification_title'] = self.datastore.data['settings']['application']['notification_title'] n_object['notification_body'] = self.datastore.data['settings']['application']['notification_body'] + n_object['notification_format'] = self.datastore.data['settings']['application']['notification_format'] self.notification_q.put(n_object) else: print(">>> NO notifications queued, watch and global notification URLs were empty.")