Files
TheOnlyMace 4f57cccea5
Some checks failed
CI / Bot (Python) (push) Successful in 12s
CI / Dashboard (Next.js) (push) Failing after 9s
Add Discord sharding support and related configurations
Enhance the bot's architecture by introducing sharding capabilities, allowing for better scalability and performance. Update environment files to include sharding options, and modify the bot's core logic to handle shard connections and latencies. Implement shard-specific logging and API synchronization, ensuring that only the primary shard performs certain tasks. Update API schemas and routes to reflect shard information, improving the overall status reporting and monitoring of the bot's performance across multiple shards.
2026-07-21 23:09:35 +02:00

138 lines
5.4 KiB
Python

# ╔══════════════════════════════════════════════════════════════════╗
# ║ ║
# ║ +-+-+-+-+-+-+-+-+ ║
# ║ |H|e|x|a|H|o|s|t| ║
# ║ +-+-+-+-+-+-+-+-+ ║
# ║ ║
# ║ © 2026 HexaHost — All Rights Reserved ║
# ║ ║
# ║ discord ── https://discord.gg/hexahost ║
# ║ github ── https://github.com/theoneandonlymace ║
# ║ ║
# ╚══════════════════════════════════════════════════════════════════╝
from utils.db_paths import db_path
from fastapi import APIRouter, Depends, HTTPException
from api.dependencies import get_bot
from api.schemas import AdminStats, AdminNodeStatus, AdminConfig, AdminConfigUpdate
from typing import TYPE_CHECKING, List
import os
import aiosqlite
if TYPE_CHECKING:
from core.axiom import Axiom
router = APIRouter()
CONFIG_DB = db_path("admin_config.db")
async def init_db():
async with aiosqlite.connect(CONFIG_DB) as db:
await db.execute("CREATE TABLE IF NOT EXISTS config (key TEXT PRIMARY KEY, value TEXT)")
# Default values
await db.execute("INSERT OR IGNORE INTO config (key, value) VALUES ('maintenance_mode', 'false')")
await db.execute("INSERT OR IGNORE INTO config (key, value) VALUES ('global_notification', '')")
await db.commit()
import psutil
import time
@router.get("/stats", response_model=AdminStats)
async def get_admin_stats(bot: "Axiom" = Depends(get_bot)):
# Calculate DB size and shard info
total_size: float = 0.0
db_count = 0
db_dir = "db"
if os.path.exists(db_dir):
for f in os.listdir(db_dir):
if f.endswith(".db"):
total_size += float(os.path.getsize(os.path.join(db_dir, f)))
db_count += 1
mb_size = total_size / (1024 * 1024)
db_size_str = f"{mb_size:.2f} MB"
if mb_size > 1024:
db_size_str = f"{(mb_size / 1024):.2f} GB"
# System Metrics
process = psutil.Process(os.getpid())
# Use a non-blocking interval check or global state for CPU
cpu_usage = psutil.cpu_percent()
ram_raw = process.memory_info().rss
ram_mb = ram_raw / (1024 * 1024)
total_commands = len(bot.commands)
loaded_cogs = len(bot.cogs or {})
# Node Healths
nodes = [
AdminNodeStatus(
name="Primary API Cluster",
status="Healthy",
load=f"CPU: {cpu_usage}% | RAM: {ram_mb:.1f}MB",
icon="Globe"
),
AdminNodeStatus(
name="Database Shards",
status="Healthy" if db_count > 0 else "Warning",
load=f"{db_count} SQLite DBs | {db_size_str}",
icon="Database"
),
AdminNodeStatus(
name="Bot Microservices",
status="Healthy" if bot.is_ready() else "Booting",
load=f"{loaded_cogs} Modules",
icon="Cpu"
),
AdminNodeStatus(
name="Auth Sockets",
status="Healthy",
load=(
f"Shards: {bot.shard_count or 1} | "
f"Latency: {round(bot.latency * 1000)}ms"
+ (
" | "
+ ", ".join(f"s{sid}:{round(lat * 1000)}ms" for sid, lat in bot.latencies)
if bot.latencies and len(bot.latencies) > 1
else ""
)
),
icon="Lock"
)
]
total_members = sum(g.member_count or 0 for g in bot.guilds)
return AdminStats(
total_users=str(total_members),
active_servers=str(len(bot.guilds)),
api_latency=f"{round(bot.latency * 1000, 2)}ms",
db_size=db_size_str,
nodes=nodes
)
@router.get("/config", response_model=AdminConfig)
async def get_admin_config():
await init_db()
async with aiosqlite.connect(CONFIG_DB) as db:
async with db.execute("SELECT value FROM config WHERE key = 'maintenance_mode'") as cursor:
mm = await cursor.fetchone()
async with db.execute("SELECT value FROM config WHERE key = 'global_notification'") as cursor:
gn = await cursor.fetchone()
return AdminConfig(
maintenance_mode=mm[0].lower() == 'true' if mm else False,
global_notification=gn[0] if gn else None
)
@router.patch("/config")
async def patch_admin_config(data: AdminConfigUpdate):
await init_db()
async with aiosqlite.connect(CONFIG_DB) as db:
if data.maintenance_mode is not None:
await db.execute("UPDATE config SET value = ? WHERE key = 'maintenance_mode'", (str(data.maintenance_mode).lower(),))
if data.global_notification is not None:
await db.execute("UPDATE config SET value = ? WHERE key = 'global_notification'", (data.global_notification,))
await db.commit()
return {"status": "success"}