63 lines
2.2 KiB
Python
63 lines
2.2 KiB
Python
from __future__ import annotations
|
|
|
|
import asyncio
|
|
import contextlib
|
|
import logging
|
|
|
|
from zyrarbot.ui.api.connection_manager import ConnectionManager
|
|
from zyrarbot.ui.api.status_service import StatusService
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
BROADCAST_INTERVAL_SECONDS = 1.0
|
|
|
|
|
|
class StatusBroadcaster:
|
|
"""Rozgłasza stan bota po WebSocketach - zarówno cyklicznie, jak i na żądanie."""
|
|
|
|
def __init__(self, status: StatusService, connections: ConnectionManager):
|
|
self._status = status
|
|
self._connections = connections
|
|
self._task: asyncio.Task[None] | None = None
|
|
|
|
async def broadcast(self) -> None:
|
|
if not self._connections.has_listeners:
|
|
return
|
|
try:
|
|
await self._connections.broadcast(self._snapshot_for_connection)
|
|
except Exception as error: # noqa: BLE001 - rozgłaszanie nie może ubić pętli
|
|
logger.error("Błąd rozgłaszania stanu: %s", error)
|
|
|
|
def _snapshot_for_connection(self, connection, guild_id: int | None) -> dict:
|
|
payload = self._status.snapshot(guild_id)
|
|
user = connection.app.state.auth.user_for_token(
|
|
connection.cookies.get("zyrarbot_session")
|
|
)
|
|
allowed = connection.app.state.auth.guild_ids(
|
|
user, [guild.id for guild in connection.app.state.guilds.guilds()]
|
|
) if user else []
|
|
payload["guilds"] = [item for item in payload["guilds"] if int(item["guild_id"]) in allowed]
|
|
return payload
|
|
|
|
def start(self) -> None:
|
|
if self._task is None or self._task.done():
|
|
self._task = asyncio.create_task(self._loop())
|
|
|
|
async def stop(self) -> None:
|
|
if self._task is None:
|
|
return
|
|
self._task.cancel()
|
|
with contextlib.suppress(asyncio.CancelledError):
|
|
await self._task
|
|
self._task = None
|
|
|
|
async def _loop(self) -> None:
|
|
while True:
|
|
try:
|
|
await asyncio.sleep(BROADCAST_INTERVAL_SECONDS)
|
|
await self.broadcast()
|
|
except asyncio.CancelledError:
|
|
break
|
|
except Exception as error: # noqa: BLE001
|
|
logger.error("Błąd pętli rozgłaszania stanu: %s", error)
|