Update project configuration files, and API routes accordingly. Add SQLite runtime file ignores to .gitignore for better file management.
Some checks failed
CI / Bot (Python) (push) Failing after 49s
CI / Dashboard (Next.js) (push) Failing after 11s

This commit is contained in:
TheOnlyMace
2026-07-21 17:11:38 +02:00
parent 5f34db4f3b
commit b4110c3d66
297 changed files with 2657 additions and 2768 deletions

View File

@@ -1,14 +1,13 @@
# ╔══════════════════════════════════════════════════════════════════╗
# ║ ║
# ║ ░█▀▀░█▀█░█▀▄░█▀▀░█░█ ░█▀▄░█▀▀░█░█░█▀▀
# ║ ░█░░░█░█░█░█░█▀▀░▄▀▄ ░█░█░█▀▀░▀▄▀░▀▀█
# ║ ░▀▀▀░▀▀▀░▀▀░░▀▀▀░▀░▀ ░▀▀░░▀▀▀░░▀░░▀▀▀
# ║ +-+-+-+-+-+-+-+-+
# ║ |H|e|x|a|H|o|s|t|
# ║ +-+-+-+-+-+-+-+-+
# ║ ║
# ║ © 2026 CodeX Devs — All Rights Reserved ║
# ║ © 2026 HexaHost — All Rights Reserved
# ║ ║
# ║ discord ── https://discord.gg/codexdev
# ║ youtube ── https://youtube.com/@CodeXDevs
# ║ github ── https://github.com/RayExo ║
# ║ discord ── https://discord.gg/hexahost
# ║ github ── https://github.com/theoneandonlymace
# ║ ║
# ╚══════════════════════════════════════════════════════════════════╝

View File

