diff --git a/changedetectionio/processors/text_json_diff/processor.py b/changedetectionio/processors/text_json_diff/processor.py index 45b7f520..32b646a9 100644 --- a/changedetectionio/processors/text_json_diff/processor.py +++ b/changedetectionio/processors/text_json_diff/processor.py @@ -397,6 +397,11 @@ class perform_site_check(difference_detection_processor): # RSS preprocessing if stream_content_type.is_rss: content = content_processor.preprocess_rss(content) + if self.datastore.data["settings"]["application"].get("rss_reader_mode"): + # Now just becomes regular HTML that can have xpath/CSS applied (first of the set etc) + stream_content_type.is_rss = False + stream_content_type.is_html = True + self.fetcher.content = content # PDF preprocessing if watch.is_pdf or stream_content_type.is_pdf: diff --git a/changedetectionio/rss_tools.py b/changedetectionio/rss_tools.py index 35f4c4f4..01561ae4 100644 --- a/changedetectionio/rss_tools.py +++ b/changedetectionio/rss_tools.py @@ -109,8 +109,22 @@ def format_rss_items(rss_content: str, render_anchor_tag_content=False) -> str: if item_parts: formatted_items.append('\n'.join(item_parts)) - # Join all items with


- return ''+'


'.join(formatted_items) + # Wrap each item in a div with classes (first, last, item-N) + items_html = [] + total_items = len(formatted_items) + for idx, item in enumerate(formatted_items): + classes = ['rss-item'] + if idx == 0: + classes.append('first') + if idx == total_items - 1: + classes.append('last') + classes.append(f'item-{idx + 1}') + + class_str = ' '.join(classes) + items_html.append(f'
{item}
') + + # Join items with two
tags + return f'{"\n

".join(items_html)}' except Exception as e: logger.warning(f"Error formatting RSS items: {str(e)}") diff --git a/changedetectionio/tests/test_rss_reader_mode.py b/changedetectionio/tests/test_rss_reader_mode.py index bcc1e493..df561b90 100644 --- a/changedetectionio/tests/test_rss_reader_mode.py +++ b/changedetectionio/tests/test_rss_reader_mode.py @@ -25,6 +25,8 @@ def set_original_cdata_xml(): Thu, 07 Aug 2025 00:00:00 GMT

Wet noodles escape

they also found themselves outside

+ + TS-2025-004 https://wetscale.com/security-bulletins/#ts-2025-004 @@ -69,3 +71,28 @@ def test_rss_reader_mode(client, live_server, measure_memory_usage): assert 'PubDate: Thu, 07 Aug 2025 00:00:00 GMT' in snapshot_contents delete_all_watches(client) +def test_rss_reader_mode_with_css_filters(client, live_server, measure_memory_usage): + set_original_cdata_xml() + + # Rarely do endpoints give the right header, usually just text/xml, so we check also for ' not in snapshot_contents + assert '<' not in snapshot_contents + assert 'The days of Terminator and The Matrix' in snapshot_contents + delete_all_watches(client) +