mirror of
https://github.com/dgtlmoon/changedetection.io.git
synced 2025-11-20 08:26:12 +00:00
Compare commits
3 Commits
0.51.1
...
send-test-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f52e98f6fc | ||
|
|
a0b994cf54 | ||
|
|
2c0ba999af |
@@ -2,7 +2,7 @@ from flask import Blueprint, request, make_response
|
|||||||
import random
|
import random
|
||||||
from loguru import logger
|
from loguru import logger
|
||||||
|
|
||||||
from changedetectionio.notification_service import NotificationContextData
|
from changedetectionio.notification_service import NotificationContextData, set_basic_notification_vars
|
||||||
from changedetectionio.store import ChangeDetectionStore
|
from changedetectionio.store import ChangeDetectionStore
|
||||||
from changedetectionio.auth_decorator import login_optionally_required
|
from changedetectionio.auth_decorator import login_optionally_required
|
||||||
|
|
||||||
@@ -95,7 +95,44 @@ def construct_blueprint(datastore: ChangeDetectionStore):
|
|||||||
n_object['notification_body'] = "Test body"
|
n_object['notification_body'] = "Test body"
|
||||||
|
|
||||||
n_object['as_async'] = False
|
n_object['as_async'] = False
|
||||||
n_object.update(watch.extra_notification_token_values())
|
|
||||||
|
# Same like in notification service, should be refactored
|
||||||
|
dates = []
|
||||||
|
trigger_text = ''
|
||||||
|
snapshot_contents = ''
|
||||||
|
if watch:
|
||||||
|
watch_history = watch.history
|
||||||
|
dates = list(watch_history.keys())
|
||||||
|
trigger_text = watch.get('trigger_text', [])
|
||||||
|
# Add text that was triggered
|
||||||
|
if len(dates):
|
||||||
|
snapshot_contents = watch.get_history_snapshot(dates[-1])
|
||||||
|
else:
|
||||||
|
snapshot_contents = "No snapshot/history available, the watch should fetch atleast once."
|
||||||
|
|
||||||
|
if len(trigger_text):
|
||||||
|
from . import html_tools
|
||||||
|
triggered_text = html_tools.get_triggered_text(content=snapshot_contents, trigger_text=trigger_text)
|
||||||
|
if triggered_text:
|
||||||
|
triggered_text = '\n'.join(triggered_text)
|
||||||
|
|
||||||
|
# Could be called as a 'test notification' with only 1 snapshot available
|
||||||
|
prev_snapshot = "Example text: example test\nExample text: change detection is cool\nExample text: some more examples\n"
|
||||||
|
current_snapshot = "Example text: example test\nExample text: change detection is fantastic\nExample text: even more examples\nExample text: a lot more examples"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if len(dates) > 1:
|
||||||
|
prev_snapshot = watch.get_history_snapshot(dates[-2])
|
||||||
|
current_snapshot = watch.get_history_snapshot(dates[-1])
|
||||||
|
|
||||||
|
n_object.update(set_basic_notification_vars(snapshot_contents=snapshot_contents,
|
||||||
|
current_snapshot=current_snapshot,
|
||||||
|
prev_snapshot=prev_snapshot,
|
||||||
|
watch=watch,
|
||||||
|
triggered_text=trigger_text))
|
||||||
|
|
||||||
|
|
||||||
sent_obj = process_notification(n_object, datastore)
|
sent_obj = process_notification(n_object, datastore)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
|||||||
@@ -9,11 +9,8 @@ for both sync and async workers
|
|||||||
from loguru import logger
|
from loguru import logger
|
||||||
import time
|
import time
|
||||||
|
|
||||||
from changedetectionio.model import USE_SYSTEM_DEFAULT_NOTIFICATION_FORMAT_FOR_WATCH
|
|
||||||
from changedetectionio.notification import default_notification_format, valid_notification_formats
|
from changedetectionio.notification import default_notification_format, valid_notification_formats
|
||||||
|
|
||||||
# This gets modified on notification time (handler.py) depending on the required notification output
|
|
||||||
CUSTOM_LINEBREAK_PLACEHOLDER='@BR@'
|
|
||||||
|
|
||||||
|
|
||||||
# What is passed around as notification context, also used as the complete list of valid {{ tokens }}
|
# What is passed around as notification context, also used as the complete list of valid {{ tokens }}
|
||||||
@@ -71,6 +68,34 @@ class NotificationContextData(dict):
|
|||||||
|
|
||||||
super().__setitem__(key, value)
|
super().__setitem__(key, value)
|
||||||
|
|
||||||
|
|
||||||
|
def set_basic_notification_vars(snapshot_contents, current_snapshot, prev_snapshot, watch, triggered_text):
|
||||||
|
now = time.time()
|
||||||
|
from changedetectionio import diff
|
||||||
|
|
||||||
|
n_object = {
|
||||||
|
'current_snapshot': snapshot_contents,
|
||||||
|
'diff': diff.render_diff(prev_snapshot, current_snapshot),
|
||||||
|
'diff_added': diff.render_diff(prev_snapshot, current_snapshot, include_removed=False),
|
||||||
|
'diff_full': diff.render_diff(prev_snapshot, current_snapshot, include_equal=True),
|
||||||
|
'diff_patch': diff.render_diff(prev_snapshot, current_snapshot, patch_format=True),
|
||||||
|
'diff_removed': diff.render_diff(prev_snapshot, current_snapshot, include_added=False),
|
||||||
|
'screenshot': watch.get_screenshot() if watch and watch.get('notification_screenshot') else None,
|
||||||
|
'triggered_text': triggered_text,
|
||||||
|
'uuid': watch.get('uuid') if watch else None,
|
||||||
|
'watch_url': watch.get('url') if watch else None,
|
||||||
|
'watch_uuid': watch.get('uuid') if watch else None,
|
||||||
|
'watch_mime_type': watch.get('content-type')
|
||||||
|
}
|
||||||
|
|
||||||
|
# The \n's in the content from the above will get converted to <br> etc depending on the notification format
|
||||||
|
|
||||||
|
if watch:
|
||||||
|
n_object.update(watch.extra_notification_token_values())
|
||||||
|
|
||||||
|
logger.trace(f"Main rendered notification placeholders (diff_added etc) calculated in {time.time() - now:.3f}s")
|
||||||
|
return n_object
|
||||||
|
|
||||||
class NotificationService:
|
class NotificationService:
|
||||||
"""
|
"""
|
||||||
Standalone notification service that handles all notification functionality
|
Standalone notification service that handles all notification functionality
|
||||||
@@ -85,7 +110,6 @@ class NotificationService:
|
|||||||
"""
|
"""
|
||||||
Queue a notification for a watch with full diff rendering and template variables
|
Queue a notification for a watch with full diff rendering and template variables
|
||||||
"""
|
"""
|
||||||
from changedetectionio import diff
|
|
||||||
from changedetectionio.notification import USE_SYSTEM_DEFAULT_NOTIFICATION_FORMAT_FOR_WATCH
|
from changedetectionio.notification import USE_SYSTEM_DEFAULT_NOTIFICATION_FORMAT_FOR_WATCH
|
||||||
|
|
||||||
if not isinstance(n_object, NotificationContextData):
|
if not isinstance(n_object, NotificationContextData):
|
||||||
@@ -94,8 +118,6 @@ class NotificationService:
|
|||||||
dates = []
|
dates = []
|
||||||
trigger_text = ''
|
trigger_text = ''
|
||||||
|
|
||||||
now = time.time()
|
|
||||||
|
|
||||||
if watch:
|
if watch:
|
||||||
watch_history = watch.history
|
watch_history = watch.history
|
||||||
dates = list(watch_history.keys())
|
dates = list(watch_history.keys())
|
||||||
@@ -117,7 +139,7 @@ class NotificationService:
|
|||||||
from . import html_tools
|
from . import html_tools
|
||||||
triggered_text = html_tools.get_triggered_text(content=snapshot_contents, trigger_text=trigger_text)
|
triggered_text = html_tools.get_triggered_text(content=snapshot_contents, trigger_text=trigger_text)
|
||||||
if triggered_text:
|
if triggered_text:
|
||||||
triggered_text = CUSTOM_LINEBREAK_PLACEHOLDER.join(triggered_text)
|
triggered_text = '\n'.join(triggered_text)
|
||||||
|
|
||||||
# Could be called as a 'test notification' with only 1 snapshot available
|
# Could be called as a 'test notification' with only 1 snapshot available
|
||||||
prev_snapshot = "Example text: example test\nExample text: change detection is cool\nExample text: some more examples\n"
|
prev_snapshot = "Example text: example test\nExample text: change detection is cool\nExample text: some more examples\n"
|
||||||
@@ -127,26 +149,13 @@ class NotificationService:
|
|||||||
prev_snapshot = watch.get_history_snapshot(dates[-2])
|
prev_snapshot = watch.get_history_snapshot(dates[-2])
|
||||||
current_snapshot = watch.get_history_snapshot(dates[-1])
|
current_snapshot = watch.get_history_snapshot(dates[-1])
|
||||||
|
|
||||||
n_object.update({
|
|
||||||
'current_snapshot': snapshot_contents,
|
|
||||||
'diff': diff.render_diff(prev_snapshot, current_snapshot),
|
|
||||||
'diff_added': diff.render_diff(prev_snapshot, current_snapshot, include_removed=False),
|
|
||||||
'diff_full': diff.render_diff(prev_snapshot, current_snapshot, include_equal=True),
|
|
||||||
'diff_patch': diff.render_diff(prev_snapshot, current_snapshot, patch_format=True),
|
|
||||||
'diff_removed': diff.render_diff(prev_snapshot, current_snapshot, include_added=False),
|
|
||||||
'screenshot': watch.get_screenshot() if watch and watch.get('notification_screenshot') else None,
|
|
||||||
'triggered_text': triggered_text,
|
|
||||||
'uuid': watch.get('uuid') if watch else None,
|
|
||||||
'watch_url': watch.get('url') if watch else None,
|
|
||||||
'watch_uuid': watch.get('uuid') if watch else None,
|
|
||||||
'watch_mime_type': watch.get('content-type')
|
|
||||||
})
|
|
||||||
# The \n's in the content from the above will get converted to <br> etc depending on the notification format
|
|
||||||
|
|
||||||
if watch:
|
n_object.update(set_basic_notification_vars(snapshot_contents=snapshot_contents,
|
||||||
n_object.update(watch.extra_notification_token_values())
|
current_snapshot=current_snapshot,
|
||||||
|
prev_snapshot=prev_snapshot,
|
||||||
|
watch=watch,
|
||||||
|
triggered_text=triggered_text))
|
||||||
|
|
||||||
logger.trace(f"Main rendered notification placeholders (diff_added etc) calculated in {time.time()-now:.3f}s")
|
|
||||||
logger.debug("Queued notification for sending")
|
logger.debug("Queued notification for sending")
|
||||||
self.notification_q.put(n_object)
|
self.notification_q.put(n_object)
|
||||||
|
|
||||||
|
|||||||
@@ -329,12 +329,18 @@ a.pure-button-selected {
|
|||||||
.notifications-wrapper {
|
.notifications-wrapper {
|
||||||
padding-top: 0.5rem;
|
padding-top: 0.5rem;
|
||||||
#notification-test-log {
|
#notification-test-log {
|
||||||
padding-top: 1rem;
|
margin-top: 1rem;
|
||||||
|
padding: 1rem;
|
||||||
white-space: pre-wrap;
|
white-space: pre-wrap;
|
||||||
word-break: break-word;
|
word-break: break-word;
|
||||||
overflow-wrap: break-word;
|
overflow-wrap: break-word;
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
|
max-height: 12rem;
|
||||||
|
overflow-y: scroll;
|
||||||
|
border: 1px solid var(--color-border-notification);
|
||||||
|
border-radius: 5px;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -404,15 +404,15 @@ def test_notification_custom_endpoint_and_jinja2(client, live_server, measure_me
|
|||||||
|
|
||||||
|
|
||||||
#2510
|
#2510
|
||||||
|
#@todo run it again as text, html, htmlcolor
|
||||||
def test_global_send_test_notification(client, live_server, measure_memory_usage, datastore_path):
|
def test_global_send_test_notification(client, live_server, measure_memory_usage, datastore_path):
|
||||||
|
|
||||||
|
|
||||||
set_original_response(datastore_path=datastore_path)
|
set_original_response(datastore_path=datastore_path)
|
||||||
if os.path.isfile(os.path.join(datastore_path, "notification.txt")):
|
if os.path.isfile(os.path.join(datastore_path, "notification.txt")):
|
||||||
os.unlink(os.path.join(datastore_path, "notification.txt")) \
|
os.unlink(os.path.join(datastore_path, "notification.txt")) \
|
||||||
|
|
||||||
# 1995 UTF-8 content should be encoded
|
# 1995 UTF-8 content should be encoded
|
||||||
test_body = 'change detection is cool 网站监测 内容更新了'
|
test_body = 'change detection is cool 网站监测 内容更新了 - {{diff_full}}'
|
||||||
|
|
||||||
# otherwise other settings would have already existed from previous tests in this file
|
# otherwise other settings would have already existed from previous tests in this file
|
||||||
res = client.post(
|
res = client.post(
|
||||||
@@ -452,7 +452,14 @@ def test_global_send_test_notification(client, live_server, measure_memory_usage
|
|||||||
|
|
||||||
with open(os.path.join(datastore_path, "notification.txt"), 'r') as f:
|
with open(os.path.join(datastore_path, "notification.txt"), 'r') as f:
|
||||||
x = f.read()
|
x = f.read()
|
||||||
assert test_body in x
|
assert 'change detection is cool 网站监测 内容更新了' in x
|
||||||
|
if 'html' in default_notification_format:
|
||||||
|
# this should come from default text when in global/system mode here changedetectionio/notification_service.py
|
||||||
|
assert 'title="Changed into">Example text:' in x
|
||||||
|
else:
|
||||||
|
assert 'title="Changed into">Example text:' not in x
|
||||||
|
assert 'span' not in x
|
||||||
|
assert 'Example text:' in x
|
||||||
|
|
||||||
os.unlink(os.path.join(datastore_path, "notification.txt"))
|
os.unlink(os.path.join(datastore_path, "notification.txt"))
|
||||||
|
|
||||||
@@ -509,6 +516,47 @@ def test_global_send_test_notification(client, live_server, measure_memory_usage
|
|||||||
assert b"Error: You must have atleast one watch configured for 'test notification' to work" in res.data
|
assert b"Error: You must have atleast one watch configured for 'test notification' to work" in res.data
|
||||||
|
|
||||||
|
|
||||||
|
#2510
|
||||||
|
def test_single_send_test_notification_on_watch(client, live_server, measure_memory_usage, datastore_path):
|
||||||
|
|
||||||
|
set_original_response(datastore_path=datastore_path)
|
||||||
|
if os.path.isfile(os.path.join(datastore_path, "notification.txt")):
|
||||||
|
os.unlink(os.path.join(datastore_path, "notification.txt")) \
|
||||||
|
|
||||||
|
|
||||||
|
test_url = url_for('test_endpoint', _external=True)
|
||||||
|
uuid = client.application.config.get('DATASTORE').add_watch(url=test_url)
|
||||||
|
client.get(url_for("ui.form_watch_checknow"), follow_redirects=True)
|
||||||
|
|
||||||
|
test_notification_url = url_for('test_notification_endpoint', _external=True).replace('http://', 'post://')+"?xxx={{ watch_url }}&+custom-header=123"
|
||||||
|
# 1995 UTF-8 content should be encoded
|
||||||
|
test_body = 'change detection is cool 网站监测 内容更新了 - {{diff_full}}'
|
||||||
|
######### Test global/system settings
|
||||||
|
res = client.post(
|
||||||
|
url_for("ui.ui_notification.ajax_callback_send_notification_test")+f"/{uuid}",
|
||||||
|
data={"notification_urls": test_notification_url,
|
||||||
|
"notification_body": test_body,
|
||||||
|
"notification_format": default_notification_format,
|
||||||
|
"notification_title": "New ChangeDetection.io Notification - {{ watch_url }}",
|
||||||
|
},
|
||||||
|
follow_redirects=True
|
||||||
|
)
|
||||||
|
|
||||||
|
assert res.status_code != 400
|
||||||
|
assert res.status_code != 500
|
||||||
|
|
||||||
|
with open(os.path.join(datastore_path, "notification.txt"), 'r') as f:
|
||||||
|
x = f.read()
|
||||||
|
assert 'change detection is cool 网站监测 内容更新了' in x
|
||||||
|
if 'html' in default_notification_format:
|
||||||
|
# this should come from default text when in global/system mode here changedetectionio/notification_service.py
|
||||||
|
assert 'title="Changed into">Example text:' in x
|
||||||
|
else:
|
||||||
|
assert 'title="Changed into">Example text:' not in x
|
||||||
|
assert 'span' not in x
|
||||||
|
assert 'Example text:' in x
|
||||||
|
|
||||||
|
os.unlink(os.path.join(datastore_path, "notification.txt"))
|
||||||
|
|
||||||
def _test_color_notifications(client, notification_body_token, datastore_path):
|
def _test_color_notifications(client, notification_body_token, datastore_path):
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user