From 8c772ab19e2e61357f8f1a3b5927df9c090ce85f Mon Sep 17 00:00:00 2001 From: Logan Fick Date: Thu, 8 Jan 2026 18:50:55 -0500 Subject: [PATCH] Fixed markdown escape characters appearing literally in plain text notifications. --- owncastsentry/notification_service.py | 8 ++++---- owncastsentry/utils.py | 22 ++++++++++++++++++++++ 2 files changed, 26 insertions(+), 4 deletions(-) diff --git a/owncastsentry/notification_service.py b/owncastsentry/notification_service.py index 24c10aa..ec017cb 100644 --- a/owncastsentry/notification_service.py +++ b/owncastsentry/notification_service.py @@ -11,7 +11,7 @@ from typing import List from mautrix.types import TextMessageEventContent, MessageType from .database import SubscriptionRepository -from .utils import SECONDS_BETWEEN_NOTIFICATIONS, sanitize_for_markdown +from .utils import SECONDS_BETWEEN_NOTIFICATIONS, sanitize_for_plain_text class NotificationService: @@ -130,7 +130,7 @@ class NotificationService: """ # Use name if available, fallback to domain stream_name = name if name else domain - safe_stream_name = sanitize_for_markdown(stream_name) + safe_stream_name = sanitize_for_plain_text(stream_name) # Choose message based on notification type if title_change: @@ -140,7 +140,7 @@ class NotificationService: # Add title if present if title != "": - safe_title = sanitize_for_markdown(title) + safe_title = sanitize_for_plain_text(title) body_text += "\nStream Title: " + safe_title # Add stream URL @@ -150,7 +150,7 @@ class NotificationService: if tags and len(tags) > 0: safe_tags = [] for tag in tags: - safe_tag = sanitize_for_markdown(tag) + safe_tag = sanitize_for_plain_text(tag) if safe_tag and not safe_tag.startswith('.'): safe_tags.append(safe_tag) diff --git a/owncastsentry/utils.py b/owncastsentry/utils.py index a94acd8..dd48f66 100644 --- a/owncastsentry/utils.py +++ b/owncastsentry/utils.py @@ -157,6 +157,28 @@ def escape_markdown(text: str) -> str: return escaped_text +def sanitize_for_plain_text(text: str) -> str: + """ + Sanitize text for plain text rendering. + + Removes newlines and normalizes whitespace without escaping special characters. + Use this for plain text notifications where escaping would show literal backslashes. + + :param text: The text to sanitize + :return: Sanitized text + """ + if not text: + return text + + # Remove newlines and carriage returns to prevent multi-line injection + sanitized = text.replace('\n', ' ').replace('\r', ' ') + + # Collapse multiple spaces into single space + sanitized = ' '.join(sanitized.split()) + + return sanitized + + def sanitize_for_markdown(text: str) -> str: """ Sanitize text for safe Markdown rendering.