diff --git a/changedetectionio/__init__.py b/changedetectionio/__init__.py index 6f21beac..3695cd23 100644 --- a/changedetectionio/__init__.py +++ b/changedetectionio/__init__.py @@ -497,6 +497,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.base_url.data = datastore.data['settings']['application']['base_url'] # Password unset is a GET if request.values.get('removepassword') == 'yes': @@ -514,9 +515,8 @@ 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_urls'] = form.notification_urls.data - datastore.needs_write = True + datastore.data['settings']['application']['base_url'] = form.base_url.data if form.trigger_check.data and len(form.notification_urls.data): n_object = {'watch_url': "Test from changedetection.io!", @@ -533,14 +533,13 @@ def changedetection_app(config=None, datastore_o=None): flask_login.logout_user() return redirect(url_for('index')) + datastore.needs_write = True flash("Settings updated.") if request.method == 'POST' and not form.validate(): flash("An error occurred, please see below.", "error") - # Same as notification.py - base_url = os.getenv('BASE_URL', '').strip('"') - output = render_template("settings.html", form=form, base_url=base_url) + output = render_template("settings.html", form=form) return output diff --git a/changedetectionio/forms.py b/changedetectionio/forms.py index 62b30b20..af675524 100644 --- a/changedetectionio/forms.py +++ b/changedetectionio/forms.py @@ -223,6 +223,7 @@ class watchForm(commonSettingsForm): class globalSettingsForm(commonSettingsForm): password = SaltyPasswordField() - minutes_between_check = html5.IntegerField('Maximum time in minutes until recheck', [validators.NumberRange(min=1)]) + extract_title_as_title = BooleanField('Extract from document and use as watch title') + base_url = StringField('Base URL', validators=[validators.Optional()]) diff --git a/changedetectionio/notification.py b/changedetectionio/notification.py index da015075..0a18fdba 100644 --- a/changedetectionio/notification.py +++ b/changedetectionio/notification.py @@ -57,7 +57,8 @@ def create_notification_parameters(n_object, datastore): watch_tag = '' # Create URLs to customise the notification with - base_url = os.getenv('BASE_URL', '').strip('"') + base_url = datastore.data['settings']['application']['base_url'] + watch_url = n_object['watch_url'] # Re #148 - Some people have just {base_url} in the body or title, but this may break some notification services diff --git a/changedetectionio/run_all_tests.sh b/changedetectionio/run_all_tests.sh index d4eb38e3..b9f8e229 100755 --- a/changedetectionio/run_all_tests.sh +++ b/changedetectionio/run_all_tests.sh @@ -9,11 +9,15 @@ # exit when any command fails set -e -# Re #65 - Ability to include a link back to the installation, in the notification. -export BASE_URL="https://foobar.com" find tests/test_*py -type f|while read test_name do echo "TEST RUNNING $test_name" pytest $test_name done + + +# Now re-run some tests with BASE_URL enabled +# Re #65 - Ability to include a link back to the installation, in the notification. +export BASE_URL="https://really-unique-domain.io" +pytest tests/test_notification.py diff --git a/changedetectionio/store.py b/changedetectionio/store.py index 25bcf613..0102f6e0 100644 --- a/changedetectionio/store.py +++ b/changedetectionio/store.py @@ -7,7 +7,7 @@ from copy import deepcopy import logging import time import threading - +import os # Is there an existing library to ensure some data store (JSON etc) is in sync with CRUD methods? # Open a github issue if you know something :) @@ -38,6 +38,7 @@ class ChangeDetectionStore: }, 'application': { 'password': False, + 'base_url' : None, 'extract_title_as_title': False, 'fetch_backend': 'html_requests', 'notification_urls': [], # Apprise URL list @@ -197,13 +198,15 @@ class ChangeDetectionStore: has_unviewed = True # #106 - Be sure this is None on empty string, False, None, etc - if not self.__data['watching'][uuid]['title']: - self.__data['watching'][uuid]['title'] = None - # Default var for fetch_backend if not self.__data['watching'][uuid]['fetch_backend']: self.__data['watching'][uuid]['fetch_backend'] = self.__data['settings']['application']['fetch_backend'] + # Re #152, Return env base_url if not overriden, @todo also prefer the proxy pass url + env_base_url = os.getenv('BASE_URL','') + if self.__data['settings']['application']['base_url'] is None and len(env_base_url) >0: + self.__data['settings']['application']['base_url'] = env_base_url.strip('" ') + self.__data['has_unviewed'] = has_unviewed return self.__data diff --git a/changedetectionio/templates/_common_fields.jinja b/changedetectionio/templates/_common_fields.jinja index 184e6011..55573781 100644 --- a/changedetectionio/templates/_common_fields.jinja +++ b/changedetectionio/templates/_common_fields.jinja @@ -3,9 +3,6 @@ {% macro render_notifications_field(form) %} - -<fieldset> - <div class="field-group"> <div class="pure-control-group"> {{ render_field(form.notification_urls, rows=5, placeholder="Examples: Gitter - gitter://token/room @@ -84,7 +81,4 @@ <div class="pure-control-group"> {{ render_field(form.trigger_check) }} </div> - </div> - - </fieldset> -{% endmacro %} \ No newline at end of file +{% endmacro %} diff --git a/changedetectionio/templates/edit.html b/changedetectionio/templates/edit.html index 95c6b14d..d1702bfd 100644 --- a/changedetectionio/templates/edit.html +++ b/changedetectionio/templates/edit.html @@ -64,7 +64,11 @@ User-Agent: wonderbra 1.0") }} <div class="tab-pane-inner" id="notifications"> <strong>Note: <i>These settings override the global settings.</i></strong> - {{ render_notifications_field(form) }} + <fieldset> + <div class="field-group"> + {{ render_notifications_field(form) }} + </div> + </fieldset> </div> <div class="tab-pane-inner" id="filters"> diff --git a/changedetectionio/templates/settings.html b/changedetectionio/templates/settings.html index f9850a55..0435e982 100644 --- a/changedetectionio/templates/settings.html +++ b/changedetectionio/templates/settings.html @@ -32,6 +32,15 @@ <span class="pure-form-message-inline">Password protection for your changedetection.io application.</span> {% endif %} </div> + <div class="pure-control-group"> + {{ render_field(form.base_url, placeholder="http://yoursite.com:5000/", + class="m-d") }} + <span class="pure-form-message-inline"> + Base URL used for the {base_url} token in notifications, default value is the ENV var 'base_url', + <a href="https://github.com/dgtlmoon/changedetection.io/wiki/Configurable-BASE_URL-setting">read more here</a>. + </span> + </div> + <div class="pure-control-group"> {{ render_field(form.extract_title_as_title) }} <span class="pure-form-message-inline">Note: This will automatically apply to all existing watches.</span> @@ -40,7 +49,11 @@ </div> <div class="tab-pane-inner" id="notifications"> - {{ render_notifications_field(form) }} + <fieldset> + <div class="field-group"> + {{ render_notifications_field(form) }} + </div> + </fieldset> </div> <div class="tab-pane-inner" id="fetching"> diff --git a/changedetectionio/tests/conftest.py b/changedetectionio/tests/conftest.py index f9b9de7c..fd2806d8 100644 --- a/changedetectionio/tests/conftest.py +++ b/changedetectionio/tests/conftest.py @@ -36,11 +36,8 @@ def app(request): except FileExistsError: pass - # Enable a BASE_URL for notifications to work (so we can look for diff/ etc URLs) - os.environ["BASE_URL"] = "http://mysite.com/" cleanup(datastore_path) - app_config = {'datastore_path': datastore_path} cleanup(app_config['datastore_path']) datastore = store.ChangeDetectionStore(datastore_path=app_config['datastore_path'], include_default_watches=False) diff --git a/changedetectionio/tests/test_notification.py b/changedetectionio/tests/test_notification.py index 9488dc93..95be9a10 100644 --- a/changedetectionio/tests/test_notification.py +++ b/changedetectionio/tests/test_notification.py @@ -3,6 +3,7 @@ import time import re from flask import url_for from . util import set_original_response, set_modified_response, live_server_setup +import logging # Hard to just add more live server URLs when one test is already running (I think) # So we add our test here (was in a different file) @@ -14,8 +15,16 @@ def test_check_notification(client, live_server): # Give the endpoint time to spin up time.sleep(3) - # re #242 - when you edited an existing new entry, it would not correctly show the notification settings + # When test mode is in BASE_URL env mode, we should see this already configured + env_base_url = os.getenv('BASE_URL', '').strip() + if len(env_base_url): + logging.debug(">>> BASE_URL enabled, looking for %s", env_base_url) + res = client.get(url_for("settings_page")) + assert bytes(env_base_url.encode('utf-8')) in res.data + else: + logging.debug(">>> SKIPPING BASE_URL check") + # re #242 - when you edited an existing new entry, it would not correctly show the notification settings # Add our URL to the import page test_url = url_for('test_endpoint', _external=True) res = client.post( @@ -104,9 +113,12 @@ def test_check_notification(client, live_server): assert test_url in notification_submission - # Re #65 - did we see our foobar.com BASE_URL ? - #assert bytes("https://foobar.com".encode('utf-8')) in notification_submission - + if env_base_url: + # Re #65 - did we see our BASE_URl ? + logging.debug (">>> BASE_URL checking in notification: %s", env_base_url) + assert env_base_url in notification_submission + else: + logging.debug(">>> Skipping BASE_URL check") ## Now configure something clever, we go into custom config (non-default) mode, this is returned by the endpoint with open("test-datastore/endpoint-content.txt", "w") as f: