Fixed unreachable streams reporting stale online status indefinitely.
This commit is contained in:
@@ -11,6 +11,7 @@ from mautrix.types import TextMessageEventContent, MessageType
|
|||||||
|
|
||||||
from .owncast_client import OwncastClient
|
from .owncast_client import OwncastClient
|
||||||
from .database import StreamRepository, SubscriptionRepository
|
from .database import StreamRepository, SubscriptionRepository
|
||||||
|
from .models import StreamStatus
|
||||||
from .utils import domainify, sanitize_for_markdown
|
from .utils import domainify, sanitize_for_markdown
|
||||||
|
|
||||||
|
|
||||||
@@ -209,18 +210,21 @@ class CommandHandler:
|
|||||||
body_text += f"- **{safe_stream_name}** \n"
|
body_text += f"- **{safe_stream_name}** \n"
|
||||||
|
|
||||||
# Add title if stream is online (as a sub-bullet)
|
# Add title if stream is online (as a sub-bullet)
|
||||||
if stream_state.online and stream_state.title:
|
if stream_state.status == StreamStatus.ONLINE and stream_state.title:
|
||||||
safe_title = sanitize_for_markdown(stream_state.title)
|
safe_title = sanitize_for_markdown(stream_state.title)
|
||||||
body_text += f" - Title: {safe_title} \n"
|
body_text += f" - Title: {safe_title} \n"
|
||||||
|
|
||||||
# Determine status and duration (as a sub-bullet)
|
# Determine status and duration (as a sub-bullet)
|
||||||
if stream_state.online:
|
if stream_state.status == StreamStatus.ONLINE:
|
||||||
# Stream is online - use last_connect_time
|
# Stream is online - use last_connect_time
|
||||||
if stream_state.last_connect_time:
|
if stream_state.last_connect_time:
|
||||||
duration = self._format_duration(stream_state.last_connect_time)
|
duration = self._format_duration(stream_state.last_connect_time)
|
||||||
body_text += f" - Status: Online for {duration} \n"
|
body_text += f" - Status: Online for {duration} \n"
|
||||||
else:
|
else:
|
||||||
body_text += f" - Status: Online \n"
|
body_text += f" - Status: Online \n"
|
||||||
|
elif stream_state.status == StreamStatus.UNKNOWN:
|
||||||
|
# Stream status is unknown - instance unreachable
|
||||||
|
body_text += f" - Status: Unknown (instance unreachable) \n"
|
||||||
else:
|
else:
|
||||||
# Stream is offline - use last_disconnect_time
|
# Stream is offline - use last_disconnect_time
|
||||||
if stream_state.last_disconnect_time:
|
if stream_state.last_disconnect_time:
|
||||||
@@ -255,11 +259,11 @@ class CommandHandler:
|
|||||||
await evt.reply("This room is not subscribed to any Owncast instances.\n\nTo subscribe to an Owncast instance, use `!subscribe <domain>`", markdown=True)
|
await evt.reply("This room is not subscribed to any Owncast instances.\n\nTo subscribe to an Owncast instance, use `!subscribe <domain>`", markdown=True)
|
||||||
return
|
return
|
||||||
|
|
||||||
# Filter for only live streams
|
# Filter for only live streams (exclude unknown status)
|
||||||
live_streams = []
|
live_streams = []
|
||||||
for domain in subscribed_domains:
|
for domain in subscribed_domains:
|
||||||
stream_state = await self.stream_repo.get_by_domain(domain)
|
stream_state = await self.stream_repo.get_by_domain(domain)
|
||||||
if stream_state and stream_state.online:
|
if stream_state and stream_state.status == StreamStatus.ONLINE:
|
||||||
live_streams.append((domain, stream_state))
|
live_streams.append((domain, stream_state))
|
||||||
|
|
||||||
# Check if there are no live streams
|
# Check if there are no live streams
|
||||||
|
|||||||
+19
-3
@@ -5,9 +5,18 @@
|
|||||||
# Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
|
# Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
|
||||||
|
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
|
from enum import Enum
|
||||||
from typing import Optional, List
|
from typing import Optional, List
|
||||||
|
|
||||||
|
|
||||||
|
class StreamStatus(Enum):
|
||||||
|
"""Represents the status of a stream."""
|
||||||
|
|
||||||
|
ONLINE = "online"
|
||||||
|
OFFLINE = "offline"
|
||||||
|
UNKNOWN = "unknown"
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class StreamState:
|
class StreamState:
|
||||||
"""Represents the state of an Owncast stream."""
|
"""Represents the state of an Owncast stream."""
|
||||||
@@ -20,9 +29,16 @@ class StreamState:
|
|||||||
failure_counter: int = 0
|
failure_counter: int = 0
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def online(self) -> bool:
|
def status(self) -> StreamStatus:
|
||||||
"""Returns True if the stream is currently online."""
|
"""Returns the stream status considering failure_counter."""
|
||||||
return self.last_connect_time is not None
|
from .utils import UNKNOWN_STATUS_THRESHOLD
|
||||||
|
|
||||||
|
if self.failure_counter > UNKNOWN_STATUS_THRESHOLD:
|
||||||
|
return StreamStatus.UNKNOWN
|
||||||
|
elif self.last_connect_time is not None:
|
||||||
|
return StreamStatus.ONLINE
|
||||||
|
else:
|
||||||
|
return StreamStatus.OFFLINE
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def from_api_response(cls, response: dict, domain: str) -> "StreamState":
|
def from_api_response(cls, response: dict, domain: str) -> "StreamState":
|
||||||
|
|||||||
@@ -33,6 +33,9 @@ TEMPORARY_OFFLINE_NOTIFICATION_COOLDOWN = 7 * 60 # 7 minutes in seconds
|
|||||||
CLEANUP_WARNING_THRESHOLD = 83 * 24 * 60 # 119,520 cycles = 83 days
|
CLEANUP_WARNING_THRESHOLD = 83 * 24 * 60 # 119,520 cycles = 83 days
|
||||||
CLEANUP_DELETE_THRESHOLD = 90 * 24 * 60 # 129,600 cycles = 90 days
|
CLEANUP_DELETE_THRESHOLD = 90 * 24 * 60 # 129,600 cycles = 90 days
|
||||||
|
|
||||||
|
# Failure counter threshold for treating stream status as "unknown"
|
||||||
|
UNKNOWN_STATUS_THRESHOLD = 15
|
||||||
|
|
||||||
# Maximum field lengths based on Owncast's configuration
|
# Maximum field lengths based on Owncast's configuration
|
||||||
# Source: https://github.com/owncast/owncast/blob/master/web/utils/config-constants.tsx
|
# Source: https://github.com/owncast/owncast/blob/master/web/utils/config-constants.tsx
|
||||||
MAX_INSTANCE_TITLE_LENGTH = 255 # Server Name (line 81)
|
MAX_INSTANCE_TITLE_LENGTH = 255 # Server Name (line 81)
|
||||||
|
|||||||
Reference in New Issue
Block a user