From ab15f3ac8ce1df608e9f7ea36808770da1a258ea Mon Sep 17 00:00:00 2001 From: esefxdz Date: Sun, 12 Jul 2026 18:46:17 +0300 Subject: [PATCH] website connected --- firebase_website/__init__.py | 29 +++++++++++ firebase_website/config.py | 18 +++++++ firebase_website/sysinfo_sync.py | 85 ++++++++++++++++++++++++++++++++ main.py | 1 + 4 files changed, 133 insertions(+) create mode 100644 firebase_website/__init__.py create mode 100644 firebase_website/config.py create mode 100644 firebase_website/sysinfo_sync.py diff --git a/firebase_website/__init__.py b/firebase_website/__init__.py new file mode 100644 index 0000000..e7dae7c --- /dev/null +++ b/firebase_website/__init__.py @@ -0,0 +1,29 @@ +"""firebase_website — Bot → Firestore sync for the esefos.netlify.app dashboard. + +Add integrations here as they grow: + sysinfo_sync — CPU, RAM, disk, uptime pushed every 10 s + (future) — gacha stats, now-playing, radio listeners, … + +Usage from main.py: + await bot.load_extension("firebase_website") +""" +###################################################################### +from discord.ext import commands + +from .sysinfo_sync import SysInfoSync + +_sync: SysInfoSync | None = None + + +async def setup(bot: commands.Bot) -> None: + """Called by bot.load_extension(). Starts the sysinfo sync loop.""" + global _sync + _sync = SysInfoSync() + _sync.start() + + +async def teardown(bot: commands.Bot) -> None: + """Called on bot unload / shutdown. Stops all sync tasks.""" + global _sync + if _sync is not None: + _sync.stop() diff --git a/firebase_website/config.py b/firebase_website/config.py new file mode 100644 index 0000000..ec43244 --- /dev/null +++ b/firebase_website/config.py @@ -0,0 +1,18 @@ +"""Firebase project config — shared by all website integrations.""" +###################################################################### + +# Your Firebase project (same one the website uses in comments.js) +PROJECT_ID = "esef-514bf" +API_KEY = "AIzaSyDuSjEGEKx5FnWYnQq8f_owbpYRBRrl5x0" + +# Firestore REST API base URL +FIRESTORE_BASE = ( + f"https://firestore.googleapis.com/v1/projects/{PROJECT_ID}" + f"/databases/(default)/documents" +) + +# Document paths +DOC_SYSINFO = f"{FIRESTORE_BASE}/sysinfo/server" + +# How often system stats are pushed (seconds) +SYSINFO_INTERVAL = 10 diff --git a/firebase_website/sysinfo_sync.py b/firebase_website/sysinfo_sync.py new file mode 100644 index 0000000..bee230b --- /dev/null +++ b/firebase_website/sysinfo_sync.py @@ -0,0 +1,85 @@ +"""Push system stats (CPU, RAM, disk, uptime) to Firestore on a loop.""" +###################################################################### +import asyncio +import logging +import time + +import aiohttp +import psutil + +from .config import DOC_SYSINFO, SYSINFO_INTERVAL + +log = logging.getLogger(__name__) + + +class SysInfoSync: + """Background task that collects system stats and pushes them to Firestore.""" + + def __init__(self) -> None: + self._task: asyncio.Task | None = None + + # ── public API ────────────────────────────────────────────────────────── + + def start(self) -> None: + """Launch the background sync loop.""" + if self._task is not None: + return + self._task = asyncio.create_task(self._run()) + log.info("SysInfo → Firestore sync started (every %ds)", SYSINFO_INTERVAL) + + def stop(self) -> None: + """Cancel the background sync loop.""" + if self._task is None: + return + self._task.cancel() + self._task = None + log.info("SysInfo → Firestore sync stopped") + + # ── internals ─────────────────────────────────────────────────────────── + + async def _run(self) -> None: + """Main loop — collect stats, push, sleep, repeat.""" + async with aiohttp.ClientSession() as session: + while True: + try: + await self._push(session) + except asyncio.CancelledError: + return + except Exception: + log.debug("SysInfo Firestore push failed", exc_info=True) + await asyncio.sleep(SYSINFO_INTERVAL) + + async def _push(self, session: aiohttp.ClientSession) -> None: + """Collect current stats and PATCH the Firestore document.""" + cpu = psutil.cpu_percent(interval=1) + mem = psutil.virtual_memory() + disk = psutil.disk_usage("/") + uptime_seconds = int(time.time() - psutil.boot_time()) + + # uptime → "3d 12h 5m" or "5h 23m" + days, r = divmod(uptime_seconds, 86400) + hours, r = divmod(r, 3600) + minutes, _ = divmod(r, 60) + if days > 0: + uptime_str = f"{days}d {hours}h {minutes}m" + else: + uptime_str = f"{hours}h {minutes}m" + + payload = { + "fields": { + "online": {"booleanValue": True}, + "cpu": {"doubleValue": round(cpu, 1)}, + "ram": {"doubleValue": round(mem.percent, 1)}, + "ramUsed": {"stringValue": f"{mem.used // (1024 ** 2)}MB"}, + "ramTotal": {"stringValue": f"{mem.total // (1024 ** 2)}MB"}, + "disk": {"doubleValue": round(disk.percent, 1)}, + "diskUsed": {"stringValue": f"{disk.used // (1024 ** 3)}GB"}, + "diskTotal": {"stringValue": f"{disk.total // (1024 ** 3)}GB"}, + "uptime": {"stringValue": uptime_str}, + } + } + + async with session.patch(DOC_SYSINFO, json=payload) as resp: + if resp.status not in (200, 201): + body = await resp.text() + log.debug("Firestore PATCH %d: %s", resp.status, body[:200]) diff --git a/main.py b/main.py index dd66f6d..8020a13 100644 --- a/main.py +++ b/main.py @@ -70,6 +70,7 @@ async def main(): await bot.load_extension("rio.ssh_connection_rio") await bot.load_extension('blue_archive.gacha') await bot.load_extension('blue_archive.inventory') + await bot.load_extension('firebase_website') try: await bot.start(os.getenv('DISCORD_TOKEN'))