diff --git a/changedetectionio/__init__.py b/changedetectionio/__init__.py
index 1370e5e2..89ccc786 100644
--- a/changedetectionio/__init__.py
+++ b/changedetectionio/__init__.py
@@ -403,14 +403,15 @@ def changedetection_app(config=None, datastore_o=None):
if form.fetch_backend.data == datastore.data['settings']['application']['fetch_backend']:
form.fetch_backend.data = None
-
update_obj = {'url': form.url.data.strip(),
'minutes_between_check': form.minutes_between_check.data,
'tag': form.tag.data.strip(),
'title': form.title.data.strip(),
'headers': form.headers.data,
'fetch_backend': form.fetch_backend.data,
- 'trigger_text': form.trigger_text.data
+ 'trigger_text': form.trigger_text.data,
+ 'notification_title': form.notification_title.data,
+ 'notification_body': form.notification_body.data
}
# Notification URLs
@@ -443,8 +444,10 @@ def changedetection_app(config=None, datastore_o=None):
if form.trigger_check.data:
n_object = {'watch_url': form.url.data.strip(),
- 'notification_urls': form.notification_urls.data
- }
+ 'notification_urls': form.notification_urls.data,
+ 'notification_title': form.notification_title.data,
+ 'notification_body' : form.notification_body.data
+ }
notification_q.put(n_object)
flash('Notifications queued.')
@@ -513,7 +516,10 @@ def changedetection_app(config=None, datastore_o=None):
if form.trigger_check.data and len(form.notification_urls.data):
n_object = {'watch_url': "Test from changedetection.io!",
- 'notification_urls': form.notification_urls.data}
+ 'notification_urls': form.notification_urls.data,
+ 'notification_title': form.notification_title.data,
+ 'notification_body': form.notification_body.data
+ }
notification_q.put(n_object)
flash('Notifications queued.')
diff --git a/changedetectionio/forms.py b/changedetectionio/forms.py
index f67d851e..4bc39215 100644
--- a/changedetectionio/forms.py
+++ b/changedetectionio/forms.py
@@ -116,6 +116,23 @@ class ValidateContentFetcherIsReady(object):
raise ValidationError(message % (field.data, e))
+class ValidateAppRiseServers(object):
+ """
+ Validates that each URL given is compatible with AppRise
+ """
+
+ def __init__(self, message=None):
+ self.message = message
+
+ def __call__(self, form, field):
+ import apprise
+ apobj = apprise.Apprise()
+
+ for server_url in field.data:
+ if not apobj.add(server_url):
+ message = field.gettext('\'%s\' is not a valid AppRise URL.' % (server_url))
+ raise ValidationError(message)
+
class ValidateTokensList(object):
"""
Validates that a {token} is from a valid set
@@ -172,42 +189,40 @@ class ValidateCSSJSONInput(object):
message = field.gettext('\'%s\' is not a valid JSONPath expression. (%s)')
raise ValidationError(message % (input, str(e)))
+
class quickWatchForm(Form):
# https://wtforms.readthedocs.io/en/2.3.x/fields/#module-wtforms.fields.html5
# `require_tld` = False is needed even for the test harness "http://localhost:5005.." to run
-
url = html5.URLField('URL', [validators.URL(require_tld=False)])
tag = StringField('Group tag', [validators.Optional(), validators.Length(max=35)])
-class watchForm(quickWatchForm):
+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()])
+ trigger_check = BooleanField('Send test notification on save')
+ fetch_backend = RadioField(u'Fetch Method', choices=content_fetcher.available_fetchers(), validators=[ValidateContentFetcherIsReady()])
+
+class watchForm(commonSettingsForm):
+
+ url = html5.URLField('URL', [validators.URL(require_tld=False)])
+ tag = StringField('Group tag', [validators.Optional(), validators.Length(max=35)])
minutes_between_check = html5.IntegerField('Maximum time in minutes until recheck',
[validators.Optional(), validators.NumberRange(min=1)])
css_filter = StringField('CSS/JSON Filter', [ValidateCSSJSONInput()])
title = StringField('Title')
- fetch_backend = RadioField(u'Fetch Method', choices=content_fetcher.available_fetchers(), validators=[ValidateContentFetcherIsReady()])
-
ignore_text = StringListField('Ignore Text', [ValidateListRegex()])
- notification_urls = StringListField('Notification URL List')
headers = StringDictKeyValue('Request Headers')
- trigger_check = BooleanField('Send test notification on save')
trigger_text = StringListField('Trigger/wait for text', [validators.Optional(), ValidateListRegex()])
-class globalSettingsForm(Form):
+class globalSettingsForm(commonSettingsForm):
password = SaltyPasswordField()
minutes_between_check = html5.IntegerField('Maximum time in minutes until recheck',
[validators.NumberRange(min=1)])
-
- notification_urls = StringListField('Notification URL List')
-
- 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')
- trigger_check = BooleanField('Send test notification on save')
-
- notification_title = StringField('Notification Title', validators=[validators.Optional(), ValidateTokensList()])
- notification_body = TextAreaField('Notification Body', validators=[validators.Optional(), ValidateTokensList()])
diff --git a/changedetectionio/notification.py b/changedetectionio/notification.py
index bd75359e..da015075 100644
--- a/changedetectionio/notification.py
+++ b/changedetectionio/notification.py
@@ -20,13 +20,13 @@ def process_notification(n_object, datastore):
apobj = apprise.Apprise(debug=True)
for url in n_object['notification_urls']:
- print (">> Process Notification: AppRise notifying {}".format(url.strip()))
- apobj.add(url.strip())
+ url = url.strip()
+ print (">> Process Notification: AppRise notifying {}".format(url))
+ apobj.add(url)
# Get the notification body from datastore
- n_body = datastore.data['settings']['application']['notification_body']
- # Get the notification title from the datastore
- n_title = datastore.data['settings']['application']['notification_title']
+ n_body = n_object['notification_body']
+ n_title = n_object['notification_title']
# Insert variables into the notification content
notification_parameters = create_notification_parameters(n_object, datastore)
@@ -37,13 +37,11 @@ def process_notification(n_object, datastore):
n_title = n_title.replace(token, val)
n_body = n_body.replace(token, val)
-
apobj.notify(
body=n_body,
title=n_title
)
-
# Notification title + body content parameters get created here.
def create_notification_parameters(n_object, datastore):
from copy import deepcopy
diff --git a/changedetectionio/store.py b/changedetectionio/store.py
index 8a28f6b6..45fc9c95 100644
--- a/changedetectionio/store.py
+++ b/changedetectionio/store.py
@@ -42,8 +42,8 @@ class ChangeDetectionStore:
'fetch_backend': 'html_requests',
'notification_urls': [], # Apprise URL list
# Custom notification content
- 'notification_title': 'ChangeDetection.io Notification - {watch_url}',
- 'notification_body': '{watch_url} had a change.'
+ 'notification_title': None,
+ 'notification_body': None,
}
}
}
@@ -66,7 +66,10 @@ class ChangeDetectionStore:
'headers': {}, # Extra headers to send
'history': {}, # Dict of timestamp and output stripped filename
'ignore_text': [], # List of text to ignore when calculating the comparison checksum
+ # Custom notification content
'notification_urls': [], # List of URLs to add to the notification Queue (Usually AppRise)
+ 'notification_title': None,
+ 'notification_body': 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
new file mode 100644
index 00000000..184e6011
--- /dev/null
+++ b/changedetectionio/templates/_common_fields.jinja
@@ -0,0 +1,90 @@
+
+{% from '_helpers.jinja' import render_field %}
+
+{% macro render_notifications_field(form) %}
+
+
+
+{% endmacro %}
\ No newline at end of file
diff --git a/changedetectionio/templates/_helpers.jinja b/changedetectionio/templates/_helpers.jinja
index 08a8815a..734fc7e0 100644
--- a/changedetectionio/templates/_helpers.jinja
+++ b/changedetectionio/templates/_helpers.jinja
@@ -22,4 +22,6 @@
{% endif %}
-{% endmacro %}
\ No newline at end of file
+{% endmacro %}
+
+
diff --git a/changedetectionio/templates/edit.html b/changedetectionio/templates/edit.html
index cd55da0c..4a3c02f9 100644
--- a/changedetectionio/templates/edit.html
+++ b/changedetectionio/templates/edit.html
@@ -1,6 +1,7 @@
{% extends 'base.html' %}
{% block content %}
{% from '_helpers.jinja' import render_field %}
+{% from '_common_fields.jinja' import render_notifications_field %}
@@ -57,25 +58,12 @@ User-Agent: wonderbra 1.0") }}
-
-
+
+ Note: These settings override the global settings.
+ {{ render_notifications_field(form) }}
+
-
-
+
+ {{ render_notifications_field(form) }}
+
{{ render_field(form.fetch_backend) }}
diff --git a/changedetectionio/tests/test_notification.py b/changedetectionio/tests/test_notification.py
index fcebb9f7..2feb36da 100644
--- a/changedetectionio/tests/test_notification.py
+++ b/changedetectionio/tests/test_notification.py
@@ -35,6 +35,16 @@ def test_check_notification(client, live_server):
res = client.post(
url_for("edit_page", uuid="first"),
data={"notification_urls": notification_url,
+ "notification_title": "New ChangeDetection.io Notification - {watch_url}",
+ "notification_body": "BASE URL: {base_url}\n"
+ "Watch URL: {watch_url}\n"
+ "Watch UUID: {watch_uuid}\n"
+ "Watch title: {watch_title}\n"
+ "Watch tag: {watch_tag}\n"
+ "Preview: {preview_url}\n"
+ "Diff URL: {diff_url}\n"
+ "Snapshot: {current_snapshot}\n"
+ ":-)",
"url": test_url,
"tag": "my tag",
"title": "my title",
@@ -66,7 +76,6 @@ def test_check_notification(client, live_server):
os.unlink("test-datastore/notification.txt")
-
set_modified_response()
# Trigger a check
@@ -100,18 +109,9 @@ def test_check_notification(client, live_server):
res = client.post(
url_for("settings_page"),
data={"notification_title": "New ChangeDetection.io Notification - {watch_url}",
- "notification_body": "BASE URL: {base_url}\n"
- "Watch URL: {watch_url}\n"
- "Watch UUID: {watch_uuid}\n"
- "Watch title: {watch_title}\n"
- "Watch tag: {watch_tag}\n"
- "Preview: {preview_url}\n"
- "Diff URL: {diff_url}\n"
- "Snapshot: {current_snapshot}\n"
- ":-)",
"notification_urls": "json://foobar.com", #Re #143 should not see that it sent without [test checkbox]
"minutes_between_check": 180,
- "fetch_backend": "html_requests"
+ "fetch_backend": "html_requests",
},
follow_redirects=True
)
diff --git a/changedetectionio/tests/test_watch_fields_storage.py b/changedetectionio/tests/test_watch_fields_storage.py
index 12f6474c..a2929b79 100644
--- a/changedetectionio/tests/test_watch_fields_storage.py
+++ b/changedetectionio/tests/test_watch_fields_storage.py
@@ -20,7 +20,7 @@ def test_check_watch_field_storage(client, live_server):
res = client.post(
url_for("edit_page", uuid="first"),
- data={ "notification_urls": "http://myapi.com",
+ data={ "notification_urls": "json://myapi.com",
"minutes_between_check": 126,
"css_filter" : ".fooclass",
"title" : "My title",
@@ -39,7 +39,7 @@ def test_check_watch_field_storage(client, live_server):
follow_redirects=True
)
- assert b"http://myapi.com" in res.data
+ assert b"json://myapi.com" in res.data
assert b"126" in res.data
assert b".fooclass" in res.data
assert b"My title" in res.data
diff --git a/changedetectionio/tests/util.py b/changedetectionio/tests/util.py
index 38e1c2b6..a24e6ae3 100644
--- a/changedetectionio/tests/util.py
+++ b/changedetectionio/tests/util.py
@@ -58,7 +58,7 @@ def live_server_setup(live_server):
# Where we POST to as a notification
- @live_server.app.route('/test_notification_endpoint', methods=['POST'])
+ @live_server.app.route('/test_notification_endpoint', methods=['POST', 'GET'])
def test_notification_endpoint():
from flask import request
diff --git a/changedetectionio/update_worker.py b/changedetectionio/update_worker.py
index a5f36bda..7e38d531 100644
--- a/changedetectionio/update_worker.py
+++ b/changedetectionio/update_worker.py
@@ -85,12 +85,16 @@ class update_worker(threading.Thread):
if len(watch['notification_urls']):
print(">>> Notifications queued for UUID from watch {}".format(uuid))
n_object['notification_urls'] = watch['notification_urls']
+ n_object['notification_title'] = watch['notification_title']
+ n_object['notification_body'] = watch['notification_body']
self.notification_q.put(n_object)
# No? maybe theres a global setting, queue them all
elif len(self.datastore.data['settings']['application']['notification_urls']):
print(">>> Watch notification URLs were empty, using GLOBAL notifications for UUID: {}".format(uuid))
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']
self.notification_q.put(n_object)
else:
print(">>> NO notifications queued, watch and global notification URLs were empty.")