@@ -1,14 +1,13 @@
# ╔══════════════════════════════════════════════════════════════════╗
# ║ ║
# ║ ░█▀▀░█▀█░█▀▄░█▀▀░█░█ ░█▀▄░█▀▀░█░█░█▀▀
# ║ ░█░░░█░█░█░█░█▀▀░▄▀▄ ░█░█░█▀▀░▀▄▀░▀▀█
# ║ ░▀▀▀░▀▀▀░▀▀░░▀▀▀░▀░▀ ░▀▀░░▀▀▀░░▀░░▀▀▀
# ║ +-+-+-+-+-+-+-+-+
# ║ |H|e|x|a|H|o|s|t|
# ║ +-+-+-+-+-+-+-+-+
# ║ ║
# ║ © 2026 CodeX Devs — All Rights Reserved ║
# ║ © 2026 HexaHost — All Rights Reserved
# ║ ║
# ║ discord ── https://discord.gg/codexdev
# ║ youtube ── https://youtube.com/@CodeXDevs
# ║ github ── https://github.com/RayExo ║
# ║ discord ── https://discord.gg/hexahost
# ║ github ── https://github.com/theoneandonlymace
# ║ ║
# ╚══════════════════════════════════════════════════════════════════╝
@@ -16,6 +15,8 @@ import aiosqlite
import asyncio
from typing import Dict
from utils.db_paths import resolve_db_path
class DatabaseManager:
"""
A simple manager for persistent SQLite connections to avoid
@@ -29,6 +30,7 @@ class DatabaseManager:
"""
Retrieves an existing connection or creates a new one for the given path.
"""
db_path = resolve_db_path(db_path)
async with self._lock:
if db_path not in self._connections:
# We use check_same_thread=False because aiosqlite handles

View File

@@ -1,14 +1,13 @@
# ╔══════════════════════════════════════════════════════════════════╗
# ║ ║
# ║ ░█▀▀░█▀█░█▀▄░█▀▀░█░█ ░█▀▄░█▀▀░█░█░█▀▀
# ║ ░█░░░█░█░█░█░█▀▀░▄▀▄ ░█░█░█▀▀░▀▄▀░▀▀█
# ║ ░▀▀▀░▀▀▀░▀▀░░▀▀▀░▀░▀ ░▀▀░░▀▀▀░░▀░░▀▀▀
# ║ +-+-+-+-+-+-+-+-+
# ║ |H|e|x|a|H|o|s|t|
# ║ +-+-+-+-+-+-+-+-+
# ║ ║
# ║ © 2026 CodeX Devs — All Rights Reserved ║
# ║ © 2026 HexaHost — All Rights Reserved
# ║ ║
# ║ discord ── https://discord.gg/codexdev
# ║ youtube ── https://youtube.com/@CodeXDevs
# ║ github ── https://github.com/RayExo ║
# ║ discord ── https://discord.gg/hexahost
# ║ github ── https://github.com/theoneandonlymace
# ║ ║
# ╚══════════════════════════════════════════════════════════════════╝
@@ -21,13 +20,13 @@ from slowapi import Limiter
from slowapi.util import get_remote_address
if TYPE_CHECKING:
from core.zyrox import zyrox
from core.hexahost import HexaHost
# Initialize rate limiter
limiter = Limiter(key_func=get_remote_address, default_limits=["1000 per minute"])
# Global reference to the bot instance
_bot_instance: Optional["zyrox"] = None
_bot_instance: Optional["HexaHost"] = None
# Security scheme
security = HTTPBearer()
@@ -54,18 +53,18 @@ def verify_api_key(credentials: HTTPAuthorizationCredentials = Security(security
)
return credentials.credentials
def set_bot(bot_instance: "zyrox"):
def set_bot(bot_instance: "HexaHost"):
"""
Sets the global bot instance.
This should be called in CodeX.py during startup.
This should be called in HexaHost.py during startup.
"""
global _bot_instance
_bot_instance = bot_instance
def get_bot() -> "zyrox":
def get_bot() -> "HexaHost":
"""
FastAPI dependency to retrieve the Discord bot instance.
Usage: bot: zyrox = Depends(get_bot)
Usage: bot: HexaHost = Depends(get_bot)
"""
if _bot_instance is None:
raise HTTPException(

View File

@@ -1,5 +1,14 @@
# ╔══════════════════════════════════════════════════════════════════╗
# ║ Discord OAuth permission checks for dashboard API requests
# ║
# ║ +-+-+-+-+-+-+-+-+ ║
# ║ |H|e|x|a|H|o|s|t| ║
# ║ +-+-+-+-+-+-+-+-+ ║
# ║ ║
# ║ © 2026 HexaHost — All Rights Reserved ║
# ║ ║
# ║ discord ── https://discord.gg/hexahost ║
# ║ github ── https://github.com/theoneandonlymace ║
# ║ ║
# ╚══════════════════════════════════════════════════════════════════╝
from __future__ import annotations

View File

@@ -1,14 +1,13 @@
# ╔══════════════════════════════════════════════════════════════════╗
# ║ ║
# ║ ░█▀▀░█▀█░█▀▄░█▀▀░█░█ ░█▀▄░█▀▀░█░█░█▀▀
# ║ ░█░░░█░█░█░█░█▀▀░▄▀▄ ░█░█░█▀▀░▀▄▀░▀▀█
# ║ ░▀▀▀░▀▀▀░▀▀░░▀▀▀░▀░▀ ░▀▀░░▀▀▀░░▀░░▀▀▀
# ║ +-+-+-+-+-+-+-+-+
# ║ |H|e|x|a|H|o|s|t|
# ║ +-+-+-+-+-+-+-+-+
# ║ ║
# ║ © 2026 CodeX Devs — All Rights Reserved ║
# ║ © 2026 HexaHost — All Rights Reserved
# ║ ║
# ║ discord ── https://discord.gg/codexdev
# ║ youtube ── https://youtube.com/@CodeXDevs
# ║ github ── https://github.com/RayExo ║
# ║ discord ── https://discord.gg/hexahost
# ║ github ── https://github.com/theoneandonlymace
# ║ ║
# ╚══════════════════════════════════════════════════════════════════╝

View File

@@ -1,16 +1,16 @@
# ╔══════════════════════════════════════════════════════════════════╗
# ║ ║
# ║ ░█▀▀░█▀█░█▀▄░█▀▀░█░█ ░█▀▄░█▀▀░█░█░█▀▀
# ║ ░█░░░█░█░█░█░█▀▀░▄▀▄ ░█░█░█▀▀░▀▄▀░▀▀█
# ║ ░▀▀▀░▀▀▀░▀▀░░▀▀▀░▀░▀ ░▀▀░░▀▀▀░░▀░░▀▀▀
# ║ +-+-+-+-+-+-+-+-+
# ║ |H|e|x|a|H|o|s|t|
# ║ +-+-+-+-+-+-+-+-+
# ║ ║
# ║ © 2026 CodeX Devs — All Rights Reserved ║
# ║ © 2026 HexaHost — All Rights Reserved
# ║ ║
# ║ discord ── https://discord.gg/codexdev
# ║ youtube ── https://youtube.com/@CodeXDevs
# ║ github ── https://github.com/RayExo ║
# ║ 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
@@ -20,11 +20,11 @@ import os
import aiosqlite
if TYPE_CHECKING:
from core.zyrox import zyrox
from core.hexahost import HexaHost
router = APIRouter()
CONFIG_DB = "db/admin_config.db"
CONFIG_DB = db_path("admin_config.db")
async def init_db():
async with aiosqlite.connect(CONFIG_DB) as db:
@@ -38,7 +38,7 @@ import psutil
import time
@router.get("/stats", response_model=AdminStats)
async def get_admin_stats(bot: "zyrox" = Depends(get_bot)):
async def get_admin_stats(bot: "HexaHost" = Depends(get_bot)):
# Calculate DB size and shard info
total_size: float = 0.0
db_count = 0

View File

@@ -1,14 +1,13 @@
# ╔══════════════════════════════════════════════════════════════════╗
# ║ ║
# ║ ░█▀▀░█▀█░█▀▄░█▀▀░█░█ ░█▀▄░█▀▀░█░█░█▀▀
# ║ ░█░░░█░█░█░█░█▀▀░▄▀▄ ░█░█░█▀▀░▀▄▀░▀▀█
# ║ ░▀▀▀░▀▀▀░▀▀░░▀▀▀░▀░▀ ░▀▀░░▀▀▀░░▀░░▀▀▀
# ║ +-+-+-+-+-+-+-+-+
# ║ |H|e|x|a|H|o|s|t|
# ║ +-+-+-+-+-+-+-+-+
# ║ ║
# ║ © 2026 CodeX Devs — All Rights Reserved ║
# ║ © 2026 HexaHost — All Rights Reserved
# ║ ║
# ║ discord ── https://discord.gg/codexdev
# ║ youtube ── https://youtube.com/@CodeXDevs
# ║ github ── https://github.com/RayExo ║
# ║ discord ── https://discord.gg/hexahost
# ║ github ── https://github.com/theoneandonlymace
# ║ ║
# ╚══════════════════════════════════════════════════════════════════╝
@@ -20,12 +19,12 @@ from utils.config import *
if TYPE_CHECKING:
from core.zyrox import zyrox
from core.hexahost import HexaHost
router = APIRouter()
@router.get("/status", response_model=BotStatus, summary="Get bot status", description="Returns real-time health metrics, latency, and scale information.")
async def get_status(bot: "zyrox" = Depends(get_bot)):
async def get_status(bot: "HexaHost" = Depends(get_bot)):
"""
Returns the live status of the bot.
"""
@@ -39,7 +38,7 @@ async def get_status(bot: "zyrox" = Depends(get_bot)):
)
@router.get("/info", response_model=BotInfo, summary="Get bot info", description="Returns general information about the bot including command count and user reach.")
async def get_bot_info(bot: "zyrox" = Depends(get_bot)):
async def get_bot_info(bot: "HexaHost" = Depends(get_bot)):
"""
Get general information about the Discord bot.
"""

View File

@@ -1,16 +1,16 @@
# ╔══════════════════════════════════════════════════════════════════╗
# ║ ║
# ║ ░█▀▀░█▀█░█▀▄░█▀▀░█░█ ░█▀▄░█▀▀░█░█░█▀▀
# ║ ░█░░░█░█░█░█░█▀▀░▄▀▄ ░█░█░█▀▀░▀▄▀░▀▀█
# ║ ░▀▀▀░▀▀▀░▀▀░░▀▀▀░▀░▀ ░▀▀░░▀▀▀░░▀░░▀▀▀
# ║ +-+-+-+-+-+-+-+-+
# ║ |H|e|x|a|H|o|s|t|
# ║ +-+-+-+-+-+-+-+-+
# ║ ║
# ║ © 2026 CodeX Devs — All Rights Reserved ║
# ║ © 2026 HexaHost — All Rights Reserved
# ║ ║
# ║ discord ── https://discord.gg/codexdev
# ║ youtube ── https://youtube.com/@CodeXDevs
# ║ github ── https://github.com/RayExo ║
# ║ discord ── https://discord.gg/hexahost
# ║ github ── https://github.com/theoneandonlymace
# ║ ║
# ╚══════════════════════════════════════════════════════════════════╝
from utils.db_paths import db_path, jsondb_path
from fastapi import APIRouter, Depends, HTTPException, Request
from api.dependencies import get_bot, limiter
@@ -37,13 +37,13 @@ import json
import os
if TYPE_CHECKING:
from core.zyrox import zyrox
from core.hexahost import HexaHost
router = APIRouter()
@router.get("/", response_model=List[GuildSummary], summary="List all guilds", description="Returns guilds the authenticated user can manage that the bot is in.")
async def list_guilds(request: Request, bot: "zyrox" = Depends(get_bot)):
async def list_guilds(request: Request, bot: "HexaHost" = Depends(get_bot)):
"""
Lists guilds the bot is in, filtered to those the caller can manage on Discord.
"""
@@ -64,7 +64,7 @@ async def list_guilds(request: Request, bot: "zyrox" = Depends(get_bot)):
return guilds_list
@router.get("/{guild_id}", response_model=GuildDetails, summary="Get guild details", description="Returns detailed metrics and metadata for a specific Discord guild.")
async def get_guild_details(guild_id: int, bot: "zyrox" = Depends(get_bot)):
async def get_guild_details(guild_id: int, bot: "HexaHost" = Depends(get_bot)):
"""
Returns detailed info for a specific guild by its ID.
"""
@@ -87,7 +87,7 @@ async def get_guild_prefix(guild_id: int):
"""
Retrieves the custom prefix for a specific guild.
"""
db = await db_manager.get_connection('db/prefix.db')
db = await db_manager.get_connection(db_path('prefix.db'))
cursor = await db.execute("SELECT prefix FROM prefixes WHERE guild_id = ?", (guild_id,))
row = await cursor.fetchone()
prefix = row[0] if row else ">"
@@ -101,7 +101,7 @@ async def update_guild_prefix(guild_id: int, data: PrefixUpdate):
if not data.prefix or len(data.prefix) > 10:
raise HTTPException(status_code=400, detail="Invalid prefix. Must be 1-10 characters.")
db = await db_manager.get_connection('db/prefix.db')
db = await db_manager.get_connection(db_path('prefix.db'))
await db.execute(
"INSERT OR REPLACE INTO prefixes (guild_id, prefix) VALUES (?, ?)",
(guild_id, data.prefix)
@@ -117,7 +117,7 @@ async def get_guild_automod(guild_id: int):
"""
Retrieves the AutoMod configuration for a specific guild.
"""
db = await db_manager.get_connection('db/automod.db')
db = await db_manager.get_connection(db_path('automod.db'))
# Check enabled status
cursor = await db.execute("SELECT enabled FROM automod WHERE guild_id = ?", (guild_id,))
enabled_row = await cursor.fetchone()
@@ -152,7 +152,7 @@ async def patch_guild_automod(guild_id: int, data: AutomodUpdate):
"""
Updates parts of the AutoMod configuration for a specific guild.
"""
db = await db_manager.get_connection('db/automod.db')
db = await db_manager.get_connection(db_path('automod.db'))
if data.enabled is not None:
await db.execute(
"INSERT OR REPLACE INTO automod (guild_id, enabled) VALUES (?, ?)",
@@ -197,7 +197,7 @@ async def get_guild_tickets(guild_id: int):
"""
Retrieves the ticket system configuration for a specific guild.
"""
db = await db_manager.get_connection('db/ticket.db')
db = await db_manager.get_connection(db_path('ticket.db'))
# Get basic config
cursor = await db.execute(
@@ -263,7 +263,7 @@ async def patch_guild_tickets(guild_id: int, data: TicketUpdate):
"""
Updates the ticket system configuration for a specific guild.
"""
db = await db_manager.get_connection('db/ticket.db')
db = await db_manager.get_connection(db_path('ticket.db'))
# Initialize config row if not exists
cursor = await db.execute("SELECT guild_id FROM guild_configs WHERE guild_id = ?", (guild_id,))
@@ -322,7 +322,7 @@ async def get_guild_leveling(guild_id: int):
"""
Retrieves the leveling system configuration for a specific guild.
"""
db = await db_manager.get_connection('db/leveling.db')
db = await db_manager.get_connection(db_path('leveling.db'))
cursor = await db.execute("SELECT * FROM leveling_settings WHERE guild_id = ?", (guild_id,))
row = await cursor.fetchone()
@@ -357,7 +357,7 @@ async def patch_guild_leveling(guild_id: int, data: LevelingUpdate):
"""
Updates parts of the leveling configuration for a specific guild.
"""
db = await db_manager.get_connection('db/leveling.db')
db = await db_manager.get_connection(db_path('leveling.db'))
# We use a series of updates or a single dynamic update.
# For simplicity and robustness with INSERT OR REPLACE:
@@ -400,7 +400,7 @@ async def get_guild_welcome(guild_id: int):
import aiosqlite
import json
async with aiosqlite.connect("db/welcome.db") as db:
async with aiosqlite.connect(db_path("welcome.db")) as db:
async with db.execute("SELECT welcome_type, welcome_message, channel_id, embed_data, auto_delete_duration FROM welcome WHERE guild_id = ?", (guild_id,)) as cursor:
row = await cursor.fetchone()
@@ -432,7 +432,7 @@ async def patch_guild_welcome(guild_id: int, data: WelcomeUpdate):
import aiosqlite
import json
async with aiosqlite.connect("db/welcome.db") as db:
async with aiosqlite.connect(db_path("welcome.db")) as db:
# Get existing or create
async with db.execute("SELECT welcome_type, welcome_message, channel_id, embed_data, auto_delete_duration FROM welcome WHERE guild_id = ?", (guild_id,)) as cursor:
row = await cursor.fetchone()
@@ -468,7 +468,7 @@ async def patch_guild_welcome(guild_id: int, data: WelcomeUpdate):
async def get_guild_antinuke(guild_id: int):
import aiosqlite
async with aiosqlite.connect("db/anti.db") as db:
async with aiosqlite.connect(db_path("anti.db")) as db:
async with db.execute("SELECT status FROM antinuke WHERE guild_id = ?", (guild_id,)) as cursor:
row = await cursor.fetchone()
@@ -490,7 +490,7 @@ async def get_guild_antinuke(guild_id: int):
async def patch_guild_antinuke(guild_id: int, data: AntiNukeUpdate):
import aiosqlite
async with aiosqlite.connect("db/anti.db") as db:
async with aiosqlite.connect(db_path("anti.db")) as db:
if data.status is not None:
# Get existing or create
async with db.execute("SELECT status FROM antinuke WHERE guild_id = ?", (guild_id,)) as cursor:
@@ -538,7 +538,7 @@ async def patch_guild_antinuke(guild_id: int, data: AntiNukeUpdate):
async def get_guild_verification(guild_id: int):
import aiosqlite
async with aiosqlite.connect("db/verification.db") as db:
async with aiosqlite.connect(db_path("verification.db")) as db:
async with db.execute("SELECT verification_channel_id, verified_role_id, log_channel_id, verification_method, enabled FROM verification_config WHERE guild_id = ?", (guild_id,)) as cursor:
row = await cursor.fetchone()
@@ -564,7 +564,7 @@ async def get_guild_verification(guild_id: int):
async def patch_guild_verification(guild_id: int, data: VerificationUpdate):
import aiosqlite
async with aiosqlite.connect("db/verification.db") as db:
async with aiosqlite.connect(db_path("verification.db")) as db:
async with db.execute("SELECT * FROM verification_config WHERE guild_id = ?", (guild_id,)) as cursor:
row = await cursor.fetchone()
@@ -589,7 +589,7 @@ async def get_guild_vanityroles(guild_id: int):
import aiosqlite
setups = []
async with aiosqlite.connect("db/vanity.db") as db:
async with aiosqlite.connect(db_path("vanity.db")) as db:
async with db.execute("SELECT vanity, role_id, log_channel_id FROM vanity_roles WHERE guild_id = ?", (guild_id,)) as cursor:
rows = await cursor.fetchall()
for row in rows:
@@ -604,7 +604,7 @@ async def get_guild_vanityroles(guild_id: int):
async def post_guild_vanityroles(guild_id: int, data: VanityRoleSetup):
import aiosqlite
async with aiosqlite.connect("db/vanity.db") as db:
async with aiosqlite.connect(db_path("vanity.db")) as db:
await db.execute(
"INSERT OR REPLACE INTO vanity_roles (guild_id, vanity, role_id, log_channel_id, current_status) VALUES (?, ?, ?, ?, NULL)",
(guild_id, data.vanity.lower(), data.role_id, data.log_channel_id)
@@ -617,7 +617,7 @@ async def post_guild_vanityroles(guild_id: int, data: VanityRoleSetup):
async def delete_guild_vanityroles(guild_id: int, vanity: str):
import aiosqlite
async with aiosqlite.connect("db/vanity.db") as db:
async with aiosqlite.connect(db_path("vanity.db")) as db:
await db.execute("DELETE FROM vanity_roles WHERE guild_id = ? AND vanity = ?", (guild_id, vanity.lower()))
await db.commit()
@@ -628,7 +628,7 @@ async def delete_guild_vanityroles(guild_id: int, vanity: str):
async def get_guild_autorole(guild_id: int):
import aiosqlite
async with aiosqlite.connect("db/autorole.db") as db:
async with aiosqlite.connect(db_path("autorole.db")) as db:
# Ensure table exists
await db.execute("""
CREATE TABLE IF NOT EXISTS autorole (
@@ -662,7 +662,7 @@ async def get_guild_autorole(guild_id: int):
async def patch_guild_autorole(guild_id: int, data: AutoRoleUpdate):
import aiosqlite
async with aiosqlite.connect("db/autorole.db") as db:
async with aiosqlite.connect(db_path("autorole.db")) as db:
await db.execute("""
CREATE TABLE IF NOT EXISTS autorole (
guild_id INTEGER PRIMARY KEY,
@@ -701,7 +701,7 @@ async def get_guild_welcome(guild_id: int):
import aiosqlite
import json
async with aiosqlite.connect("db/welcome.db") as db:
async with aiosqlite.connect(db_path("welcome.db")) as db:
async with db.execute("SELECT welcome_type, welcome_message, channel_id, embed_data, auto_delete_duration FROM welcome WHERE guild_id = ?", (guild_id,)) as cursor:
row = await cursor.fetchone()
@@ -730,7 +730,7 @@ async def patch_guild_welcome(guild_id: int, data: WelcomeUpdate):
import aiosqlite
import json
async with aiosqlite.connect("db/welcome.db") as db:
async with aiosqlite.connect(db_path("welcome.db")) as db:
async with db.execute("SELECT welcome_type, welcome_message, channel_id, embed_data, auto_delete_duration FROM welcome WHERE guild_id = ?", (guild_id,)) as cursor:
row = await cursor.fetchone()
@@ -766,7 +766,7 @@ async def patch_guild_welcome(guild_id: int, data: WelcomeUpdate):
@router.delete("/{guild_id}/welcome", summary="Delete Welcome config")
async def delete_guild_welcome(guild_id: int):
import aiosqlite
async with aiosqlite.connect("db/welcome.db") as db:
async with aiosqlite.connect(db_path("welcome.db")) as db:
await db.execute("DELETE FROM welcome WHERE guild_id = ?", (guild_id,))
await db.commit()
return {"status": "success"}
@@ -775,7 +775,7 @@ async def delete_guild_welcome(guild_id: int):
@router.get("/{guild_id}/tracking", response_model=TrackingConfig, summary="Get Tracking config")
async def get_guild_tracking(guild_id: int):
import aiosqlite
async with aiosqlite.connect("db/invite.db") as db:
async with aiosqlite.connect(db_path("invite.db")) as db:
async with db.execute("SELECT channel_id FROM logging WHERE guild_id = ?", (guild_id,)) as cursor:
row = await cursor.fetchone()
return TrackingConfig(guild_id=guild_id, channel_id=row[0] if row else None)
@@ -783,7 +783,7 @@ async def get_guild_tracking(guild_id: int):
@router.patch("/{guild_id}/tracking", summary="Update Tracking config")
async def patch_guild_tracking(guild_id: int, data: TrackingUpdate):
import aiosqlite
async with aiosqlite.connect("db/invite.db") as db:
async with aiosqlite.connect(db_path("invite.db")) as db:
await db.execute("INSERT OR REPLACE INTO logging (guild_id, channel_id) VALUES (?, ?)", (guild_id, data.channel_id))
await db.commit()
return {"status": "success"}
@@ -820,7 +820,7 @@ async def get_guild_j2c(guild_id: int):
return J2CConfig(guild_id=str(guild_id))
@router.patch("/{guild_id}/j2c", summary="Update J2C config")
async def patch_guild_j2c(guild_id: int, data: J2CUpdate, bot: "zyrox" = Depends(get_bot)):
async def patch_guild_j2c(guild_id: int, data: J2CUpdate, bot: "HexaHost" = Depends(get_bot)):
import aiosqlite
def to_id(val):
@@ -903,7 +903,7 @@ async def patch_guild_j2c(guild_id: int, data: J2CUpdate, bot: "zyrox" = Depends
@router.get("/{guild_id}/joindm", response_model=JoinDMConfig, summary="Get JoinDM config")
async def get_guild_joindm(guild_id: int):
config_file = 'jsondb/joindm_messages.json'
config_file = jsondb_path('joindm_messages.json')
os.makedirs('jsondb', exist_ok=True)
if os.path.exists(config_file):
@@ -925,7 +925,7 @@ async def get_guild_joindm(guild_id: int):
@router.patch("/{guild_id}/joindm", summary="Update JoinDM config")
async def patch_guild_joindm(guild_id: int, data: JoinDMUpdate):
config_file = 'jsondb/joindm_messages.json'
config_file = jsondb_path('joindm_messages.json')
os.makedirs('jsondb', exist_ok=True)
messages = {}
@@ -950,7 +950,7 @@ async def patch_guild_joindm(guild_id: int, data: JoinDMUpdate):
@router.get("/{guild_id}/customroles", response_model=CustomRoleConfig, summary="Get CustomRoles config")
async def get_guild_customroles(guild_id: int):
import aiosqlite
async with aiosqlite.connect('db/customrole.db') as db:
async with aiosqlite.connect(db_path('customrole.db')) as db:
async with db.execute("SELECT staff, girl, vip, guest, frnd, reqrole FROM roles WHERE guild_id = ?", (guild_id,)) as cursor:
row = await cursor.fetchone()
if row:
@@ -975,7 +975,7 @@ async def patch_guild_customroles(guild_id: int, data: CustomRoleUpdate):
try: return int(val)
except: return None
async with aiosqlite.connect('db/customrole.db') as db:
async with aiosqlite.connect(db_path('customrole.db')) as db:
async with db.execute("SELECT * FROM roles WHERE guild_id = ?", (guild_id,)) as cursor:
row = await cursor.fetchone()
@@ -1000,7 +1000,7 @@ async def patch_guild_customroles(guild_id: int, data: CustomRoleUpdate):
return {"status": "success"}
@router.get("/{guild_id}/logging", response_model=LoggingConfig, summary="Get Logging config", description="Retrieves the event logging configuration and designated log channels.")
async def get_guild_logging(guild_id: int, bot: "zyrox" = Depends(get_bot)):
async def get_guild_logging(guild_id: int, bot: "HexaHost" = Depends(get_bot)):
"""
Retrieves the logging configuration for a specific guild.
"""
@@ -1013,7 +1013,7 @@ async def get_guild_logging(guild_id: int, bot: "zyrox" = Depends(get_bot)):
# Try reading from file as fallback
import json
import os
config_file = "jsondb/logging_config.json"
config_file = jsondb_path("logging_config.json")
if os.path.exists(config_file):
try:
with open(config_file, "r") as f:
@@ -1044,7 +1044,7 @@ async def get_guild_logging(guild_id: int, bot: "zyrox" = Depends(get_bot)):
)
@router.patch("/{guild_id}/logging", summary="Update Logging config", description="Updates which Discord events are logged and where they are posted.")
async def patch_guild_logging(guild_id: int, data: LoggingUpdate, bot: "zyrox" = Depends(get_bot)):
async def patch_guild_logging(guild_id: int, data: LoggingUpdate, bot: "HexaHost" = Depends(get_bot)):
"""
Updates the logging configuration for a specific guild.
"""
@@ -1076,8 +1076,8 @@ async def patch_guild_logging(guild_id: int, data: LoggingUpdate, bot: "zyrox" =
return {"status": "success", "guild_id": guild_id}
@router.get("/{guild_id}/leveling/leaderboard", response_model=List[LeaderboardEntry], summary="Get leveling leaderboard", description="Returns top users by XP for a specific guild.")
async def get_leveling_leaderboard(guild_id: int, bot: "zyrox" = Depends(get_bot)):
db = await db_manager.get_connection('db/leveling.db')
async def get_leveling_leaderboard(guild_id: int, bot: "HexaHost" = Depends(get_bot)):
db = await db_manager.get_connection(db_path('leveling.db'))
cursor = await db.execute(
"SELECT user_id, xp FROM user_xp WHERE guild_id = ? ORDER BY xp DESC LIMIT 100",
(guild_id,)
@@ -1116,7 +1116,7 @@ async def get_leveling_leaderboard(guild_id: int, bot: "zyrox" = Depends(get_bot
return leaderboard
@router.get("/{guild_id}/channels", response_model=List[DiscordChannel], summary="Get guild channels", description="Returns a list of all channels for the specific guild.")
async def get_guild_channels(guild_id: int, bot: "zyrox" = Depends(get_bot)):
async def get_guild_channels(guild_id: int, bot: "HexaHost" = Depends(get_bot)):
guild = bot.get_guild(guild_id)
if not guild:
raise HTTPException(status_code=404, detail="Guild not found")
@@ -1136,7 +1136,7 @@ async def get_guild_channels(guild_id: int, bot: "zyrox" = Depends(get_bot)):
return channels
@router.get("/{guild_id}/roles", response_model=List[DiscordRole], summary="Get guild roles", description="Returns a list of roles for the specific guild.")
async def get_guild_roles(guild_id: int, bot: "zyrox" = Depends(get_bot)):
async def get_guild_roles(guild_id: int, bot: "HexaHost" = Depends(get_bot)):
guild = bot.get_guild(guild_id)
if not guild:
raise HTTPException(status_code=404, detail="Guild not found")
@@ -1164,7 +1164,7 @@ async def get_guild_roles(guild_id: int, bot: "zyrox" = Depends(get_bot)):
@router.get("/{guild_id}/autoreact", response_model=AutoReactConfig, summary="Get AutoReact config")
async def get_guild_autoreact(guild_id: int):
import aiosqlite
async with aiosqlite.connect("db/autoreact.db") as db:
async with aiosqlite.connect(db_path("autoreact.db")) as db:
await db.execute("""
CREATE TABLE IF NOT EXISTS autoreact (
guild_id INTEGER,
@@ -1185,7 +1185,7 @@ async def get_guild_autoreact(guild_id: int):
@router.get("/{guild_id}/invcrole", response_model=InvcConfig, summary="Get Invc Role config")
async def get_guild_invcrole(guild_id: int):
db = await db_manager.get_connection('db/invc.db')
db = await db_manager.get_connection(db_path('invc.db'))
# Use execute instead of with for shared connection
await db.execute("""
CREATE TABLE IF NOT EXISTS vcroles (
@@ -1209,7 +1209,7 @@ async def get_guild_invcrole(guild_id: int):
@router.patch("/{guild_id}/invcrole", summary="Update Invc Role config")
async def patch_guild_invcrole(guild_id: int, data: InvcUpdate):
db = await db_manager.get_connection('db/invc.db')
db = await db_manager.get_connection(db_path('invc.db'))
# Get existing row to merge
cursor = await db.execute("SELECT role_id, enabled FROM vcroles WHERE guild_id = ?", (guild_id,))
@@ -1246,7 +1246,7 @@ async def patch_guild_invcrole(guild_id: int, data: InvcUpdate):
@router.get("/{guild_id}/autoreact", response_model=AutoReactConfig, summary="Get AutoReact config")
async def get_guild_autoreact(guild_id: int):
import aiosqlite
async with aiosqlite.connect("db/autoreact.db") as db:
async with aiosqlite.connect(db_path("autoreact.db")) as db:
await db.execute("""
CREATE TABLE IF NOT EXISTS autoreact (
guild_id INTEGER,
@@ -1264,7 +1264,7 @@ async def get_guild_autoreact(guild_id: int):
@router.patch("/{guild_id}/autoreact", summary="Update AutoReact config")
async def patch_guild_autoreact(guild_id: int, data: AutoReactUpdate):
db = await db_manager.get_connection("db/autoreact.db")
db = await db_manager.get_connection(db_path("autoreact.db"))
await db.execute("""
CREATE TABLE IF NOT EXISTS autoreact (
guild_id INTEGER,
@@ -1287,7 +1287,7 @@ async def get_guild_invites(guild_id: int):
table_name = f"invites_{guild_id}"
data_list = []
db = await db_manager.get_connection("db/invite.db")
db = await db_manager.get_connection(db_path("invite.db"))
# Check if table exists
async with db.execute("SELECT name FROM sqlite_master WHERE type='table' AND name=?", (table_name,)) as cursor:
exists = await cursor.fetchone()

View File

@@ -1,14 +1,13 @@
# ╔══════════════════════════════════════════════════════════════════╗
# ║ ║
# ║ ░█▀▀░█▀█░█▀▄░█▀▀░█░█ ░█▀▄░█▀▀░█░█░█▀▀
# ║ ░█░░░█░█░█░█░█▀▀░▄▀▄ ░█░█░█▀▀░▀▄▀░▀▀█
# ║ ░▀▀▀░▀▀▀░▀▀░░▀▀▀░▀░▀ ░▀▀░░▀▀▀░░▀░░▀▀▀
# ║ +-+-+-+-+-+-+-+-+
# ║ |H|e|x|a|H|o|s|t|
# ║ +-+-+-+-+-+-+-+-+
# ║ ║
# ║ © 2026 CodeX Devs — All Rights Reserved ║
# ║ © 2026 HexaHost — All Rights Reserved
# ║ ║
# ║ discord ── https://discord.gg/codexdev
# ║ youtube ── https://youtube.com/@CodeXDevs
# ║ github ── https://github.com/RayExo ║
# ║ discord ── https://discord.gg/hexahost
# ║ github ── https://github.com/theoneandonlymace
# ║ ║
# ╚══════════════════════════════════════════════════════════════════╝

View File

@@ -1,14 +1,13 @@
# ╔══════════════════════════════════════════════════════════════════╗
# ║ ║
# ║ ░█▀▀░█▀█░█▀▄░█▀▀░█░█ ░█▀▄░█▀▀░█░█░█▀▀
# ║ ░█░░░█░█░█░█░█▀▀░▄▀▄ ░█░█░█▀▀░▀▄▀░▀▀█
# ║ ░▀▀▀░▀▀▀░▀▀░░▀▀▀░▀░▀ ░▀▀░░▀▀▀░░▀░░▀▀▀
# ║ +-+-+-+-+-+-+-+-+
# ║ |H|e|x|a|H|o|s|t|
# ║ +-+-+-+-+-+-+-+-+
# ║ ║
# ║ © 2026 CodeX Devs — All Rights Reserved ║
# ║ © 2026 HexaHost — All Rights Reserved
# ║ ║
# ║ discord ── https://discord.gg/codexdev
# ║ youtube ── https://youtube.com/@CodeXDevs
# ║ github ── https://github.com/RayExo ║
# ║ discord ── https://discord.gg/hexahost
# ║ github ── https://github.com/theoneandonlymace
# ║ ║
# ╚══════════════════════════════════════════════════════════════════╝
@@ -53,8 +52,8 @@ async def lifespan(app: FastAPI):
def create_app() -> FastAPI:
"""
Initializes the FastAPI application for the CodeX Bot Dashboard.
The bot instance will be attached to app.state.bot in CodeX.py at runtime.
Initializes the FastAPI application for the HexaHost Bot Dashboard.
The bot instance will be attached to app.state.bot in HexaHost.py at runtime.
"""
app = FastAPI(
title=f"{BRAND_NAME} Bot API",