Simplified title-change notification handling.
This commit is contained in:
@@ -134,12 +134,11 @@ def _classify_notification(
|
||||
observation: StreamStateObservation,
|
||||
*,
|
||||
offline_duration_seconds: int | None = None,
|
||||
went_offline_after_last_notification: bool = False,
|
||||
) -> _NotificationKind:
|
||||
"""Classify the live/title notification policy for a transition.
|
||||
|
||||
The caller supplies timing context because it comes from the monitor's
|
||||
monotonic offline cache and notification-service cache, not the transition.
|
||||
The caller supplies offline duration because it comes from the monitor's
|
||||
monotonic offline cache, not the transition.
|
||||
"""
|
||||
match transition.kind:
|
||||
case _StreamTransitionKind.WENT_LIVE:
|
||||
@@ -153,8 +152,6 @@ def _classify_notification(
|
||||
return _NotificationKind.LIVE
|
||||
|
||||
case _StreamTransitionKind.TITLE_CHANGED:
|
||||
if went_offline_after_last_notification:
|
||||
return _NotificationKind.LIVE
|
||||
return _NotificationKind.TITLE_CHANGE
|
||||
|
||||
case _:
|
||||
@@ -314,7 +311,6 @@ class StreamMonitor:
|
||||
# Notification policy may need runtime timing context in addition to
|
||||
# the stored state and latest observation.
|
||||
offline_duration_seconds: int | None = None
|
||||
went_offline_after_last_notification = False
|
||||
|
||||
match transition.kind:
|
||||
case _StreamTransitionKind.FIRST_OBSERVATION:
|
||||
@@ -343,11 +339,6 @@ class StreamMonitor:
|
||||
)
|
||||
case _StreamTransitionKind.TITLE_CHANGED:
|
||||
self.log.info("[%s] Stream title was changed!", domain)
|
||||
# If we saw an offline event after the last notification, send
|
||||
# a go-live notice instead of only a title-change notice.
|
||||
went_offline_after_last_notification = self.offline_timer_cache[
|
||||
domain
|
||||
] > self.notification_service.get_last_notification_time(domain)
|
||||
case _StreamTransitionKind.WENT_OFFLINE:
|
||||
self.offline_timer_cache[domain] = time.monotonic()
|
||||
self.log.info("[%s] Stream is now offline.", domain)
|
||||
@@ -359,7 +350,6 @@ class StreamMonitor:
|
||||
old_state,
|
||||
observation,
|
||||
offline_duration_seconds=offline_duration_seconds,
|
||||
went_offline_after_last_notification=went_offline_after_last_notification,
|
||||
)
|
||||
|
||||
stream_config: StreamConfigObservation | None = None
|
||||
|
||||
@@ -457,32 +457,6 @@ class TestClassifyNotification:
|
||||
|
||||
assert notification_kind is _NotificationKind.TITLE_CHANGE
|
||||
|
||||
def test_went_offline_after_last_notification_notifies_live(self) -> None:
|
||||
"""Notify live when stream went offline after the last notification."""
|
||||
old_state = StreamState(
|
||||
domain="example.com",
|
||||
title="Old",
|
||||
online=True,
|
||||
status_since="2026-01-01T10:00:00+00:00",
|
||||
)
|
||||
observation = _stream_observation(
|
||||
domain="example.com",
|
||||
title="New",
|
||||
online=True,
|
||||
observed_at="2026-01-01T12:00:00+00:00",
|
||||
)
|
||||
transition = _classify_transition(old_state, observation)
|
||||
|
||||
notification_kind = _classify_notification(
|
||||
transition,
|
||||
old_state,
|
||||
observation,
|
||||
went_offline_after_last_notification=True,
|
||||
)
|
||||
|
||||
assert notification_kind is _NotificationKind.LIVE
|
||||
|
||||
|
||||
class TestUpdateAllStreams:
|
||||
"""Parallel stream update orchestration."""
|
||||
|
||||
@@ -959,12 +933,12 @@ class TestUpdateStreamTitleChange:
|
||||
)
|
||||
assert owncast.config_call_count == 1
|
||||
|
||||
async def test_sends_go_live_when_last_notification_before_offline(
|
||||
async def test_sends_title_change_after_offline_gap(
|
||||
self,
|
||||
stream_repo: StreamRepository,
|
||||
subscription_repo: SubscriptionRepository,
|
||||
) -> None:
|
||||
"""Send go-live instead of title-change after an offline gap."""
|
||||
"""Send title-change when an already-online stream changes title."""
|
||||
owncast = _StubOwncastClient(
|
||||
stream_state=_stream_observation(
|
||||
domain="title.com",
|
||||
@@ -991,8 +965,8 @@ class TestUpdateStreamTitleChange:
|
||||
status_since="2026-01-01T12:00:00+00:00",
|
||||
)
|
||||
|
||||
# Offline timer is MORE recent than last notification,
|
||||
# and both are old enough to pass rate limiting
|
||||
# Offline timer is more recent than the last notification, but title
|
||||
# changes remain title changes once the stream is already online.
|
||||
now = time.monotonic()
|
||||
monitor.offline_timer_cache["title.com"] = (
|
||||
now - _SECONDS_BETWEEN_NOTIFICATIONS - 100
|
||||
@@ -1005,7 +979,7 @@ class TestUpdateStreamTitleChange:
|
||||
assert result is True
|
||||
assert len(client.sent_messages) == 1
|
||||
assert client.sent_messages[0].content.body == (
|
||||
"🎥 Title Stream is now live!\n"
|
||||
"📝 Title Stream has changed its stream title!\n"
|
||||
"Stream Title: Updated Title\n"
|
||||
"\n"
|
||||
"To tune in, visit: https://title.com/"
|
||||
|
||||
Reference in New Issue
Block a user