mirror of
				https://github.com/dgtlmoon/changedetection.io.git
				synced 2025-10-30 22:27:52 +00:00 
			
		
		
		
	Compare commits
	
		
			8 Commits
		
	
	
		
			url-valida
			...
			fixing-pos
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | aff506c916 | ||
|   | 920e0f0300 | ||
|   | 15cd5fbc75 | ||
|   | 9314839d23 | ||
|   | ed27d8f17c | ||
|   | 8177ccea66 | ||
|   | b899579ca8 | ||
|   | 1f7f1e2bfa | 
| @@ -46,6 +46,9 @@ from apprise.decorators import notify | ||||
| @notify(on="puts") | ||||
| def apprise_custom_api_call_wrapper(body, title, notify_type, *args, **kwargs): | ||||
|     import requests | ||||
|     from apprise.utils import parse_url as apprise_parse_url | ||||
|     from apprise.URLBase import URLBase | ||||
|  | ||||
|     url = kwargs['meta'].get('url') | ||||
|  | ||||
|     if url.startswith('post'): | ||||
| @@ -68,16 +71,45 @@ def apprise_custom_api_call_wrapper(body, title, notify_type, *args, **kwargs): | ||||
|     url = url.replace('delete://', 'http://') | ||||
|     url = url.replace('deletes://', 'https://') | ||||
|  | ||||
|     # Try to auto-guess if it's JSON | ||||
|     headers = {} | ||||
|     params = {} | ||||
|     auth = None | ||||
|  | ||||
|     # Convert /foobar?+some-header=hello to proper header dictionary | ||||
|     results = apprise_parse_url(url) | ||||
|     if results: | ||||
|         # Add our headers that the user can potentially over-ride if they wish | ||||
|         # to to our returned result set and tidy entries by unquoting them | ||||
|         headers = {URLBase.unquote(x): URLBase.unquote(y) | ||||
|                    for x, y in results['qsd+'].items()} | ||||
|  | ||||
|         # https://github.com/caronc/apprise/wiki/Notify_Custom_JSON#get-parameter-manipulation | ||||
|         # In Apprise, it relies on prefixing each request arg with "-", because it uses say &method=update as a flag for apprise | ||||
|         # but here we are making straight requests, so we need todo convert this against apprise's logic | ||||
|         for k, v in results['qsd'].items(): | ||||
|             if not k.strip('+-') in results['qsd+'].keys(): | ||||
|                 params[URLBase.unquote(k)] = URLBase.unquote(v) | ||||
|  | ||||
|         # Determine Authentication | ||||
|         auth = '' | ||||
|         if results.get('user') and results.get('password'): | ||||
|             auth = (URLBase.unquote(results.get('user')), URLBase.unquote(results.get('user'))) | ||||
|         elif results.get('user'): | ||||
|             auth = (URLBase.unquote(results.get('user'))) | ||||
|  | ||||
|     # Try to auto-guess if it's JSON | ||||
|     try: | ||||
|         json.loads(body) | ||||
|         headers = {'Content-Type': 'application/json; charset=utf-8'} | ||||
|         headers['Content-Type'] = 'application/json; charset=utf-8' | ||||
|     except ValueError as e: | ||||
|         pass | ||||
|  | ||||
|  | ||||
|     r(url, headers=headers, data=body) | ||||
|     r(results.get('url'), | ||||
|       auth=auth, | ||||
|       data=body, | ||||
|       headers=headers, | ||||
|       params=params | ||||
|       ) | ||||
|  | ||||
|  | ||||
| def process_notification(n_object, datastore): | ||||
|   | ||||
| @@ -16,7 +16,7 @@ | ||||
|                                 <li><code><a target=_new href="https://github.com/caronc/apprise/wiki/Notify_discord">discord://</a></code> (or <code>https://discord.com/api/webhooks...</code>)) only supports a maximum <strong>2,000 characters</strong> of notification text, including the title.</li> | ||||
|                                 <li><code><a target=_new href="https://github.com/caronc/apprise/wiki/Notify_telegram">tgram://</a></code> bots can't send messages to other bots, so you should specify chat ID of non-bot user.</li> | ||||
|                                 <li><code><a target=_new href="https://github.com/caronc/apprise/wiki/Notify_telegram">tgram://</a></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> | ||||
|                                 <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>) <a href="https://github.com/dgtlmoon/changedetection.io/wiki/Notification-configuration-notes#postposts">more help here</a></li> | ||||
|                                   <li>Accepts the <code>{{ '{{token}}' }}</code> placeholders listed below</li> | ||||
|                               </ul> | ||||
|                             </div> | ||||
|   | ||||
| @@ -13,22 +13,17 @@ global app | ||||
|  | ||||
|  | ||||
| def cleanup(datastore_path): | ||||
|     import glob | ||||
|     # Unlink test output files | ||||
|     files = [ | ||||
|         'count.txt', | ||||
|         'endpoint-content.txt' | ||||
|         'headers.txt', | ||||
|         'headers-testtag.txt', | ||||
|         'notification.txt', | ||||
|         'secret.txt', | ||||
|         'url-watches.json', | ||||
|         'output.txt', | ||||
|     ] | ||||
|     for file in files: | ||||
|         try: | ||||
|             os.unlink("{}/{}".format(datastore_path, file)) | ||||
|         except FileNotFoundError: | ||||
|             pass | ||||
|  | ||||
|     for g in ["*.txt", "*.json", "*.pdf"]: | ||||
|         files = glob.glob(os.path.join(datastore_path, g)) | ||||
|         for f in files: | ||||
|             if 'proxies.json' in f: | ||||
|                 # Usually mounted by docker container during test time | ||||
|                 continue | ||||
|             if os.path.isfile(f): | ||||
|                 os.unlink(f) | ||||
|  | ||||
| @pytest.fixture(scope='session') | ||||
| def app(request): | ||||
|   | ||||
| @@ -281,7 +281,8 @@ def test_notification_custom_endpoint_and_jinja2(client, live_server): | ||||
|  | ||||
|     # 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 }}" | ||||
|     # https://github.com/caronc/apprise/wiki/Notify_Custom_JSON#header-manipulation | ||||
|     test_notification_url = url_for('test_notification_endpoint', _external=True).replace('http://', 'post://')+"?xxx={{ watch_url }}&+custom-header=123" | ||||
|  | ||||
|     res = client.post( | ||||
|         url_for("settings_page"), | ||||
| @@ -297,10 +298,7 @@ def test_notification_custom_endpoint_and_jinja2(client, live_server): | ||||
|         follow_redirects=True | ||||
|     ) | ||||
|     assert b'Settings updated' in res.data | ||||
|     client.get( | ||||
|         url_for("form_delete", uuid="all"), | ||||
|         follow_redirects=True | ||||
|     ) | ||||
|  | ||||
|     # Add a watch and trigger a HTTP POST | ||||
|     test_url = url_for('test_endpoint', _external=True) | ||||
|     res = client.post( | ||||
| @@ -315,7 +313,9 @@ def test_notification_custom_endpoint_and_jinja2(client, live_server): | ||||
|     set_modified_response() | ||||
|  | ||||
|     client.get(url_for("form_watch_checknow"), follow_redirects=True) | ||||
|     time.sleep(2) | ||||
|     wait_for_all_checks(client) | ||||
|  | ||||
|     time.sleep(2) # plus extra delay for notifications to fire | ||||
|  | ||||
|     with open("test-datastore/notification.txt", 'r') as f: | ||||
|         x = f.read() | ||||
| @@ -328,6 +328,13 @@ def test_notification_custom_endpoint_and_jinja2(client, live_server): | ||||
|     with open("test-datastore/notification-url.txt", 'r') as f: | ||||
|         notification_url = f.read() | ||||
|         assert 'xxx=http' in notification_url | ||||
|         # apprise style headers should be stripped | ||||
|         assert 'custom-header' not in notification_url | ||||
|  | ||||
|     with open("test-datastore/notification-headers.txt", 'r') as f: | ||||
|         notification_headers = f.read() | ||||
|         assert 'custom-header: 123' in notification_headers.lower() | ||||
|  | ||||
|  | ||||
|     # Should always be automatically detected as JSON content type even when we set it as 'Text' (default) | ||||
|     assert os.path.isfile("test-datastore/notification-content-type.txt") | ||||
| @@ -335,3 +342,8 @@ def test_notification_custom_endpoint_and_jinja2(client, live_server): | ||||
|         assert 'application/json' in f.read() | ||||
|  | ||||
|     os.unlink("test-datastore/notification-url.txt") | ||||
|  | ||||
|     client.get( | ||||
|         url_for("form_delete", uuid="all"), | ||||
|         follow_redirects=True | ||||
|     ) | ||||
|   | ||||
| @@ -205,6 +205,9 @@ def live_server_setup(live_server): | ||||
|         with open("test-datastore/notification-url.txt", "w") as f: | ||||
|             f.write(request.url) | ||||
|  | ||||
|         with open("test-datastore/notification-headers.txt", "w") as f: | ||||
|             f.write(str(request.headers)) | ||||
|  | ||||
|         if request.content_type: | ||||
|             with open("test-datastore/notification-content-type.txt", "w") as f: | ||||
|                 f.write(request.content_type) | ||||
|   | ||||
		Reference in New Issue
	
	Block a user