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,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()