diff --git a/changedetectionio/diff.py b/changedetectionio/diff.py index 9cb4c9fe..3371ad4d 100644 --- a/changedetectionio/diff.py +++ b/changedetectionio/diff.py @@ -35,15 +35,19 @@ def customSequenceMatcher(before, after, include_equal=False, include_removed=Tr # only_differences - only return info about the differences, no context # line_feed_sep could be "
" or "
  • " or "\n" etc -def render_diff(previous_version_file_contents, newest_version_file_contents, include_equal=False, include_removed=True, include_added=True, include_replaced=True, line_feed_sep="\n", include_change_type_prefix=True): +def render_diff(previous_version_file_contents, newest_version_file_contents, include_equal=False, include_removed=True, include_added=True, include_replaced=True, line_feed_sep="\n", include_change_type_prefix=True, patch_format=False): newest_version_file_contents = [line.rstrip() for line in newest_version_file_contents.splitlines()] if previous_version_file_contents: - previous_version_file_contents = [line.rstrip() for line in previous_version_file_contents.splitlines()] + previous_version_file_contents = [line.rstrip() for line in previous_version_file_contents.splitlines()] else: previous_version_file_contents = "" + if patch_format: + patch = difflib.unified_diff(previous_version_file_contents, newest_version_file_contents) + return line_feed_sep.join(patch) + rendered_diff = customSequenceMatcher(before=previous_version_file_contents, after=newest_version_file_contents, include_equal=include_equal, diff --git a/changedetectionio/notification.py b/changedetectionio/notification.py index d2beda01..27c7afa7 100644 --- a/changedetectionio/notification.py +++ b/changedetectionio/notification.py @@ -9,6 +9,7 @@ valid_tokens = { 'diff': '', 'diff_added': '', 'diff_full': '', + 'diff_patch': '', 'diff_removed': '', 'diff_url': '', 'preview_url': '', @@ -98,7 +99,7 @@ def process_notification(n_object, datastore): # Initially text or whatever n_format = datastore.data['settings']['application'].get('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 @@ -177,7 +178,7 @@ def process_notification(n_object, datastore): log_value = logs.getvalue() if log_value and 'WARNING' in log_value or 'ERROR' in log_value: raise Exception(log_value) - + sent_objs.append({'title': n_title, 'body': n_body, 'url' : url, @@ -230,6 +231,7 @@ def create_notification_parameters(n_object, datastore): 'diff': n_object.get('diff', ''), # Null default in the case we use a test 'diff_added': n_object.get('diff_added', ''), # Null default in the case we use a test 'diff_full': n_object.get('diff_full', ''), # Null default in the case we use a test + 'diff_patch': n_object.get('diff_patch', ''), # Null default in the case we use a test 'diff_removed': n_object.get('diff_removed', ''), # Null default in the case we use a test 'diff_url': diff_url, 'preview_url': preview_url, diff --git a/changedetectionio/templates/_common_fields.jinja b/changedetectionio/templates/_common_fields.jinja index c8ffdb00..6b6f6e05 100644 --- a/changedetectionio/templates/_common_fields.jinja +++ b/changedetectionio/templates/_common_fields.jinja @@ -99,6 +99,10 @@ {{ '{{diff_full}}' }} The diff output - full difference output + + {{ '{{diff_patch}}' }} + The diff output - patch in unified format + {{ '{{current_snapshot}}' }} The current snapshot value, useful when combined with JSON or CSS filters diff --git a/changedetectionio/tests/test_filter_exist_changes.py b/changedetectionio/tests/test_filter_exist_changes.py index 24f84455..e57db579 100644 --- a/changedetectionio/tests/test_filter_exist_changes.py +++ b/changedetectionio/tests/test_filter_exist_changes.py @@ -15,7 +15,7 @@ def set_response_without_filter():

    Which is across multiple lines


    So let's see what happens.
    -
    Some text thats the same
    +
    Some text thats the same
    """ @@ -32,7 +32,7 @@ def set_response_with_filter():

    Which is across multiple lines


    So let's see what happens.
    -
    Ticket now on sale!
    +
    Ticket now on sale!
    """ @@ -84,6 +84,7 @@ def test_filter_doesnt_exist_then_exists_should_get_notification(client, live_se "Snapshot: {{current_snapshot}}\n" "Diff: {{diff}}\n" "Diff Full: {{diff_full}}\n" + "Diff as Patch: {{diff_patch}}\n" ":-)", "notification_format": "Text"} diff --git a/changedetectionio/tests/test_filter_failure_notification.py b/changedetectionio/tests/test_filter_failure_notification.py index 3ec5bfb7..b25931ea 100644 --- a/changedetectionio/tests/test_filter_failure_notification.py +++ b/changedetectionio/tests/test_filter_failure_notification.py @@ -12,7 +12,7 @@ def set_response_with_filter():

    Which is across multiple lines


    So let's see what happens.
    -
    Some text thats the same
    +
    Some text thats the same
    """ @@ -66,6 +66,7 @@ def run_filter_test(client, content_filter): "Snapshot: {{current_snapshot}}\n" "Diff: {{diff}}\n" "Diff Full: {{diff_full}}\n" + "Diff as Patch: {{diff_patch}}\n" ":-)", "notification_format": "Text"} diff --git a/changedetectionio/tests/test_group.py b/changedetectionio/tests/test_group.py index 2bac9710..ed38cb98 100644 --- a/changedetectionio/tests/test_group.py +++ b/changedetectionio/tests/test_group.py @@ -15,7 +15,7 @@ def set_original_response(): Some initial text

    Should be only this


    -

    And never this

    +

    And never this

    """ @@ -30,7 +30,7 @@ def set_modified_response(): Some initial text

    Should be REALLY only this


    -

    And never this

    +

    And never this

    """ @@ -189,6 +189,7 @@ def test_group_tag_notification(client, live_server): "Diff Added: {{diff_added}}\n" "Diff Removed: {{diff_removed}}\n" "Diff Full: {{diff_full}}\n" + "Diff as Patch: {{diff_patch}}\n" ":-)", "notification_screenshot": True, "notification_format": "Text", @@ -319,4 +320,4 @@ def test_clone_tag_on_quickwatchform_add(client, live_server): assert b'Deleted' in res.data res = client.get(url_for("tags.delete_all"), follow_redirects=True) - assert b'All tags deleted' in res.data \ No newline at end of file + assert b'All tags deleted' in res.data diff --git a/changedetectionio/tests/test_notification.py b/changedetectionio/tests/test_notification.py index 5f7b0582..7d0e5ff2 100644 --- a/changedetectionio/tests/test_notification.py +++ b/changedetectionio/tests/test_notification.py @@ -98,6 +98,7 @@ def test_check_notification(client, live_server): "Diff Added: {{diff_added}}\n" "Diff Removed: {{diff_removed}}\n" "Diff Full: {{diff_full}}\n" + "Diff as Patch: {{diff_patch}}\n" ":-)", "notification_screenshot": True, "notification_format": "Text"} diff --git a/changedetectionio/tests/unit/test_notification_diff.py b/changedetectionio/tests/unit/test_notification_diff.py index 6f323146..c7befc20 100755 --- a/changedetectionio/tests/unit/test_notification_diff.py +++ b/changedetectionio/tests/unit/test_notification_diff.py @@ -36,7 +36,7 @@ class TestDiffBuilder(unittest.TestCase): output = output.split("\n") self.assertIn('(removed) for having learned computerese,', output) self.assertIn('(removed) I continue to examine bits, bytes and words', output) - + #diff_removed with open(base_dir + "/test-content/before.txt", 'r') as f: previous_version_file_contents = f.read() @@ -49,7 +49,7 @@ class TestDiffBuilder(unittest.TestCase): self.assertIn('(into) xok', output) self.assertIn('(into) next-x-ok', output) self.assertNotIn('(added) and something new', output) - + #diff_removed with open(base_dir + "/test-content/after-2.txt", 'r') as f: newest_version_file_contents = f.read() @@ -57,9 +57,25 @@ class TestDiffBuilder(unittest.TestCase): output = output.split("\n") self.assertIn('(removed) for having learned computerese,', output) self.assertIn('(removed) I continue to examine bits, bytes and words', output) - + + def test_expected_diff_patch_output(self): + base_dir = os.path.dirname(__file__) + with open(base_dir + "/test-content/before.txt", 'r') as f: + before = f.read() + with open(base_dir + "/test-content/after.txt", 'r') as f: + after = f.read() + + output = diff.render_diff(previous_version_file_contents=before, + newest_version_file_contents=after, + patch_format=True) + output = output.split("\n") + + self.assertIn('-ok', output) + self.assertIn('+xok', output) + self.assertIn('+next-x-ok', output) + self.assertIn('+and something new', output) # @todo test blocks of changed, blocks of added, blocks of removed if __name__ == '__main__': - unittest.main() \ No newline at end of file + unittest.main() diff --git a/changedetectionio/update_worker.py b/changedetectionio/update_worker.py index 61b42394..63a0aab4 100644 --- a/changedetectionio/update_worker.py +++ b/changedetectionio/update_worker.py @@ -58,6 +58,7 @@ class update_worker(threading.Thread): 'diff': diff.render_diff(watch.get_history_snapshot(dates[-2]), watch.get_history_snapshot(dates[-1]), line_feed_sep=line_feed_sep), 'diff_added': diff.render_diff(watch.get_history_snapshot(dates[-2]), watch.get_history_snapshot(dates[-1]), include_removed=False, line_feed_sep=line_feed_sep), 'diff_full': diff.render_diff(watch.get_history_snapshot(dates[-2]), watch.get_history_snapshot(dates[-1]), include_equal=True, line_feed_sep=line_feed_sep), + 'diff_patch': diff.render_diff(watch.get_history_snapshot(dates[-2]), watch.get_history_snapshot(dates[-1]), line_feed_sep=line_feed_sep, patch_format=True), 'diff_removed': diff.render_diff(watch.get_history_snapshot(dates[-2]), watch.get_history_snapshot(dates[-1]), include_added=False, line_feed_sep=line_feed_sep), 'screenshot': watch.get_screenshot() if watch.get('notification_screenshot') else None, 'triggered_text': triggered_text,