mirror of
				https://github.com/dgtlmoon/changedetection.io.git
				synced 2025-10-31 14:47:21 +00:00 
			
		
		
		
	Compare commits
	
		
			26 Commits
		
	
	
		
			0.42.2
			...
			jinja2-not
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | 5787f581e9 | ||
|   | 99524513c0 | ||
|   | 42e1098e7b | ||
|   | a1afb77f36 | ||
|   | 18a90825a1 | ||
|   | 8103634e9d | ||
|   | c9a2dd6920 | ||
|   | 7e76276703 | ||
|   | 5e0dae5703 | ||
|   | 8773f5ed90 | ||
|   | a5e6676431 | ||
|   | c51b243e7c | ||
|   | 5dd275555e | ||
|   | dbfcc3a5a3 | ||
|   | e97c2b3224 | ||
|   | 3f49d9591c | ||
|   | 8e254c4314 | ||
|   | f4163cfa6f | ||
|   | 86fbf505fd | ||
|   | 8bceb0abd4 | ||
|   | bba10afd97 | ||
|   | 658a88f895 | ||
|   | 4f602ff69a | ||
|   | 7c7946ec0b | ||
|   | 1d0ba2e633 | ||
|   | 72b9f9151b | 
| @@ -159,7 +159,7 @@ Just some examples | ||||
|  | ||||
| <img src="https://raw.githubusercontent.com/dgtlmoon/changedetection.io/master/docs/screenshot-notifications.png" style="max-width:100%;" alt="Self-hosted web page change monitoring notifications"  title="Self-hosted web page change monitoring notifications"  /> | ||||
|  | ||||
| Now you can also customise your notification content! | ||||
| Now you can also customise your notification content and use <a target="_new" href="https://jinja.palletsprojects.com/en/3.0.x/templates/">Jinja2 templating</a> for their title and body! | ||||
|  | ||||
| ## JSON API Monitoring | ||||
|  | ||||
|   | ||||
| @@ -193,7 +193,7 @@ class ValidateAppRiseServers(object): | ||||
|                 message = field.gettext('\'%s\' is not a valid AppRise URL.' % (server_url)) | ||||
|                 raise ValidationError(message) | ||||
|  | ||||
| class ValidateTokensList(object): | ||||
| class ValidateJinja2Template(object): | ||||
|     """ | ||||
|     Validates that a {token} is from a valid set | ||||
|     """ | ||||
| @@ -202,11 +202,24 @@ class ValidateTokensList(object): | ||||
|  | ||||
|     def __call__(self, form, field): | ||||
|         from changedetectionio import notification | ||||
|         regex = re.compile('{.*?}') | ||||
|         for p in re.findall(regex, field.data): | ||||
|             if not p.strip('{}') in notification.valid_tokens: | ||||
|                 message = field.gettext('Token \'%s\' is not a valid token.') | ||||
|                 raise ValidationError(message % (p)) | ||||
|  | ||||
|         from jinja2 import Environment, BaseLoader, TemplateSyntaxError | ||||
|         from jinja2.meta import find_undeclared_variables | ||||
|  | ||||
|  | ||||
|         try: | ||||
|             jinja2_env = Environment(loader=BaseLoader) | ||||
|             jinja2_env.globals.update(notification.valid_tokens) | ||||
|             rendered = jinja2_env.from_string(field.data).render() | ||||
|         except TemplateSyntaxError as e: | ||||
|             raise ValidationError(f"This is not a valid Jinja2 template: {e}") from e | ||||
|  | ||||
|         ast = jinja2_env.parse(field.data) | ||||
|         undefined = ", ".join(find_undeclared_variables(ast)) | ||||
|         if undefined: | ||||
|             raise ValidationError( | ||||
|                 f"The following tokens used in the notification are not valid: {undefined}" | ||||
|             ) | ||||
|  | ||||
| class validateURL(object): | ||||
|  | ||||
| @@ -225,6 +238,7 @@ class validateURL(object): | ||||
|             message = field.gettext('\'%s\' is not a valid URL.' % (field.data.strip())) | ||||
|             raise ValidationError(message) | ||||
|  | ||||
|  | ||||
| class ValidateListRegex(object): | ||||
|     """ | ||||
|     Validates that anything that looks like a regex passes as a regex | ||||
| @@ -333,11 +347,11 @@ class quickWatchForm(Form): | ||||
|  | ||||
| # Common to a single watch and the global settings | ||||
| class commonSettingsForm(Form): | ||||
|     notification_urls = StringListField('Notification URL list', validators=[validators.Optional(), ValidateAppRiseServers()]) | ||||
|     notification_title = StringField('Notification title', validators=[validators.Optional(), ValidateTokensList()]) | ||||
|     notification_body = TextAreaField('Notification body', validators=[validators.Optional(), ValidateTokensList()]) | ||||
|     notification_urls = StringListField('Notification URL List', validators=[validators.Optional(), ValidateAppRiseServers()]) | ||||
|     notification_title = StringField('Notification Title', default='ChangeDetection.io Notification - {{ watch_url }}', validators=[validators.Optional(), ValidateJinja2Template()]) | ||||
|     notification_body = TextAreaField('Notification Body', default='{{ watch_url }} had a change.', validators=[validators.Optional(), ValidateJinja2Template()]) | ||||
|     notification_format = SelectField('Notification format', choices=valid_notification_formats.keys()) | ||||
|     fetch_backend = RadioField(u'Fetch method', choices=content_fetcher.available_fetchers(), validators=[ValidateContentFetcherIsReady()]) | ||||
|     fetch_backend = RadioField(u'Fetch Method', choices=content_fetcher.available_fetchers(), validators=[ValidateContentFetcherIsReady()]) | ||||
|     extract_title_as_title = BooleanField('Extract <title> from document and use as watch title', default=False) | ||||
|     webdriver_delay = IntegerField('Wait seconds before extracting text', validators=[validators.Optional(), validators.NumberRange(min=1, | ||||
|                                                                                                                                     message="Should contain one or more seconds")]) | ||||
|   | ||||
| @@ -1,5 +1,7 @@ | ||||
| import apprise | ||||
| from jinja2 import Environment, BaseLoader | ||||
| from apprise import NotifyFormat | ||||
| import json | ||||
|  | ||||
| valid_tokens = { | ||||
|     'base_url': '', | ||||
| @@ -16,8 +18,8 @@ valid_tokens = { | ||||
|  | ||||
| default_notification_format_for_watch = 'System default' | ||||
| default_notification_format = 'Text' | ||||
| default_notification_body = '{watch_url} had a change.\n---\n{diff}\n---\n' | ||||
| default_notification_title = 'ChangeDetection.io Notification - {watch_url}' | ||||
| default_notification_body = '{{watch_url}} had a change.\n---\n{{diff}}\n---\n' | ||||
| default_notification_title = 'ChangeDetection.io Notification - {{watch_url}}' | ||||
|  | ||||
| valid_notification_formats = { | ||||
|     'Text': NotifyFormat.TEXT, | ||||
| @@ -27,25 +29,67 @@ valid_notification_formats = { | ||||
|     default_notification_format_for_watch: default_notification_format_for_watch | ||||
| } | ||||
|  | ||||
| def process_notification(n_object, datastore): | ||||
| # include the decorator | ||||
| from apprise.decorators import notify | ||||
|  | ||||
|     # Get the notification body from datastore | ||||
|     n_body = n_object.get('notification_body', default_notification_body) | ||||
|     n_title = n_object.get('notification_title', default_notification_title) | ||||
|     n_format = valid_notification_formats.get( | ||||
|         n_object['notification_format'], | ||||
|         valid_notification_formats[default_notification_format], | ||||
|     ) | ||||
| @notify(on="delete") | ||||
| @notify(on="deletes") | ||||
| @notify(on="get") | ||||
| @notify(on="gets") | ||||
| @notify(on="post") | ||||
| @notify(on="posts") | ||||
| @notify(on="put") | ||||
| @notify(on="puts") | ||||
| def apprise_custom_api_call_wrapper(body, title, notify_type, *args, **kwargs): | ||||
|     import requests | ||||
|     url = kwargs['meta'].get('url') | ||||
|  | ||||
|     if url.startswith('post'): | ||||
|         r = requests.post | ||||
|     elif url.startswith('get'): | ||||
|         r = requests.get | ||||
|     elif url.startswith('put'): | ||||
|         r = requests.put | ||||
|     elif url.startswith('delete'): | ||||
|         r = requests.delete | ||||
|  | ||||
|     url = url.replace('post://', 'http://') | ||||
|     url = url.replace('posts://', 'https://') | ||||
|     url = url.replace('put://', 'http://') | ||||
|     url = url.replace('puts://', 'https://') | ||||
|     url = url.replace('get://', 'http://') | ||||
|     url = url.replace('gets://', 'https://') | ||||
|     url = url.replace('put://', 'http://') | ||||
|     url = url.replace('puts://', 'https://') | ||||
|     url = url.replace('delete://', 'http://') | ||||
|     url = url.replace('deletes://', 'https://') | ||||
|  | ||||
|     # Try to auto-guess if it's JSON | ||||
|     headers = {} | ||||
|     try: | ||||
|         json.loads(body) | ||||
|         headers = {'Content-Type': 'application/json; charset=utf-8'} | ||||
|     except ValueError as e: | ||||
|         pass | ||||
|  | ||||
|  | ||||
|     r(url, headers=headers, data=body) | ||||
|  | ||||
|  | ||||
| def process_notification(n_object, datastore): | ||||
|  | ||||
|     # Insert variables into the notification content | ||||
|     notification_parameters = create_notification_parameters(n_object, datastore) | ||||
|  | ||||
|     for n_k in notification_parameters: | ||||
|         token = '{' + n_k + '}' | ||||
|         val = notification_parameters[n_k] | ||||
|         n_title = n_title.replace(token, val) | ||||
|         n_body = n_body.replace(token, val) | ||||
|  | ||||
|     # Get the notification body from datastore | ||||
|     jinja2_env = Environment(loader=BaseLoader) | ||||
|     n_body = jinja2_env.from_string(n_object.get('notification_body', default_notification_body)).render(**notification_parameters) | ||||
|     n_title = jinja2_env.from_string(n_object.get('notification_title', default_notification_title)).render(**notification_parameters) | ||||
|     n_format = valid_notification_formats.get( | ||||
|         n_object['notification_format'], | ||||
|         valid_notification_formats[default_notification_format], | ||||
|     ) | ||||
|      | ||||
|     # https://github.com/caronc/apprise/wiki/Development_LogCapture | ||||
|     # Anything higher than or equal to WARNING (which covers things like Connection errors) | ||||
|     # raise it as an exception | ||||
| @@ -53,6 +97,7 @@ def process_notification(n_object, datastore): | ||||
|     sent_objs=[] | ||||
|     from .apprise_asset import asset | ||||
|     for url in n_object['notification_urls']: | ||||
|         url = jinja2_env.from_string(url).render(**notification_parameters) | ||||
|         apobj = apprise.Apprise(debug=True, asset=asset) | ||||
|         url = url.strip() | ||||
|         if len(url): | ||||
| @@ -66,7 +111,12 @@ def process_notification(n_object, datastore): | ||||
|  | ||||
|                 # So if no avatar_url is specified, add one so it can be correctly calculated into the total payload | ||||
|                 k = '?' if not '?' in url else '&' | ||||
|                 if not 'avatar_url' in url and not url.startswith('mail'): | ||||
|                 if not 'avatar_url' in url \ | ||||
|                         and not url.startswith('mail') \ | ||||
|                         and not url.startswith('post') \ | ||||
|                         and not url.startswith('get') \ | ||||
|                         and not url.startswith('delete') \ | ||||
|                         and not url.startswith('put'): | ||||
|                     url += k + 'avatar_url=https://raw.githubusercontent.com/dgtlmoon/changedetection.io/master/changedetectionio/static/images/avatar-256x256.png' | ||||
|  | ||||
|                 if url.startswith('tgram://'): | ||||
| @@ -144,7 +194,7 @@ def create_notification_parameters(n_object, datastore): | ||||
|  | ||||
|     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 | ||||
|     # Re #148 - Some people have just {{ base_url }} in the body or title, but this may break some notification services | ||||
|     #           like 'Join', so it's always best to atleast set something obvious so that they are not broken. | ||||
|     if base_url == '': | ||||
|         base_url = "<base-url-env-var-not-set>" | ||||
|   | ||||
| @@ -877,6 +877,9 @@ body.full-width { | ||||
|   .pure-form-message-inline { | ||||
|     padding-left: 0; | ||||
|     color: var(--color-text-input-description); | ||||
|     code { | ||||
|       font-size: .875em; | ||||
|     } | ||||
|   } | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -851,6 +851,8 @@ body.full-width .edit-form { | ||||
|   .edit-form .pure-form-message-inline { | ||||
|     padding-left: 0; | ||||
|     color: var(--color-text-input-description); } | ||||
|     .edit-form .pure-form-message-inline code { | ||||
|       font-size: .875em; } | ||||
|  | ||||
| ul { | ||||
|   padding-left: 1em; | ||||
|   | ||||
| @@ -621,4 +621,44 @@ class ChangeDetectionStore: | ||||
|                     watch['include_filters'] = [existing_filter] | ||||
|             except: | ||||
|                 continue | ||||
|         return | ||||
|         return | ||||
|  | ||||
|     # Convert old static notification tokens to jinja2 tokens | ||||
|     def update_9(self): | ||||
|         # Each watch | ||||
|         import re | ||||
|         # only { } not {{ or }} | ||||
|         r = r'(?<!{){(?!{)(\w+)(?<!})}(?!})' | ||||
|         for uuid, watch in self.data['watching'].items(): | ||||
|             try: | ||||
|                 n_body = watch.get('notification_body', '') | ||||
|                 if n_body: | ||||
|                     watch['notification_body'] = re.sub(r, r'{{\1}}', n_body) | ||||
|  | ||||
|                 n_title = watch.get('notification_title') | ||||
|                 if n_title: | ||||
|                     self.data['settings']['application']['notification_title'] = re.sub(r, r'{{\1}}', n_title) | ||||
|  | ||||
|                 n_urls = watch.get('notification_urls') | ||||
|                 if n_urls: | ||||
|                     for i, url in enumerate(n_urls): | ||||
|                         watch['notification_urls'][i] = re.sub(r, r'{{\1}}', url) | ||||
|  | ||||
|             except: | ||||
|                 continue | ||||
|  | ||||
|         # System wide | ||||
|         n_body = self.data['settings']['application'].get('notification_body') | ||||
|         if n_body: | ||||
|             self.data['settings']['application']['notification_body'] = re.sub(r, r'{{\1}}', n_body) | ||||
|  | ||||
|         n_title = self.data['settings']['application'].get('notification_title') | ||||
|         if n_body: | ||||
|             self.data['settings']['application']['notification_title'] = re.sub(r, r'{{\1}}', n_title) | ||||
|  | ||||
|         n_urls =  self.data['settings']['application'].get('notification_urls') | ||||
|         if n_urls: | ||||
|             for i, url in enumerate(n_urls): | ||||
|                 self.data['settings']['application']['notification_urls'][i] = re.sub(r, r'{{\1}}', url) | ||||
|  | ||||
|         return | ||||
|   | ||||
| @@ -16,6 +16,7 @@ | ||||
|                                 <li><code>discord://</code> only supports a maximum <strong>2,000 characters</strong> of notification text, including the title.</li> | ||||
|                                 <li><code>tgram://</code> bots cant send messages to other bots, so you should specify chat ID of non-bot user.</li> | ||||
|                                 <li><code>tgram://</code> only supports very limited HTML and can fail when extra tags are sent, <a href="https://core.telegram.org/bots/api#html-style">read more here</a> (or use plaintext/markdown format)</li> | ||||
|                                 <li><code>gets://</code>, <code>posts://</code>, <code>puts://</code>, <code>deletes://</code> for direct API calls (or omit the "<code>s</code>" for non-SSL ie <code>get://</code>)</li> | ||||
|                               </ul> | ||||
|                             </div> | ||||
|                             <div class="notifications-wrapper"> | ||||
| @@ -41,8 +42,9 @@ | ||||
|                                 <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 customise the notification text. | ||||
|                             <p class="pure-form-message-inline"> | ||||
|                                 You can use <a target="_new" href="https://jinja.palletsprojects.com/en/3.0.x/templates/">Jinja2</a> templating in the notification title, body and URL. | ||||
|                             </p> | ||||
|  | ||||
|                                 <table class="pure-table" id="token-table"> | ||||
|                                     <thead> | ||||
| @@ -53,52 +55,49 @@ | ||||
|                                     </thead> | ||||
|                                     <tbody> | ||||
|                                     <tr> | ||||
|                                         <td><code>{base_url}</code></td> | ||||
|                                         <td><code>{{ '{{ base_url }}' }}</code></td> | ||||
|                                         <td>The URL of the changedetection.io instance you are running.</td> | ||||
|                                     </tr> | ||||
|                                     <tr> | ||||
|                                         <td><code>{watch_url}</code></td> | ||||
|                                         <td><code>{{ '{{ watch_url }}' }}</code></td> | ||||
|                                         <td>The URL being watched.</td> | ||||
|                                     </tr> | ||||
|                                     <tr> | ||||
|                                         <td><code>{watch_uuid}</code></td> | ||||
|                                         <td><code>{{ '{{ watch_uuid }}' }}</code></td> | ||||
|                                         <td>The UUID of the watch.</td> | ||||
|                                     </tr> | ||||
|                                     <tr> | ||||
|                                         <td><code>{watch_title}</code></td> | ||||
|                                         <td><code>{{ '{{ watch_title }}' }}</code></td> | ||||
|                                         <td>The title of the watch.</td> | ||||
|                                     </tr> | ||||
|                                     <tr> | ||||
|                                         <td><code>{watch_tag}</code></td> | ||||
|                                         <td><code>{{ '{{ watch_tag }}' }}</code></td> | ||||
|                                         <td>The tag of the watch.</td> | ||||
|                                     </tr> | ||||
|                                     <tr> | ||||
|                                         <td><code>{preview_url}</code></td> | ||||
|                                         <td><code>{{ '{{ preview_url }}' }}</code></td> | ||||
|                                         <td>The URL of the preview page generated by changedetection.io.</td> | ||||
|                                     </tr> | ||||
|                                     <tr> | ||||
|                                         <td><code>{diff}</code></td> | ||||
|                                         <td><code>{{ '{{ diff_url }}' }}</code></td> | ||||
|                                         <td>The diff output - differences only</td> | ||||
|                                     </tr> | ||||
|                                     <tr> | ||||
|                                         <td><code>{diff_full}</code></td> | ||||
|                                         <td><code>{{ '{{ diff_full }}' }}</code></td> | ||||
|                                         <td>The diff output - full difference output</td> | ||||
|                                     </tr> | ||||
|                                     <tr> | ||||
|                                         <td><code>{diff_url}</code></td> | ||||
|                                         <td>The URL of the diff page generated by changedetection.io.</td> | ||||
|                                     </tr> | ||||
|                                     <tr> | ||||
|                                         <td><code>{current_snapshot}</code></td> | ||||
|                                         <td><code>{{ '{{ current_snapshot }}' }}</code></td> | ||||
|                                         <td>The current snapshot value, useful when combined with JSON or CSS filters | ||||
|                                         </td> | ||||
|                                     </tr> | ||||
|                                     </tbody> | ||||
|                                 </table> | ||||
|                                 <br/> | ||||
|                                 URLs generated by changedetection.io (such as <code>{diff_url}</code>) require the <code>BASE_URL</code> environment variable set.<br/> | ||||
|                                 Your <code>BASE_URL</code> var is currently "{{settings_application['current_base_url']}}" | ||||
|                             </span> | ||||
|                                 <div class="pure-form-message-inline"> | ||||
|                                     <br> | ||||
|                                     URLs generated by changedetection.io (such as <code>{{ '{{ diff_url }}' }}</code>) require the <code>BASE_URL</code> environment variable set.<br/> | ||||
|                                     Your <code>BASE_URL</code> var is currently "{{settings_application['current_base_url']}}" | ||||
|                                 </div> | ||||
|                             </div> | ||||
|                         </div> | ||||
| {% endmacro %} | ||||
|   | ||||
| @@ -60,7 +60,7 @@ | ||||
|                         {{ render_field(form.application.form.base_url, placeholder="http://yoursite.com:5000/", | ||||
|                         class="m-d") }} | ||||
|                         <span class="pure-form-message-inline"> | ||||
|                             Base URL used for the <code>{base_url}</code> token in notifications and RSS links.<br/>Default value is the ENV var 'BASE_URL' (Currently "{{settings_application['current_base_url']}}"), | ||||
|                             Base URL used for the <code>{{ '{{ base_url }}' }}</code> token in notifications and RSS links.<br/>Default value is the ENV var 'BASE_URL' (Currently "{{settings_application['current_base_url']}}"), | ||||
|                             <a href="https://github.com/dgtlmoon/changedetection.io/wiki/Configurable-BASE_URL-setting">read more here</a>. | ||||
|                         </span> | ||||
|                     </div> | ||||
|   | ||||
| @@ -73,17 +73,17 @@ def test_filter_doesnt_exist_then_exists_should_get_notification(client, live_se | ||||
|  | ||||
|     # Just a regular notification setting, this will be used by the special 'filter not found' notification | ||||
|     notification_form_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" | ||||
|                                                    "Diff: {diff}\n" | ||||
|                                                    "Diff Full: {diff_full}\n" | ||||
|                               "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" | ||||
|                                                    "Diff: {{diff}}\n" | ||||
|                                                    "Diff Full: {{diff_full}}\n" | ||||
|                                                    ":-)", | ||||
|                               "notification_format": "Text"} | ||||
|  | ||||
|   | ||||
| @@ -56,17 +56,17 @@ def run_filter_test(client, content_filter): | ||||
|  | ||||
|     # Just a regular notification setting, this will be used by the special 'filter not found' notification | ||||
|     notification_form_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" | ||||
|                                                    "Diff: {diff}\n" | ||||
|                                                    "Diff Full: {diff_full}\n" | ||||
|                               "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" | ||||
|                                                    "Diff: {{diff}}\n" | ||||
|                                                    "Diff Full: {{diff_full}}\n" | ||||
|                                                    ":-)", | ||||
|                               "notification_format": "Text"} | ||||
|  | ||||
| @@ -84,6 +84,7 @@ def run_filter_test(client, content_filter): | ||||
|         data=notification_form_data, | ||||
|         follow_redirects=True | ||||
|     ) | ||||
|  | ||||
|     assert b"Updated watch." in res.data | ||||
|     time.sleep(3) | ||||
|  | ||||
|   | ||||
| @@ -90,17 +90,17 @@ def test_check_notification(client, live_server): | ||||
|     print (">>>> Notification URL: "+notification_url) | ||||
|  | ||||
|     notification_form_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" | ||||
|                                                    "Diff: {diff}\n" | ||||
|                                                    "Diff Full: {diff_full}\n" | ||||
|                               "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" | ||||
|                                                    "Diff: {{diff}}\n" | ||||
|                                                    "Diff Full: {{diff_full}}\n" | ||||
|                                                    ":-)", | ||||
|                               "notification_screenshot": True, | ||||
|                               "notification_format": "Text"} | ||||
| @@ -179,7 +179,6 @@ def test_check_notification(client, live_server): | ||||
|         logging.debug(">>> Skipping BASE_URL check") | ||||
|  | ||||
|  | ||||
|  | ||||
|     # This should insert the {current_snapshot} | ||||
|     set_more_modified_response() | ||||
|     client.get(url_for("form_watch_checknow"), follow_redirects=True) | ||||
| @@ -237,10 +236,9 @@ def test_check_notification(client, live_server): | ||||
|         follow_redirects=True | ||||
|     ) | ||||
|  | ||||
|  | ||||
| def test_notification_validation(client, live_server): | ||||
|     #live_server_setup(live_server) | ||||
|     time.sleep(3) | ||||
|     time.sleep(1) | ||||
|  | ||||
|     # 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) | ||||
| @@ -269,19 +267,33 @@ def test_notification_validation(client, live_server): | ||||
| #    assert b"Notification Body and Title is required when a Notification URL is used" in res.data | ||||
|  | ||||
|     # Now adding a wrong token should give us an error | ||||
| # Disabled for now | ||||
| #    res = client.post( | ||||
| #        url_for("settings_page"), | ||||
| #        data={"application-notification_title": "New ChangeDetection.io Notification - {{watch_url}}", | ||||
| #              "application-notification_body": "Rubbish: {{rubbish}}\n", | ||||
| #              "application-notification_format": "Text", | ||||
| #              "application-notification_urls": "json://localhost/foobar", | ||||
| #              "requests-time_between_check-minutes": 180, | ||||
| #              "fetch_backend": "html_requests" | ||||
| #              }, | ||||
| #        follow_redirects=True | ||||
| #    ) | ||||
| #    assert bytes("Token 'rubbish' is not a valid token or is unknown".encode('utf-8')) in res.data | ||||
|  | ||||
|     # And trying to define an invalid Jinja2 template should also throw an error | ||||
|     res = client.post( | ||||
|         url_for("settings_page"), | ||||
|         data={"application-notification_title": "New ChangeDetection.io Notification - {watch_url}", | ||||
|               "application-notification_body": "Rubbish: {rubbish}\n", | ||||
|               "application-notification_format": "Text", | ||||
|               "application-notification_urls": "json://localhost/foobar", | ||||
|               "requests-time_between_check-minutes": 180, | ||||
|               "fetch_backend": "html_requests" | ||||
|         data={"application-notification_title": "New ChangeDetection.io Notification - {{ watch_url }}", | ||||
|               "application-notification_body": "Rubbish: {{ rubbish }\n", | ||||
|               "application-notification_urls": "json://foobar.com", | ||||
|               "application-minutes_between_check": 180, | ||||
|               "application-fetch_backend": "html_requests" | ||||
|               }, | ||||
|         follow_redirects=True | ||||
|     ) | ||||
|     assert bytes("This is not a valid Jinja2 template".encode('utf-8')) in res.data | ||||
|  | ||||
|     assert bytes("is not a valid token".encode('utf-8')) in res.data | ||||
|  | ||||
|     # cleanup for the next | ||||
|     client.get( | ||||
| @@ -289,4 +301,55 @@ def test_notification_validation(client, live_server): | ||||
|         follow_redirects=True | ||||
|     ) | ||||
|  | ||||
| def test_notification_jinja2(client, live_server): | ||||
|     #live_server_setup(live_server) | ||||
|     time.sleep(1) | ||||
|  | ||||
|     # test_endpoint - that sends the contents of a file | ||||
|     # test_notification_endpoint - that takes a POST and writes it to file (test-datastore/notification.txt) | ||||
|  | ||||
|     # CUSTOM JSON BODY CHECK for POST:// | ||||
|     set_original_response() | ||||
|     test_notification_url = url_for('test_notification_endpoint', _external=True).replace('http://', 'post://')+"?xxx={{ watch_url }}" | ||||
|  | ||||
|     res = client.post( | ||||
|         url_for("settings_page"), | ||||
|         data={"application-notification_title": "New ChangeDetection.io Notification - {{ watch_url }}", | ||||
|               "application-notification_body": '{ "url" : "{{ watch_url }}", "secret": 444 }', | ||||
|               # https://github.com/caronc/apprise/wiki/Notify_Custom_JSON#get-parameter-manipulation | ||||
|               "application-notification_urls": test_notification_url, | ||||
|               "application-minutes_between_check": 180, | ||||
|               "application-fetch_backend": "html_requests" | ||||
|               }, | ||||
|         follow_redirects=True | ||||
|     ) | ||||
|     assert b'Settings updated' in res.data | ||||
|  | ||||
|     # Add a watch and trigger a HTTP POST | ||||
|     test_url = url_for('test_endpoint', _external=True) | ||||
|     res = client.post( | ||||
|         url_for("form_quick_watch_add"), | ||||
|         data={"url": test_url, "tag": 'nice one'}, | ||||
|         follow_redirects=True | ||||
|     ) | ||||
|  | ||||
|     assert b"Watch added" in res.data | ||||
|  | ||||
|     time.sleep(2) | ||||
|     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: | ||||
|         x=f.read() | ||||
|         j = json.loads(x) | ||||
|         assert j['url'].startswith('http://localhost') | ||||
|         assert j['secret'] == 444 | ||||
|  | ||||
|     # URL check, this will always be converted to lowercase | ||||
|     assert os.path.isfile("test-datastore/notification-url.txt") | ||||
|     with open("test-datastore/notification-url.txt", 'r') as f: | ||||
|         notification_url = f.read() | ||||
|         assert 'xxx=http' in notification_url | ||||
|     os.unlink("test-datastore/notification-url.txt") | ||||
| @@ -149,6 +149,9 @@ def live_server_setup(live_server): | ||||
|             if data != None: | ||||
|                 f.write(data) | ||||
|  | ||||
|         with open("test-datastore/notification-url.txt", "w") as f: | ||||
|             f.write(request.url) | ||||
|  | ||||
|         print("\n>> Test notification endpoint was hit.\n", data) | ||||
|         return "Text was set" | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user