Live dashboard with real-time WebSocket updates, analytics page with time-filtered stats, ClickHouse storage, and Caddy reverse proxy.
62 lines
1.6 KiB
Python
62 lines
1.6 KiB
Python
"""
|
|
Entry point — starts all async tasks concurrently:
|
|
1. StreamKar WebSocket client (anonymous, captures user bets)
|
|
2. Game state HTTP poller (authenticated, captures full game state)
|
|
3. aiohttp web server (serves dashboard, pushes events to browsers)
|
|
"""
|
|
|
|
import asyncio
|
|
import logging
|
|
import signal
|
|
|
|
from .server import WebServer
|
|
from .streamkar_ws import StreamKarWSClient
|
|
from .game_poller import GamePoller
|
|
|
|
logging.basicConfig(
|
|
level=logging.INFO,
|
|
format="%(asctime)s [%(name)s] %(levelname)s: %(message)s",
|
|
datefmt="%H:%M:%S",
|
|
)
|
|
log = logging.getLogger(__name__)
|
|
|
|
|
|
async def main():
|
|
server = WebServer()
|
|
ws_client = StreamKarWSClient(broadcast_fn=server.broadcast)
|
|
poller = GamePoller(broadcast_fn=server.broadcast, push_refresh_fn=server.push_refresh)
|
|
|
|
loop = asyncio.get_event_loop()
|
|
|
|
def shutdown():
|
|
log.info("Shutting down...")
|
|
ws_client.stop()
|
|
poller.stop()
|
|
for task in asyncio.all_tasks(loop):
|
|
task.cancel()
|
|
|
|
for sig in (signal.SIGINT, signal.SIGTERM):
|
|
loop.add_signal_handler(sig, shutdown)
|
|
|
|
log.info("Starting Teen Patti Live Monitor")
|
|
log.info("Dashboard: http://localhost:8765")
|
|
|
|
tasks = [
|
|
asyncio.create_task(server.run(), name="web_server"),
|
|
asyncio.create_task(poller.run(), name="game_poller"),
|
|
asyncio.create_task(ws_client.run(), name="ws_client"),
|
|
]
|
|
|
|
try:
|
|
await asyncio.gather(*tasks)
|
|
except asyncio.CancelledError:
|
|
pass
|
|
except Exception as e:
|
|
log.error("Fatal: %s", e)
|
|
finally:
|
|
log.info("Stopped.")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
asyncio.run(main())
|