Compare commits

..

23 Commits

Author SHA1 Message Date
TheOnlyMace
4f57cccea5 Add Discord sharding support and related configurations
Some checks failed
CI / Bot (Python) (push) Successful in 12s
CI / Dashboard (Next.js) (push) Failing after 9s
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
TheOnlyMace
36b32de34c Enhance AutoMod configuration by introducing event-specific settings and thresholds. Refactor Automod schemas to include event configurations, thresholds, and limits for ignored roles and channels. Update database interactions to support new structure and improve handling of AutoMod rules in cogs, ensuring dynamic thresholds for various events. Update dashboard components to accommodate new configurations and improve user experience in managing AutoMod settings.
Some checks failed
CI / Bot (Python) (push) Successful in 12s
CI / Dashboard (Next.js) (push) Failing after 9s
2026-07-21 23:05:05 +02:00
TheOnlyMace
d24b810164 Refactor command definitions across various cogs to replace hybrid commands with regular commands for improved consistency and clarity. Update command structures in moderation, music, and other cogs to enhance user experience and streamline command handling.
Some checks failed
CI / Bot (Python) (push) Successful in 12s
CI / Dashboard (Next.js) (push) Failing after 9s
2026-07-21 22:59:25 +02:00
TheOnlyMace
a52d84467d Refactor slash command synchronization logic to prevent duplicate commands in Discord. Update environment variables for command sync modes and enhance command clearing functionality. Improve command registration handling in the bot to streamline user experience.
Some checks failed
CI / Bot (Python) (push) Successful in 12s
CI / Dashboard (Next.js) (push) Failing after 9s
2026-07-21 22:53:51 +02:00
TheOnlyMace
1da2085087 Refactor command definitions across multiple cogs to replace hybrid commands with regular commands for consistency. This change enhances clarity and standardizes command handling throughout the bot.
Some checks failed
CI / Bot (Python) (push) Successful in 12s
CI / Dashboard (Next.js) (push) Failing after 8s
2026-07-21 22:50:11 +02:00
TheOnlyMace
20193404e8 Refactor command definitions in owner and moderation cogs for consistency. Change getinvite command to a regular command and update type hints for parameters in enlarge and roleicon commands to improve clarity and type safety.
Some checks failed
CI / Bot (Python) (push) Successful in 12s
CI / Dashboard (Next.js) (push) Failing after 8s
2026-07-21 22:47:29 +02:00
TheOnlyMace
299351463c Refactor welcome message handling in the Autorole cog to enhance user experience. Implement dynamic embed creation for guild join events, including updated branding and links to the dashboard and support server. Improve error handling for direct messages and audit log access.
Some checks failed
CI / Bot (Python) (push) Failing after 12s
CI / Dashboard (Next.js) (push) Failing after 9s
2026-07-21 22:45:50 +02:00
TheOnlyMace
6b0091f7d5 Update invite links to use dynamic Discord client ID and import necessary configuration constants. Refactor slash command synchronization logic for improved error handling and performance.
Some checks failed
CI / Bot (Python) (push) Failing after 12s
CI / Dashboard (Next.js) (push) Failing after 10s
2026-07-21 22:44:40 +02:00
TheOnlyMace
fc77f0a3c2 Implement slash command synchronization features in environment files and update command definitions to hybrid commands across various cogs. Enhance command registration for improved user experience and streamline command handling in the bot. 2026-07-21 22:41:41 +02:00
TheOnlyMace
f15c869993 Enhance Discord authentication and guild management by implementing caching for user and guild data to reduce API calls and improve performance. Update error handling for Discord API responses and refactor the guilds listing logic in the dashboard to streamline data retrieval. Adjust retry logic for rate limits and improve session error handling in the authentication flow.
Some checks failed
CI / Bot (Python) (push) Successful in 12s
CI / Dashboard (Next.js) (push) Failing after 9s
2026-07-21 22:33:30 +02:00
TheOnlyMace
60390009d1 Refactor dashboard notification handling and improve admin broadcast functionality. Ensure only admins can access global notifications, implement draft management for broadcast messages, and add event listeners for real-time updates across dashboard components.
Some checks failed
CI / Bot (Python) (push) Successful in 12s
CI / Dashboard (Next.js) (push) Failing after 9s
2026-07-21 22:30:08 +02:00
TheOnlyMace
18ef29f777 Refactor database path resolution in cogs and improve cog loading error handling. Update database connections in Giveaway, Nightmode, and Owner cogs to use a centralized path resolver. Enhance cog loading feedback with success and failure messages.
Some checks failed
CI / Bot (Python) (push) Successful in 12s
CI / Dashboard (Next.js) (push) Failing after 9s
2026-07-21 22:28:18 +02:00
TheOnlyMace
9006b06c09 Enhance Discord integration by adding optional bot permissions in environment files and updating the dashboard to include an "Add Bot to your Server" button. Refactor authentication logic to handle token refresh and improve error handling for Discord sessions. Update placeholder text for better clarity in the search input field.
Some checks failed
CI / Bot (Python) (push) Successful in 12s
CI / Dashboard (Next.js) (push) Failing after 8s
2026-07-21 22:19:13 +02:00
TheOnlyMace
8294c1b4f7 Update branding assets by replacing SVG logos with PNG versions for improved compatibility and performance. Update references in the BrandLogo component to use the new PNG logo. Additionally, update various favicon and touch icon files to align with the new branding.
Some checks failed
CI / Bot (Python) (push) Successful in 12s
CI / Dashboard (Next.js) (push) Failing after 9s
2026-07-21 21:58:37 +02:00
TheOnlyMace
831a3ac8ea Update dashboard styles and branding to reflect HexaHost theme. Change primary colors, background gradients, and text styles across various components. Enhance layout and navigation elements for improved user experience.
Some checks failed
CI / Bot (Python) (push) Successful in 13s
CI / Dashboard (Next.js) (push) Failing after 9s
2026-07-21 21:24:28 +02:00
TheOnlyMace
698d61ec6d Update requirements.txt to reflect project branding change from HexaHost to Axiom and add aiofiles dependency for file handling.
Some checks failed
CI / Bot (Python) (push) Successful in 13s
CI / Dashboard (Next.js) (push) Failing after 8s
2026-07-21 21:16:21 +02:00
TheOnlyMace
daf3338382 Refactor project branding from HexaHost to Axiom across all configurations, documentation, and code files. Update environment variables, Docker setup, and README to reflect the new brand name. Ensure consistency in naming conventions and improve clarity in setup instructions.
Some checks failed
CI / Bot (Python) (push) Failing after 12s
CI / Dashboard (Next.js) (push) Failing after 9s
2026-07-21 19:45:07 +02:00
TheOnlyMace
03c8f2ec2c Remove NexioHost badge from README for a cleaner presentation.
Some checks failed
CI / Bot (Python) (push) Failing after 12s
CI / Dashboard (Next.js) (push) Failing after 9s
2026-07-21 17:56:24 +02:00
TheOnlyMace
7dca4fb77a Update Docker setup documentation for HexaHost, enhancing clarity on prerequisites, configuration steps, and troubleshooting. Added detailed instructions for setting up Traefik, environment variables, and Discord integration.
Some checks failed
CI / Bot (Python) (push) Failing after 12s
CI / Dashboard (Next.js) (push) Failing after 9s
2026-07-21 17:55:26 +02:00
TheOnlyMace
9bcde844da Replace Creative Commons license with MIT License, updating copyright information and permissions for software usage and distribution.
Some checks failed
CI / Bot (Python) (push) Failing after 11s
CI / Dashboard (Next.js) (push) Failing after 9s
2026-07-21 17:46:46 +02:00
TheOnlyMace
41d5841d82 Enhance project configuration by setting output to "standalone" in Next.js config files and updating .gitignore to include example environment files for better clarity and management.
Some checks failed
CI / Bot (Python) (push) Failing after 12s
CI / Dashboard (Next.js) (push) Failing after 9s
2026-07-21 17:35:08 +02:00
TheOnlyMace
b4110c3d66 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
2026-07-21 17:11:38 +02:00
5f34db4f3b LICENSE aktualisiert 2026-07-21 14:37:31 +00:00
326 changed files with 5760 additions and 3440 deletions

50
.env.docker.example Normal file
View File

@@ -0,0 +1,50 @@
# ── Docker Compose (.env) — copy to .env in the repo root ─────────────────────
# cp .env.docker.example .env
# Discord Bot
TOKEN=TOKEN_HERE
brand_name=Axiom
OWNER_IDS=YOUR_DISCORD_USER_ID_HERE
DASHBOARD_ADMIN_IDS=YOUR_DISCORD_USER_ID_HERE
# Sharding — leave unset for auto (recommended). Multi-process: same TOKEN, shared bot-db volume.
# SHARD_COUNT=
# SHARD_IDS=0,1
# SHARD_PRIMARY=
# Enable API only on the primary shard process.
# Shared secret — must match between bot API and dashboard
DASHBOARD_API_KEY=generate_a_long_random_secret_here
# Lavalink (optional music)
LAVALINK_HOST=lavalink.jirayu.net
LAVALINK_PASSWORD=youshallnotpass
LAVALINK_SECURE=false
LAVALINK_PORT=13592
EMOJI_SYNC=false
JISHAKU_ENABLED=false
# Slash (/) command sync — use ONE mode to avoid duplicate commands in Discord
SLASH_SYNC_MODE=global
SLASH_CLEAR_GUILD_COMMANDS=true
# SLASH_GUILD_IDS=
# Traefik (optional override — default in compose: letsencrypt)
# TRAEFIK_CERT_RESOLVER=letsencrypt
# ── Dashboard / NextAuth ──────────────────────────────────────────────────────
NEXTAUTH_SECRET=generate_a_long_random_secret_here
DISCORD_CLIENT_ID=
DISCORD_CLIENT_SECRET=
# Optional: Discord permission bitfield for /api/invite (default: 8 = Administrator)
# DISCORD_BOT_PERMISSIONS=8
# Same Discord user IDs as owners/admins (comma-separated)
ADMIN_IDS=YOUR_DISCORD_USER_ID_HERE
NEXT_PUBLIC_ADMIN_IDS=YOUR_DISCORD_USER_ID_HERE
NEXT_PUBLIC_BRAND_NAME=Axiom
NEXT_PUBLIC_BRAND_NAME_WORD=AX
# Discord OAuth Redirect URL in the Discord Developer Portal:
# https://bot.hexahost.de/api/auth/callback/discord

76
.github/workflows/ci.yml vendored Normal file
View File

@@ -0,0 +1,76 @@
name: CI
on:
push:
branches: [main, master]
pull_request:
branches: [main, master]
jobs:
bot:
name: Bot (Python)
runs-on: ubuntu-latest
defaults:
run:
working-directory: bot
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.11"
cache: pip
cache-dependency-path: bot/requirements.txt
- name: Install dependencies
run: pip install -r requirements.txt
- name: Syntax check
run: python -m compileall -q -x 'leveling_original' .
- name: Import smoke test
env:
TOKEN: test
OWNER_IDS: "123456789012345678"
API_ENABLED: "false"
TUNNEL_ENABLED: "false"
run: |
python - <<'PY'
from core.axiom import Axiom
from api.server import create_app
bot = Axiom()
create_app()
import cogs
print("imports ok")
PY
dashboard:
name: Dashboard (Next.js)
runs-on: ubuntu-latest
defaults:
run:
working-directory: dashboard
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: "20"
cache: npm
cache-dependency-path: dashboard/package-lock.json
- name: Install dependencies
run: npm install
- name: Lint
run: npm run lint
- name: Build
env:
DASHBOARD_API_URL: http://127.0.0.1:8000/api/v1
DASHBOARD_API_KEY: ci-test-key
NEXTAUTH_URL: http://localhost:3000
NEXTAUTH_SECRET: ci-test-secret-min-32-chars-long!!
DISCORD_CLIENT_ID: "0"
DISCORD_CLIENT_SECRET: ci-secret
run: npm run build

6
.gitignore vendored
View File

@@ -46,9 +46,15 @@ build/
.env
.env.local
.env.*.local
!.env.docker.example
!.env.example
# Ignore SQLite runtime files
bot/db/**/*.db-journal
# Ignore node_modules
node_modules/
package-lock.json
# Ignore Next.js build output

201
DOCKER.md Normal file
View File

@@ -0,0 +1,201 @@
# Axiom — Docker-Setup (Hersteller: HexaHost, Traefik)
Dashboard: **https://bot.hexahost.de**
Bot-API: nur intern (`http://bot:8000`) — nicht öffentlich.
---
## Voraussetzungen
1. **Docker** + **Docker Compose** auf dem Server
2. **Traefik** läuft bereits und ist am Netzwerk `traefik-network` angeschlossen
3. DNS: `bot.hexahost.de` zeigt auf die IP deines Traefik-Servers (A/AAAA)
4. Discord-Anwendung (Bot + OAuth) im [Discord Developer Portal](https://discord.com/developers/applications)
Traefik erwartet typischerweise:
| Einstellung | Wert (Standard hier) |
|-------------|----------------------|
| Externes Netzwerk | `traefik-network` |
| HTTP-Entrypoint | `web` (Port 80) |
| HTTPS-Entrypoint | `websecure` (Port 443) |
| Cert-Resolver | `letsencrypt` |
Falls dein Cert-Resolver anders heißt → später `TRAEFIK_CERT_RESOLVER` in `.env` setzen.
---
## 1. Projekt auf den Server holen
```bash
git clone <dein-repo-url> Axiom
cd Axiom
```
Oder Dateien per SCP/SFTP hochladen und in den Projektordner wechseln.
---
## 2. Traefik-Netzwerk prüfen
```bash
docker network ls | grep traefik-network
```
Falls es fehlt (nur wenn Traefik es nicht schon angelegt hat):
```bash
docker network create traefik-network
```
**Wichtig:** Traefik selbst muss an `traefik-network` hängen. Sonst erreicht Traefik das Dashboard nicht.
---
## 3. Secrets / `.env` anlegen
```bash
cp .env.docker.example .env
nano .env # oder vim / code
```
### Pflichtfelder ausfüllen
| Variable | Bedeutung |
|----------|-----------|
| `TOKEN` | Bot-Token (Discord → Bot → Reset Token) |
| `OWNER_IDS` | Deine Discord-User-ID (Komma bei mehreren) |
| `DASHBOARD_ADMIN_IDS` | IDs für Bot-Admin-API (meist = Owner) |
| `DASHBOARD_API_KEY` | Langes zufälliges Geheimnis (Bot ↔ Dashboard) |
| `NEXTAUTH_SECRET` | Anderes langes zufälliges Geheimnis |
| `DISCORD_CLIENT_ID` | Application ID der Discord-App |
| `DISCORD_CLIENT_SECRET` | OAuth2 → Client Secret |
| `ADMIN_IDS` | Dashboard-Admins (Discord-User-IDs) |
| `NEXT_PUBLIC_ADMIN_IDS` | Gleich wie `ADMIN_IDS` |
Secrets erzeugen (Beispiel):
```bash
openssl rand -hex 32 # für DASHBOARD_API_KEY
openssl rand -hex 32 # für NEXTAUTH_SECRET
```
Discord-User-ID: Discord → Einstellungen → Erweitert → Entwicklermodus → Rechtsklick auf dich → „ID kopieren“.
---
## 4. Discord Developer Portal
### Bot
1. Application öffnen → **Bot** → Token kopieren → in `.env` als `TOKEN`
2. Privileged Gateway Intents aktivieren, die der Bot braucht (z.B. Server Members, Message Content — je nach Features)
3. Bot auf den Server einladen (OAuth2 → URL Generator → `bot` + benötigte Permissions)
### OAuth fürs Dashboard
1. **OAuth2 → General**
2. Redirects hinzufügen:
```text
https://bot.hexahost.de/api/auth/callback/discord
```
3. **Client ID** und **Client Secret** in `.env` eintragen (`DISCORD_CLIENT_ID` / `DISCORD_CLIENT_SECRET`)
---
## 5. Container starten
Im Projektroot (dort wo `docker-compose.yml` liegt):
```bash
docker compose up -d --build
```
Erster Build kann einige Minuten dauern (Python-Deps + Next.js-Build).
Status prüfen:
```bash
docker compose ps
docker compose logs -f bot
docker compose logs -f dashboard
```
Erwartung:
- `axiom-bot` — online, Discord-Login, API auf Port 8000
- `axiom-dashboard` — läuft, Traefik routet `bot.hexahost.de`
---
## 6. Testen
1. Browser: **https://bot.hexahost.de**
2. Mit Discord anmelden
3. Guilds sollten erscheinen (Bot muss auf dem Server sein + du brauchst Manage Server / Admin)
---
## Alltag: Updates & Wartung
```bash
# Neueste Version holen und neu bauen
git pull
docker compose up -d --build
# Nur Neustart
docker compose restart
# Stoppen
docker compose down
# Logs
docker compose logs -f --tail=100
```
Daten liegen in Docker-Volumes (`bot-db`, `bot-jsondb`, `bot-logs`) und bleiben bei `docker compose down` erhalten.
Volumes **löschen** (Daten weg): `docker compose down -v` — nur bewusst nutzen.
---
## Troubleshooting
| Problem | Check |
|---------|--------|
| 502 / Gateway Timeout | `docker compose ps` — läuft `axiom-dashboard`? Traefik am richtigen Netzwerk? |
| Kein HTTPS-Zertifikat | DNS auf Server? Cert-Resolver-Name (`TRAEFIK_CERT_RESOLVER`)? Entrypoints `web`/`websecure`? |
| Login schlägt fehl | Redirect-URL exakt wie oben? `NEXTAUTH_URL` = `https://bot.hexahost.de/`? |
| Dashboard leer / API-Fehler | Gleiches `DASHBOARD_API_KEY`? Bot-Logs: `API_ENABLED` / Startfehler? |
| Bot offline | `TOKEN` gültig? Intents? `docker compose logs bot` |
| Traefik sieht Container nicht | Beide an `traefik-network`? Label `traefik.enable=true`? |
Netzwerk-Check:
```bash
docker network inspect traefik-network
```
Dort sollten u. a. Traefik, `axiom-bot` und `axiom-dashboard` erscheinen.
---
## Architektur (kurz)
```text
Internet
Traefik (traefik-network)
│ Host: bot.hexahost.de
axiom-dashboard :3000
│ DASHBOARD_API_URL=http://bot:8000/api/v1
axiom-bot :8000 (nur Docker-intern)
└── Discord Gateway (ausgehend)
```
Die Bot-API wird **nicht** über Traefik veröffentlicht; das Dashboard spricht sie nur im internen Netzwerk an.

View File

@@ -1,6 +1,6 @@
MIT License
Copyright (c) 2026 CodeX Devs
Copyright (c) 2026 HexaHost
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@@ -3,8 +3,8 @@
| Field | Value |
|-------|-------|
| **Report ID** | ZYROX-SEC-2026-001 |
| **Target** | ZyroX CV2 AIO Discord Bot with Dashboard |
| **Repository** | `ZyroX-CV2-AIO-With-Dashboard-main` |
| **Target** | Axiom CV2 AIO Discord Bot with Dashboard |
| **Repository** | `Axiom-CV2-AIO-With-Dashboard-main` |
| **Assessment Date** | 2026-07-21 |
| **Report Version** | 1.0 |
| **Classification** | Internal — Distribution Restricted |
@@ -34,7 +34,7 @@
## 1. Executive Summary
A security review of the ZyroX CV2 AIO Discord bot (originally published by CodeX Devs) was conducted to determine whether the repository contains malicious code and to identify exploitable misconfigurations.
A security review of the Axiom CV2 AIO Discord bot (originally published by HexaHost) was conducted to determine whether the repository contains malicious code and to identify exploitable misconfigurations.
### 1.1 Malware Classification
@@ -69,7 +69,7 @@ A security review of the ZyroX CV2 AIO Discord bot (originally published by Code
```
┌─────────────────────────────────────┐
│ Trust Boundary │
Discord Users ───►│ discord.py Gateway (bot/CodeX.py) │
Discord Users ───►│ discord.py Gateway (bot/Axiom.py) │
│ │ │ │
│ ▼ ▼ │
│ SQLite (bot/db/) FastAPI :8000 │
@@ -153,7 +153,7 @@ OWNER_IDS: list[int] = _parse_ids("OWNER_IDS", [870179991462236170])
| **CVSS 3.1 (est.)** | 9.8 (AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H) |
| **Status at review** | Open → Remediated (#2) |
**Affected component:** `bot/CodeX.py` (~L345)
**Affected component:** `bot/Axiom.py` (~L345)
```python
await client.load_extension("jishaku")
@@ -176,7 +176,7 @@ await client.load_extension("jishaku")
| **CVSS 3.1 (est.)** | 7.5 (AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N) |
| **Status at review** | Open → Remediated (#3) |
**Affected component:** `bot/CodeX.py``on_command_completion`
**Affected component:** `bot/Axiom.py``on_command_completion`
**Description:** Non-owner command invocations are POSTed to `CMD_WEBHOOK_URL` with command text, user ID, guild name/ID, and channel ID. Owner commands are explicitly excluded from logging.
@@ -198,9 +198,9 @@ await client.load_extension("jishaku")
| File | Channel ID | Function |
|------|------------|----------|
| `bot/CodeX.py` | `1396794297386532978` | Guild join notifications |
| `bot/CodeX.py` | `1419729255977189467` | Server count display |
| `bot/CodeX.py` | `1419729283861184632` | Member count display |
| `bot/Axiom.py` | `1396794297386532978` | Guild join notifications |
| `bot/Axiom.py` | `1419729255977189467` | Server count display |
| `bot/Axiom.py` | `1419729283861184632` | Member count display |
| `bot/cogs/events/on_guild.py` | `1396794297386532978` | Join/leave detail logs |
| `bot/cogs/commands/np.py` | `1396794297386532978` | No-prefix command audit |
@@ -218,7 +218,7 @@ await client.load_extension("jishaku")
| **CWE** | [CWE-284](https://cwe.mitre.org/data/definitions/284.html) — Improper Access Control |
| **Status at review** | Open → Partially remediated (#5, #10) |
**Affected components:** `bot/api/server.py`, `bot/utils/tunnel.py`, `bot/CodeX.py`
**Affected components:** `bot/api/server.py`, `bot/utils/tunnel.py`, `bot/Axiom.py`
**Description:** API listens on `0.0.0.0:8000` by default. Cloudflare tunnel can expose localhost to the public internet. Authentication is a single shared bearer token without per-guild Discord authorization (pre-fix).
@@ -324,7 +324,7 @@ const API_KEY = process.env.NEXT_PUBLIC_DASHBOARD_API_KEY;
| **Severity** | Low / Informational |
| **Status at review** | Acknowledged — no code change required |
**Description:** >100 files contain CodeX branding headers (`discord.gg/codexdev`). Commented `autoblacklist` cog references external support channel. Help footers link to developer Discord.
**Description:** >100 files contain legacy branding headers (`discord.gg/hexahost`). Commented `autoblacklist` cog references external support channel. Help footers link to developer Discord.
**Impact:** No direct exploitation path; increases fingerprinting and social-trust surface.
@@ -388,8 +388,8 @@ const API_KEY = process.env.NEXT_PUBLIC_DASHBOARD_API_KEY;
| Component | Role |
|-----------|------|
| `CodeX.py` | Process entry: bot, API thread, optional tunnel |
| `core/zyrox.py` | `AutoShardedBot` subclass, prefix resolution |
| `Axiom.py` | Process entry: bot, API thread, optional tunnel |
| `core/axiom.py` | `AutoShardedBot` subclass, prefix resolution |
| `utils/config.py` | Centralized environment configuration |
| `api/` | FastAPI REST layer for dashboard |
| `cogs/` | Feature modules (~80+ extensions) |
@@ -454,7 +454,7 @@ All databases are local SQLite files under `bot/db/`. No encryption at rest obse
## Appendix D — Startup Sequence
```
python bot/CodeX.py
python bot/Axiom.py
├─ load_dotenv()
├─ FastAPI thread (if API_ENABLED)
├─ Cloudflare tunnel (if TUNNEL_ENABLED)
@@ -473,7 +473,7 @@ npm run dev (dashboard/)
## 6. Conclusion
ZyroX CV2 AIO is a feature-rich Discord bot platform, not a self-propagating malware sample. The primary security concern is **deployment-time trust delegation**: unchanged defaults effectively assign operational control and observability to the original publisher.
Axiom CV2 AIO is a feature-rich Discord bot platform, not a self-propagating malware sample. The primary security concern is **deployment-time trust delegation**: unchanged defaults effectively assign operational control and observability to the original publisher.
Operators treating this as production software must treat initial configuration as a **security-critical step**, equivalent to key ceremony for any SaaS deployment.

View File

@@ -2,7 +2,7 @@
## Summary
Security audit and hardening of the ZyroX CV2 AIO Discord bot with dashboard. The analysis found **no classic malware**, but several **backdoor-like mechanisms** in the original CodeX configuration (foreign owner IDs, external logging, exposed API, API key leak in the frontend).
Security audit and hardening of the Axiom CV2 AIO Discord bot with dashboard. The analysis found **no classic malware**, but several **backdoor-like mechanisms** in the original legacy configuration (foreign owner IDs, external logging, exposed API, API key leak in the frontend).
This PR addresses **10 security issues** and introduces **secure defaults**: without a proper `.env` configuration, no foreign user retains owner rights, no external logging occurs, and the API is not publicly exposed.

View File

@@ -1,18 +1,14 @@
<div align="center">
```
███████╗██╗ ██╗██████╗ ██████╗ ██╗ ██╗
╚══███╔╝╚██╗ ██╔╝██╔══██╗██╔═══██╗╚██╗██╔╝
███╔╝ ╚████╔╝ ██████╔╝██║ ██║ ╚███╔╝
███╔╝ ╚██╔╝ ██╔══██╗██║ ██║ ██╔██╗
███████╗ ██║ ██║ ██║╚██████╔╝██╔╝ ██╗
╚══════╝ ╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝
+-+-+-+-+-+
|A|x|i|o|m|
+-+-+-+-+-+
by HexaHost
```
<h3>A feature-rich Discord bot paired with a sleek Next.js dashboard</h3>
<a href="https://nexiohost.in"><img src="https://img.shields.io/badge/⭐%20PREMIUM%20HOSTING-NexioHost-FFD700?style=for-the-badge&labelColor=1a1a2e&color=FFD700&logoColor=FFD700"/></a>
<p>
<a href="https://python.org"><img src="https://img.shields.io/badge/Python-3.10+-3776AB?style=for-the-badge&logo=python&logoColor=white"/></a>
<a href="https://nextjs.org"><img src="https://img.shields.io/badge/Next.js-14+-000000?style=for-the-badge&logo=nextdotjs&logoColor=white"/></a>
@@ -21,9 +17,8 @@
</p>
<p>
<a href="LICENSE"><img src="https://img.shields.io/badge/License-MIT-red?style=for-the-badge"/></a>
<a href="https://discord.gg/codexdev"><img src="https://img.shields.io/badge/Discord-Join_Server-5865F2?style=for-the-badge&logo=discord&logoColor=white"/></a>
<a href="https://youtube.com/@CodeXDevs"><img src="https://img.shields.io/badge/YouTube-CodeXDevs-FF0000?style=for-the-badge&logo=youtube&logoColor=white"/></a>
<a href="https://github.com/RayExo"><img src="https://img.shields.io/badge/GitHub-RayExo-181717?style=for-the-badge&logo=github&logoColor=white"/></a>
<a href="https://discord.gg/hexahost"><img src="https://img.shields.io/badge/Discord-Join_Server-5865F2?style=for-the-badge&logo=discord&logoColor=white"/></a>
<a href="https://github.com/theoneandonlymace"><img src="https://img.shields.io/badge/GitHub-theoneandonlymace-181717?style=for-the-badge&logo=github&logoColor=white"/></a>
</p>
</div>
@@ -32,10 +27,10 @@
## ✦ Overview
ZyroX is a fully-featured Discord bot with a modern web dashboard for managing everything from antinuke to music. Built on `discord.py v2`, `FastAPI`, and `Next.js 14` with Tailwind CSS.
Axiom is a fully-featured Discord bot by HexaHost with a modern web dashboard for managing everything from antinuke to music. Built on `discord.py v2`, `FastAPI`, and `Next.js 14` with Tailwind CSS.
```
ZyroX-CV2-With-Dashboard/
Axiom-CV2-With-Dashboard/
├── 🤖 bot/ Python Discord bot + FastAPI backend
│ ├── api/ Dashboard REST API (FastAPI)
│ ├── cogs/ All bot features (commands, events, antinuke, automod…)
@@ -43,7 +38,7 @@ ZyroX-CV2-With-Dashboard/
│ ├── utils/ Shared utilities (emoji, tools, sync, cloudflare tunnel…)
│ ├── games/ Standalone game modules
│ ├── assets/ Fonts, backgrounds, GIFs
│ └── CodeX.py Entry point
│ └── Axiom.py Entry point
└── 🌐 dashboard/ Next.js frontend
├── app/ App Router pages & API routes
@@ -122,7 +117,7 @@ ZyroX-CV2-With-Dashboard/
- Slash + prefix commands
- FastAPI backend with API key auth + rate limiting
- Cloudflare Tunnel — unlimited bandwidth, permanent URL, zero system installs
- CodeX Devs watermark on every source file
- HexaHost manufacturer watermark on every source file
</td>
</tr>
@@ -148,8 +143,8 @@ ZyroX-CV2-With-Dashboard/
**1 — Clone the repo**
```bash
git clone https://github.com/RayExo/ZyroX-CV2-With-Dashboard
cd ZyroX-CV2-With-Dashboard/bot
git clone https://github.com/theoneandonlymace/Axiom-CV2-With-Dashboard
cd Axiom-CV2-With-Dashboard/bot
```
**2 — Install dependencies**
@@ -173,7 +168,7 @@ Copy `.env.example` to `.env` and fill in the values:
```env
# ── Core ──────────────────────────────────────────────────────────
TOKEN = your_discord_bot_token
brand_name = 'ZyroX'
brand_name = 'Axiom'
# ── Owner IDs (REQUIRED — your Discord user ID) ───────────────────
OWNER_IDS = YOUR_DISCORD_USER_ID_HERE
@@ -207,7 +202,7 @@ CF_TUNNEL_URL = "https://api.yourdomain.com"
**4 — Run the bot**
```bash
python CodeX.py
python Axiom.py
```
---
@@ -237,7 +232,7 @@ DISCORD_CLIENT_SECRET = your_discord_oauth_client_secret
ADMIN_IDS = your_discord_user_id
NEXT_PUBLIC_ADMIN_IDS = your_discord_user_id
NEXT_PUBLIC_BRAND_NAME = "ZyroX"
NEXT_PUBLIC_BRAND_NAME = "Axiom"
NEXT_PUBLIC_BRAND_NAME_WORD = "ZX"
```
@@ -309,7 +304,7 @@ The bot uses **pycloudflared** — a Python package that downloads the `cloudfla
**Setup (browser only, no CLI needed):**
1. Go to [one.dash.cloudflare.com](https://one.dash.cloudflare.com) → **Networks → Tunnels → Create a tunnel**
2. Choose **Cloudflared**, give it a name (e.g. `zyrox-api`), save
2. Choose **Cloudflared**, give it a name (e.g. `axiom-api`), save
3. On the **Install connector** step, copy the token from the command shown:
```
cloudflared tunnel run --token <COPY_THIS>
@@ -336,7 +331,7 @@ On every startup the console prints:
### 🤖 Bot — any Python host
1. Upload the entire `bot/` folder to your host (Pterodactyl, Render, Railway, Fly.io, VPS…)
2. Set the start command to `python CodeX.py`
2. Set the start command to `python Axiom.py`
3. Add all environment variables
4. `pycloudflared` downloads the binary automatically on first run — no extra steps
@@ -407,19 +402,18 @@ Runs automatically on startup when `EMOJI_SYNC=true`:
<div align="center">
## ✦ CodeX Devs
## ✦ HexaHost
*Built for protection. Designed for style.*
<a href="https://discord.gg/codexdev"><img src="https://discord.com/api/guilds/1301573144817045524/widget.png?style=banner2" alt="CodeX Development Discord Server" width="480"/></a>
<a href="https://discord.gg/hexahost"><img src="https://discord.com/api/guilds/1301573144817045524/widget.png?style=banner2" alt="HexaHost Discord Server" width="480"/></a>
<p>
<a href="https://discord.gg/codexdev"><img src="https://img.shields.io/badge/Discord-Join_Server-5865F2?style=for-the-badge&logo=discord&logoColor=white"/></a>
<a href="https://youtube.com/@CodeXDevs"><img src="https://img.shields.io/badge/YouTube-CodeXDevs-FF0000?style=for-the-badge&logo=youtube&logoColor=white"/></a>
<a href="https://github.com/RayExo"><img src="https://img.shields.io/badge/GitHub-RayExo-181717?style=for-the-badge&logo=github&logoColor=white"/></a>
<a href="https://discord.gg/hexahost"><img src="https://img.shields.io/badge/Discord-Join_Server-5865F2?style=for-the-badge&logo=discord&logoColor=white"/></a>
<a href="https://github.com/theoneandonlymace"><img src="https://img.shields.io/badge/GitHub-theoneandonlymace-181717?style=for-the-badge&logo=github&logoColor=white"/></a>
<a href="https://nexiohost.in"><img src="https://img.shields.io/badge/⭐%20PREMIUM%20HOSTING-NexioHost-FFD700?style=for-the-badge&labelColor=1a1a2e&color=FFD700&logoColor=FFD700"/></a>
</p>
© 2026 CodeX Devs — MIT License
© 2026 HexaHost — MIT License
</div>

View File

@@ -7,7 +7,7 @@
| **Publication Date** | 2026-07-21 |
| **Status** | Patches applied — operator action required |
| **Classification** | Internal — Distribution Restricted |
| **Affected Product** | ZyroX CV2 AIO Discord Bot with Dashboard |
| **Affected Product** | Axiom CV2 AIO Discord Bot with Dashboard |
---
@@ -46,7 +46,7 @@ This document tracks remediation of findings identified during static security a
| File | Change |
|------|--------|
| `bot/utils/config.py` | `_parse_ids()` returns empty list on missing env var |
| `bot/CodeX.py` | Startup warning when `OWNER_IDS` is empty |
| `bot/Axiom.py` | Startup warning when `OWNER_IDS` is empty |
| `bot/.env.example` | Placeholder `YOUR_DISCORD_USER_ID_HERE`; foreign IDs removed |
| `dashboard/.env.example` | `ADMIN_IDS` placeholder replaces foreign ID |
@@ -67,7 +67,7 @@ OWNER_IDS=<your_discord_snowflake>
| File | Change |
|------|--------|
| `bot/utils/config.py` | `JISHAKU_ENABLED` flag (default: `false`) |
| `bot/CodeX.py` | Conditional extension load |
| `bot/Axiom.py` | Conditional extension load |
| `bot/.env.example` | Documented opt-in flag |
**Post-patch behavior:** Jishaku inactive unless `JISHAKU_ENABLED=true`. Recommended for local debugging only.
@@ -82,7 +82,7 @@ OWNER_IDS=<your_discord_snowflake>
| File | Change |
|------|--------|
| `bot/utils/config.py` | `_valid_webhook_url()` rejects empty/placeholder values |
| `bot/CodeX.py` | `on_command_completion` early-return when URL invalid |
| `bot/Axiom.py` | `on_command_completion` early-return when URL invalid |
**Post-patch behavior:** No outbound command telemetry without fully qualified, operator-configured webhook URL.
@@ -96,7 +96,7 @@ OWNER_IDS=<your_discord_snowflake>
| File | Change |
|------|--------|
| `bot/utils/config.py` | `LOG_CHANNEL_ID`, `SERVER_COUNT_CHANNEL_ID`, `USER_COUNT_CHANNEL_ID` |
| `bot/CodeX.py` | Config-driven channel references; stats task gated on config |
| `bot/Axiom.py` | Config-driven channel references; stats task gated on config |
| `bot/cogs/events/on_guild.py` | Join/leave logging conditional on `LOG_CHANNEL_ID` |
| `bot/cogs/commands/np.py` | Audit logs use `LOG_CHANNEL_ID` |
| `bot/.env.example` | Optional IDs documented (commented) |
@@ -120,7 +120,7 @@ USER_COUNT_CHANNEL_ID=<channel_snowflake>
| File | Change |
|------|--------|
| `bot/utils/config.py` | `API_ENABLED=false`, `API_HOST=127.0.0.1`, `TUNNEL_ENABLED=false` |
| `bot/CodeX.py` | Bind to `API_HOST`; warn on `0.0.0.0` |
| `bot/Axiom.py` | Bind to `API_HOST`; warn on `0.0.0.0` |
| `bot/.env.example` | Secure defaults documented |
**Post-patch behavior:** API and tunnel disabled until explicitly enabled. Localhost binding by default.
@@ -200,7 +200,7 @@ Remove `NEXT_PUBLIC_DASHBOARD_API_KEY` from any existing `.env`.
| File | Change |
|------|--------|
| `bot/cogs/commands/general.py` | Removed `hack`, `token`, `wizz`; dead code cleanup |
| `bot/cogs/zyrox/general.py` | Help index updated |
| `bot/cogs/axiom/general.py` | Help index updated |
**Post-patch behavior:** Commands no longer registered. No regression in remaining general commands.
@@ -234,8 +234,8 @@ Secondary pass on remediation code identified gaps in the initial proxy implemen
| API proxy accessible without session | Critical | Session gate + guild/admin validation in proxy route |
| Guild dashboard pages lacking authZ check | High | `guild/[guildId]/layout.tsx` enforces Discord permissions |
| `GET /guilds` returned all bot guilds | High | Proxy filters to user-manageable intersection |
| `on_command_completion` NullPointer on `command is None` | Medium | Guard clause in `CodeX.py` |
| Orphaned `jishaku` import in `bot/core/zyrox.py` | Low | Import removed |
| `on_command_completion` NullPointer on `command is None` | Medium | Guard clause in `Axiom.py` |
| Orphaned `jishaku` import in `bot/core/axiom.py` | Low | Import removed |
| Admin check relied solely on `NEXT_PUBLIC_ADMIN_IDS` | Medium | Server-side `ADMIN_IDS` supported |
---
@@ -274,8 +274,8 @@ Execute after pulling patched codebase:
| Item | Rationale | Risk Level |
|------|-----------|------------|
| Developer credits in `mention.py`, `stats.py` | Cosmetic attribution | Informational |
| CodeX file headers | Branding | Informational |
| `discord.gg/codexdev` in welcome templates | Operator-configurable content | Informational |
| Legacy file headers | Branding | Informational |
| `discord.gg/hexahost` in welcome templates | Operator-configurable content | Informational |
These items do not constitute exploitable vulnerabilities under the assessed threat model.

19
bot/.dockerignore Normal file
View File

@@ -0,0 +1,19 @@
.env
.env.*
!.env.example
__pycache__
*.py[cod]
*.db
*.db-journal
.venv
venv
myenv
.git
.gitignore
*.md
LICENSE
logs
*.log
.pytest_cache
.mypy_cache
CodeX.py

View File

@@ -1,6 +1,23 @@
TOKEN=TOKEN_HERE
brand_name='ZyroX'
NEXT_PUBLIC_BRAND_NAME='ZyroX'
brand_name='Axiom'
NEXT_PUBLIC_BRAND_NAME='Axiom'
# ── Multiple instances (optional) ─────────────────────────────────────────────
# Run several bot processes on one host — each needs its own .env / TOKEN / API_PORT.
# BOT_INSTANCE_ID isolates all SQLite + jsondb files under bot/db/<id>/ (and jsondb subfolder).
# Leave unset for normal single-bot operation (paths stay bot/db/*.db and bot/jsondb/*.json).
# BOT_INSTANCE_ID=prod-a
# API_PORT=8001
# ── Discord sharding (optional) ───────────────────────────────────────────────
# Default (all unset): AutoShardedBot asks Discord for recommended shard count (one process).
# Multi-process cluster: same TOKEN + shared DB volume; set SHARD_COUNT + SHARD_IDS per process.
# API / slash sync / emoji sync only on the primary (shard 0 in SHARD_IDS, or SHARD_PRIMARY=true).
# SHARD_COUNT=
# SHARD_IDS=0,1
# SHARD_PRIMARY=
# Only enable API on the primary process:
# API_ENABLED=true
# ── Owner / Staff IDs (REQUIRED — comma-separated Discord user IDs) ───────────
# Set your own Discord user ID(s). No foreign IDs are used as fallback.
@@ -20,8 +37,12 @@ LAVALINK_PASSWORD="youshallnotpass"
LAVALINK_SECURE="false"
LAVALINK_PORT="13592"
# ── Emoji Sync ────────────────────────────────────────────────────────────────
EMOJI_SYNC="false"
SLASH_SYNC_MODE=global
# global = one set worldwide (default, no duplicates)
# guild = instant only in connected servers (set SLASH_GUILD_IDS or rely on all guilds)
# SLASH_GUILD_IDS=
# Clears old per-server copies that caused duplicate /commands in Discord
SLASH_CLEAR_GUILD_COMMANDS=true
# ── API / Dashboard Backend ───────────────────────────────────────────────────
API_ENABLED="false"

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
# ║ ║
# ╚══════════════════════════════════════════════════════════════════╝
@@ -29,11 +28,12 @@ from discord.ext import commands, tasks
from core import Context
from core.Cog import Cog
from core.zyrox import zyrox
from core.axiom import Axiom
from utils.Tools import *
from utils.config import *
from utils.emoji import SUCCESS, ERROR, TICK, CROSS, REACTION_TEST_EMOJIS
from utils.sync_emojis import run_sync
from utils.slash_sync import sync_slash_commands
import cogs
@@ -51,7 +51,7 @@ if not OWNER_IDS:
print("\033[33m⚠ OWNER_IDS is not set in .env — no bot owners configured.\033[0m")
print("\033[33m Set OWNER_IDS=YOUR_DISCORD_USER_ID before running in production.\033[0m")
client = zyrox()
client = Axiom()
tree = client.tree
# --- Background Task for Stats ---
@@ -87,37 +87,75 @@ async def on_ready():
print("""
\033[1;31m
+-+-+-+-+-+-+-+-+-+
|H|e|x|a|H|o|s|t|
+-+-+-+-+-+-+-+-+-+
\033[0m
""")
print("Loaded & Online!")
print(f"Logged in as: {client.user}")
print(f"Connected to: {len(client.guilds)} guilds")
print(f"Connected to: {len(client.users)} users")
shard_count = client.shard_count or 1
shard_ids = list(client.shards.keys()) if client.shards else [0]
print(f"Shards: {shard_count} (this process: {shard_ids})")
print(f"Shard primary: {IS_SHARD_PRIMARY}")
if client.latencies:
for sid, lat in client.latencies:
print(f" Shard {sid}: {round(lat * 1000)}ms")
if not IS_SHARD_PRIMARY:
print("\033[33m◈ Non-primary shard process — skipping API-side sync tasks\033[0m")
return
# Sync application emojis on startup
await run_sync(TOKEN)
async def sync_commands():
# Register / slash commands (guild sync = instant; global can take up to ~1h)
if not getattr(client, "_slash_synced", False):
client._slash_synced = True
try:
synced = await client.tree.sync()
all_commands = list(client.commands)
print(f"Synced Total {len(all_commands)} Client Commands and {len(synced)} Slash Commands")
await sync_slash_commands(client)
except Exception as e:
print(f"Error syncing command tree: {e}")
print(f"\033[31mError syncing command tree: {e}\033[0m")
client.loop.create_task(sync_commands())
if SERVER_COUNT_CHANNEL_ID or USER_COUNT_CHANNEL_ID:
client.loop.create_task(update_stats())
@client.event
async def on_shard_connect(shard_id: int):
print(f"\033[32m◈ Shard {shard_id}: connected\033[0m")
@client.event
async def on_shard_ready(shard_id: int):
print(f"\033[32m◈ Shard {shard_id}: ready\033[0m")
@client.event
async def on_shard_disconnect(shard_id: int):
print(f"\033[33m◈ Shard {shard_id}: disconnected\033[0m")
@client.event
async def on_shard_resumed(shard_id: int):
print(f"\033[32m◈ Shard {shard_id}: resumed\033[0m")
@client.event
async def on_guild_join(guild: discord.Guild):
# Only guild-mode needs per-server registration; global mode must not
# copy commands into the guild or Discord shows duplicates (/afk twice).
if IS_SHARD_PRIMARY:
try:
from utils.slash_sync import _sync_mode, sync_guild
if _sync_mode() == "guild":
synced = await sync_guild(client, guild, copy_global=True)
print(f"◈ Slash sync for new guild {guild.id}: {len(synced)} command(s)")
except Exception as e:
print(f"Slash sync on guild join failed: {e}")
if not LOG_CHANNEL_ID:
return
log_channel = client.get_channel(LOG_CHANNEL_ID)
@@ -322,6 +360,9 @@ def run_api():
uvicorn.run(fastapi_app, host=API_HOST, port=API_PORT, log_level="warning")
def keep_alive():
if not IS_SHARD_PRIMARY:
print(f"\033[33m◈ API Server: Skipped (non-primary shard process)\033[0m")
return
if not API_ENABLED:
print(f"\033[33m◈ API Server: Disabled via API_ENABLED=false\033[0m")
return
@@ -335,7 +376,10 @@ keep_alive()
# --- Cloudflare Tunnel (HTTPS for API) — only when explicitly enabled ---
from utils.tunnel import start_tunnel
if IS_SHARD_PRIMARY:
start_tunnel()
else:
print("\033[33m◈ Cloudflare Tunnel: Skipped (non-primary shard process)\033[0m")
# --- Main Bot Execution ---
async def main():

29
bot/Dockerfile Normal file
View File

@@ -0,0 +1,29 @@
# Axiom Discord Bot + FastAPI dashboard backend (by HexaHost)
FROM python:3.12-slim-bookworm
ENV PYTHONDONTWRITEBYTECODE=1 \
PYTHONUNBUFFERED=1 \
PIP_NO_CACHE_DIR=1 \
PIP_DISABLE_PIP_VERSION_CHECK=1
WORKDIR /app
RUN apt-get update && apt-get install -y --no-install-recommends \
gcc \
libffi-dev \
libjpeg62-turbo-dev \
zlib1g-dev \
libsodium-dev \
&& rm -rf /var/lib/apt/lists/*
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .
# Persist SQLite / JSON data outside the image
RUN mkdir -p /app/db /app/jsondb /app/logs
EXPOSE 8000
CMD ["python", "Axiom.py"]

View File

@@ -1,6 +1,6 @@
MIT License
Copyright (c) 2026 CodeX Devs
Copyright (c) 2026 HexaHost
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@@ -1,15 +1,13 @@
<div align="center">
```
███████╗██╗ ██╗██████╗ ██████╗ ██╗ ██╗
╚══███╔╝╚██╗ ██╔╝██╔══██╗██╔═══██╗╚██╗██╔╝
███╔╝ ╚████╔╝ ██████╔╝██║ ██║ ╚███╔╝
███╔╝ ╚██╔╝ ██╔══██╗██║ ██║ ██╔██╗
███████╗ ██║ ██║ ██║╚██████╔╝██╔╝ ██╗
╚══════╝ ╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝
+-+-+-+-+-+
|A|x|i|o|m|
+-+-+-+-+-+
by HexaHost
```
<h3>ZyroX Bot — Python Discord Bot + FastAPI Backend</h3>
<h3>Axiom Bot — Python Discord Bot + FastAPI Backend</h3>
<a href="https://nexiohost.in"><img src="https://img.shields.io/badge/⭐%20PREMIUM%20HOSTING-NexioHost-FFD700?style=for-the-badge&labelColor=1a1a2e&color=FFD700&logoColor=FFD700"/></a>
@@ -20,9 +18,8 @@
<a href="LICENSE"><img src="https://img.shields.io/badge/License-MIT-red?style=for-the-badge"/></a>
</p>
<p>
<a href="https://discord.gg/codexdev"><img src="https://img.shields.io/badge/Discord-Join_Server-5865F2?style=for-the-badge&logo=discord&logoColor=white"/></a>
<a href="https://youtube.com/@CodeXDevs"><img src="https://img.shields.io/badge/YouTube-CodeXDevs-FF0000?style=for-the-badge&logo=youtube&logoColor=white"/></a>
<a href="https://github.com/RayExo"><img src="https://img.shields.io/badge/GitHub-RayExo-181717?style=for-the-badge&logo=github&logoColor=white"/></a>
<a href="https://discord.gg/hexahost"><img src="https://img.shields.io/badge/Discord-Join_Server-5865F2?style=for-the-badge&logo=discord&logoColor=white"/></a>
<a href="https://github.com/theoneandonlymace"><img src="https://img.shields.io/badge/GitHub-theoneandonlymace-181717?style=for-the-badge&logo=github&logoColor=white"/></a>
</p>
</div>
@@ -31,7 +28,7 @@
## ✦ Overview
This folder contains the ZyroX Discord bot built on `discord.py v2` alongside a `FastAPI` backend that powers the web dashboard. Everything runs from a single `python CodeX.py` command.
This folder contains the Axiom Discord bot built on `discord.py v2` alongside a `FastAPI` backend that powers the web dashboard. Everything runs from a single `python Axiom.py` command.
```
bot/
@@ -43,12 +40,12 @@ bot/
│ ├── commands/ All slash & prefix command modules
│ ├── events/ General Discord event listeners
│ ├── moderation/ Moderation action modules
│ └── zyrox/ Core ZyroX feature cogs
│ └── axiom/ Help / feature index cogs
├── core/ Bot client, context, cog base classes
├── games/ Standalone game logic + button views
├── utils/ Emoji, tools, sync, Cloudflare tunnel
├── assets/ Fonts, backgrounds, GIFs
└── CodeX.py Entry point
└── Axiom.py Entry point
```
---
@@ -136,7 +133,7 @@ bot/
- Slash + prefix commands
- Cloudflare Tunnel via pycloudflared — zero system installs, unlimited traffic
- Single `OWNER_IDS` env var controls all permission checks
- CodeX Devs watermark on every source file
- HexaHost manufacturer watermark on every source file
</td>
</tr>
@@ -178,7 +175,7 @@ Create a `.env` file (copy from `.env.example`):
```env
# ── Core ──────────────────────────────────────────────────────────
TOKEN = your_discord_bot_token
brand_name = 'ZyroX'
brand_name = 'Axiom'
# ── Owner IDs (REQUIRED — your Discord user ID) ───────────────────
OWNER_IDS = YOUR_DISCORD_USER_ID_HERE
@@ -212,7 +209,7 @@ CF_TUNNEL_URL = "https://api.yourdomain.com"
### 3 — Run
```bash
python CodeX.py
python Axiom.py
```
---
@@ -262,7 +259,7 @@ Uses **pycloudflared** — downloads the `cloudflared` binary automatically on f
**Setup (browser only — no CLI needed):**
1. Go to [one.dash.cloudflare.com](https://one.dash.cloudflare.com) → **Networks → Tunnels → Create a tunnel**
2. Choose **Cloudflared**, name it (e.g. `zyrox-api`), save
2. Choose **Cloudflared**, name it (e.g. `axiom-api`), save
3. On **Install connector**, copy the token from the command shown:
```
cloudflared tunnel run --token <COPY_THIS_TOKEN>
@@ -304,7 +301,7 @@ When `EMOJI_SYNC=true`, the bot syncs application emojis on every startup:
Upload the entire `bot/` folder to your host and set the start command to:
```bash
python CodeX.py
python Axiom.py
```
`pycloudflared` downloads the binary on first run — no extra steps on any host.
@@ -331,19 +328,18 @@ python CodeX.py
<div align="center">
## ✦ CodeX Devs
## ✦ HexaHost
*Built for protection. Designed for style.*
<a href="https://discord.gg/codexdev"><img src="https://discord.com/api/guilds/1301573144817045524/widget.png?style=banner2" alt="CodeX Development Discord Server" width="480"/></a>
<a href="https://discord.gg/hexahost"><img src="https://discord.com/api/guilds/1301573144817045524/widget.png?style=banner2" alt="HexaHost Discord Server" width="480"/></a>
<p>
<a href="https://discord.gg/codexdev"><img src="https://img.shields.io/badge/Discord-Join_Server-5865F2?style=for-the-badge&logo=discord&logoColor=white"/></a>
<a href="https://youtube.com/@CodeXDevs"><img src="https://img.shields.io/badge/YouTube-CodeXDevs-FF0000?style=for-the-badge&logo=youtube&logoColor=white"/></a>
<a href="https://github.com/RayExo"><img src="https://img.shields.io/badge/GitHub-RayExo-181717?style=for-the-badge&logo=github&logoColor=white"/></a>
<a href="https://discord.gg/hexahost"><img src="https://img.shields.io/badge/Discord-Join_Server-5865F2?style=for-the-badge&logo=discord&logoColor=white"/></a>
<a href="https://github.com/theoneandonlymace"><img src="https://img.shields.io/badge/GitHub-theoneandonlymace-181717?style=for-the-badge&logo=github&logoColor=white"/></a>
<a href="https://nexiohost.in"><img src="https://img.shields.io/badge/⭐%20PREMIUM%20HOSTING-NexioHost-FFD700?style=for-the-badge&labelColor=1a1a2e&color=FFD700&logoColor=FFD700"/></a>
</p>
© 2026 CodeX Devs — MIT License
© 2026 HexaHost — MIT License
</div>

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.axiom import Axiom
# 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["Axiom"] = 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: "Axiom"):
"""
Sets the global bot instance.
This should be called in CodeX.py during startup.
This should be called in Axiom.py during startup.
"""
global _bot_instance
_bot_instance = bot_instance
def get_bot() -> "zyrox":
def get_bot() -> "Axiom":
"""
FastAPI dependency to retrieve the Discord bot instance.
Usage: bot: zyrox = Depends(get_bot)
Usage: bot: Axiom = Depends(get_bot)
"""
if _bot_instance is None:
raise HTTPException(

View File

@@ -1,10 +1,21 @@
# ╔══════════════════════════════════════════════════════════════════╗
# ║ 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
import asyncio
import re
import time
from typing import Any
import aiohttp
@@ -17,6 +28,17 @@ ADMINISTRATOR = 0x8
GUILD_PATH_RE = re.compile(r"^/api/v1/guilds/(\d+)(?:/|$)")
# Short-lived process caches — cut Discord 429s from dashboard reloads
_USER_CACHE_TTL = 60.0
_GUILDS_CACHE_TTL = 60.0
_user_cache: dict[str, tuple[float, dict[str, Any]]] = {}
_guilds_cache: dict[str, tuple[float, list[dict[str, Any]]]] = {}
_guilds_inflight: dict[str, asyncio.Future[list[dict[str, Any]]]] = {}
def _token_key(access_token: str) -> str:
return f"{access_token[:12]}:{len(access_token)}:{access_token[-8:]}"
def _parse_admin_ids() -> list[str]:
import os
@@ -37,33 +59,92 @@ def can_manage_guild(guild: dict[str, Any]) -> bool:
return bool(perms & ADMINISTRATOR) or bool(perms & MANAGE_GUILD)
def _discord_auth_error(status: int) -> HTTPException:
if status == 429:
return HTTPException(
status_code=429,
detail="Discord rate limit — please wait a few seconds and retry.",
)
if status in (401, 403):
return HTTPException(
status_code=401,
detail="Invalid or expired Discord access token. Please sign out and sign in again.",
)
return HTTPException(
status_code=403,
detail=f"Discord API error ({status}).",
)
async def fetch_user_guilds(access_token: str) -> list[dict[str, Any]]:
key = _token_key(access_token)
cached = _guilds_cache.get(key)
if cached and cached[0] > time.monotonic():
return cached[1]
existing = _guilds_inflight.get(key)
if existing is not None:
return await existing
loop = asyncio.get_running_loop()
fut: asyncio.Future[list[dict[str, Any]]] = loop.create_future()
_guilds_inflight[key] = fut
try:
guilds = await _fetch_user_guilds_uncached(access_token)
_guilds_cache[key] = (time.monotonic() + _GUILDS_CACHE_TTL, guilds)
fut.set_result(guilds)
return guilds
except Exception as exc:
fut.set_exception(exc)
raise
finally:
_guilds_inflight.pop(key, None)
async def _fetch_user_guilds_uncached(access_token: str) -> list[dict[str, Any]]:
max_attempts = 3
async with aiohttp.ClientSession() as session:
for attempt in range(1, max_attempts + 1):
async with session.get(
"https://discord.com/api/users/@me/guilds",
headers={"Authorization": f"Bearer {access_token}"},
) as resp:
if resp.status != 200:
raise HTTPException(
status_code=403,
detail="Invalid or expired Discord access token.",
)
if resp.status == 200:
data = await resp.json()
return data if isinstance(data, list) else []
if resp.status == 429 and attempt < max_attempts:
retry_after = 1.0
try:
body = await resp.json()
retry_after = float(body.get("retry_after", 1))
except Exception:
retry_after = float(resp.headers.get("Retry-After", "1") or 1)
await asyncio.sleep(min(max(retry_after, 0.3), 5.0))
continue
raise _discord_auth_error(resp.status)
raise _discord_auth_error(429)
async def verify_discord_token(access_token: str) -> dict[str, Any]:
key = _token_key(access_token)
cached = _user_cache.get(key)
if cached and cached[0] > time.monotonic():
return cached[1]
async with aiohttp.ClientSession() as session:
async with session.get(
"https://discord.com/api/users/@me",
headers={"Authorization": f"Bearer {access_token}"},
) as resp:
if resp.status != 200:
raise HTTPException(
status_code=403,
detail="Invalid or expired Discord access token.",
)
return await resp.json()
raise _discord_auth_error(resp.status)
user = await resp.json()
_user_cache[key] = (time.monotonic() + _USER_CACHE_TTL, user)
return user
async def user_can_manage_guild(access_token: str, guild_id: int) -> bool:

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.axiom import Axiom
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: "Axiom" = Depends(get_bot)):
# Calculate DB size and shard info
total_size: float = 0.0
db_count = 0
@@ -87,7 +87,16 @@ async def get_admin_stats(bot: "zyrox" = Depends(get_bot)):
AdminNodeStatus(
name="Auth Sockets",
status="Healthy",
load=f"Shard: {bot.shard_count} | Latency: {round(bot.latency * 1000)}ms",
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"
)
]

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,26 +19,33 @@ from utils.config import *
if TYPE_CHECKING:
from core.zyrox import zyrox
from core.axiom import Axiom
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: "Axiom" = Depends(get_bot)):
"""
Returns the live status of the bot.
"""
shard_ids = list(bot.shards.keys()) if bot.shards else ([0] if bot.shard_count else [])
shard_latencies = [
{"id": sid, "latency_ms": round(lat * 1000, 2)}
for sid, lat in (bot.latencies or [])
]
return BotStatus(
user=str(bot.user),
id=str(bot.user.id) if bot.user else None,
latency=bot.latency * 1000,
guild_count=len(bot.guilds),
user_count=sum(g.member_count or 0 for g in bot.guilds),
shards=bot.shard_count
shards=bot.shard_count,
shard_ids=shard_ids,
shard_latencies=shard_latencies,
)
@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: "Axiom" = Depends(get_bot)):
"""
Get general information about the Discord bot.
"""

View File

@@ -1,23 +1,23 @@
# ╔══════════════════════════════════════════════════════════════════╗
# ║ ║
# ║ ░█▀▀░█▀█░█▀▄░█▀▀░█░█ ░█▀▄░█▀▀░█░█░█▀▀
# ║ ░█░░░█░█░█░█░█▀▀░▄▀▄ ░█░█░█▀▀░▀▄▀░▀▀█
# ║ ░▀▀▀░▀▀▀░▀▀░░▀▀▀░▀░▀ ░▀▀░░▀▀▀░░▀░░▀▀▀
# ║ +-+-+-+-+-+-+-+-+
# ║ |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
from api.discord_auth import require_discord_session, get_manageable_guild_ids
from api.discord_auth import get_manageable_guild_ids, get_discord_headers
from api.db_manager import db_manager
from api.schemas import (
GuildSummary, GuildDetails, PrefixConfig, AutomodConfig,
GuildSummary, GuildDetails, PrefixConfig, AutomodConfig, AutomodEventConfig,
TicketConfig, LevelingConfig, LoggingConfig, TicketEmbed,
TicketCategory, LevelingEmbedStyle, PrefixUpdate,
AutomodUpdate, LevelingUpdate, LoggingUpdate, TicketUpdate,
@@ -30,24 +30,39 @@ from api.schemas import (
RRConfig, RRUpdate, ReactionRoleEntry,
InviteStat, InvitesLeaderboard
)
from utils.automod_settings import (
EVENT_ID_TO_DB,
THRESHOLD_META,
MAX_IGNORED,
NSFW_KEYWORDS,
normalize_event_id,
normalize_punishment,
ensure_thresholds_table,
get_all_thresholds,
set_thresholds,
)
from typing import TYPE_CHECKING, List, Optional
import math
import aiosqlite
import json
import os
import discord
if TYPE_CHECKING:
from core.zyrox import zyrox
from core.axiom import Axiom
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: "Axiom" = Depends(get_bot)):
"""
Lists guilds the bot is in, filtered to those the caller can manage on Discord.
Session is already verified by middleware — only fetch manageable guild IDs here.
"""
token, _ = await require_discord_session(request)
token, _ = get_discord_headers(request)
if not token:
raise HTTPException(status_code=403, detail="X-Discord-Access-Token header is required.")
manageable_ids = await get_manageable_guild_ids(token)
guilds_list = []
@@ -64,7 +79,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: "Axiom" = Depends(get_bot)):
"""
Returns detailed info for a specific guild by its ID.
"""
@@ -87,7 +102,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 +116,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,79 +132,265 @@ 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')
# Check enabled status
db = await db_manager.get_connection(db_path('automod.db'))
await ensure_thresholds_table(db)
cursor = await db.execute("SELECT enabled FROM automod WHERE guild_id = ?", (guild_id,))
enabled_row = await cursor.fetchone()
enabled = bool(enabled_row[0]) if enabled_row else False
# Get punishments
cursor = await db.execute("SELECT event, punishment FROM automod_punishments WHERE guild_id = ?", (guild_id,))
punishments = {row[0]: row[1] for row in await cursor.fetchall()}
cursor = await db.execute(
"SELECT event, punishment FROM automod_punishments WHERE guild_id = ?",
(guild_id,),
)
raw_punishments = {row[0]: row[1] for row in await cursor.fetchall()}
# Get ignored items
cursor = await db.execute("SELECT type, id FROM automod_ignored WHERE guild_id = ?", (guild_id,))
events: dict[str, AutomodEventConfig] = {}
punishments_out: dict[str, str] = {}
for event_id, db_name in EVENT_ID_TO_DB.items():
present = db_name in raw_punishments
pun = raw_punishments.get(db_name)
if event_id == "anti_nsfw_link":
events[event_id] = AutomodEventConfig(
enabled=present,
punishment="block_message",
readonly_punishment=True,
)
if present:
punishments_out[event_id] = "block_message"
else:
norm = normalize_punishment(pun) if present else None
events[event_id] = AutomodEventConfig(
enabled=present,
punishment=norm or ("Mute" if present else None),
readonly_punishment=False,
)
if present and norm:
punishments_out[event_id] = norm
cursor = await db.execute(
"SELECT type, id FROM automod_ignored WHERE guild_id = ?", (guild_id,)
)
ignored_items = await cursor.fetchall()
ignored_roles = [row[1] for row in ignored_items if row[0] == 'role']
ignored_channels = [row[1] for row in ignored_items if row[0] == 'channel']
ignored_roles = [row[1] for row in ignored_items if row[0] == "role"]
ignored_channels = [row[1] for row in ignored_items if row[0] == "channel"]
# Get logging channel
cursor = await db.execute("SELECT log_channel FROM automod_logging WHERE guild_id = ?", (guild_id,))
cursor = await db.execute(
"SELECT log_channel FROM automod_logging WHERE guild_id = ?", (guild_id,)
)
logging_row = await cursor.fetchone()
logging_channel = logging_row[0] if logging_row else None
thresholds = await get_all_thresholds(guild_id)
return AutomodConfig(
guild_id=guild_id,
enabled=enabled,
punishments=punishments,
punishments=punishments_out,
events=events,
thresholds=thresholds,
threshold_meta=THRESHOLD_META,
ignored_roles=ignored_roles,
ignored_channels=ignored_channels,
logging_channel=logging_channel
logging_channel=logging_channel,
limits={"max_ignored_roles": MAX_IGNORED, "max_ignored_channels": MAX_IGNORED},
)
async def _sync_nsfw_rule(
bot: "Axiom",
guild_id: int,
*,
enabled: bool,
ignored_roles: list[int],
ignored_channels: list[int],
) -> None:
guild = bot.get_guild(guild_id)
if not guild:
return
existing = None
try:
rules = await guild.fetch_automod_rules()
existing = next((r for r in rules if r.name == "Anti NSFW Links"), None)
except (discord.Forbidden, discord.HTTPException):
return
if not enabled:
if existing:
try:
await existing.delete(reason="Automod NSFW disabled via dashboard")
except (discord.Forbidden, discord.HTTPException):
pass
return
exempt_roles = [discord.Object(i) for i in ignored_roles[:MAX_IGNORED]]
exempt_channels = [discord.Object(i) for i in ignored_channels[:MAX_IGNORED]]
try:
if existing:
await existing.edit(
exempt_roles=exempt_roles,
exempt_channels=exempt_channels,
enabled=True,
reason="Automod NSFW updated via dashboard",
)
else:
await guild.create_automod_rule(
name="Anti NSFW Links",
event_type=discord.AutoModRuleEventType.message_send,
trigger=discord.AutoModTrigger(
type=discord.AutoModRuleTriggerType.keyword,
keyword_filter=NSFW_KEYWORDS,
),
actions=[
discord.AutoModRuleAction(type=discord.AutoModRuleActionType.block_message),
],
enabled=True,
exempt_roles=exempt_roles,
exempt_channels=exempt_channels,
reason="Automod NSFW enabled via dashboard",
)
except (discord.Forbidden, discord.HTTPException) as e:
print(f"Automod NSFW sync error for guild {guild_id}: {e}")
@router.patch("/{guild_id}/automod", summary="Update AutoMod config", description="Partially updates the AutoMod configuration components.")
async def patch_guild_automod(guild_id: int, data: AutomodUpdate):
async def patch_guild_automod(
guild_id: int,
data: AutomodUpdate,
bot: "Axiom" = Depends(get_bot),
):
"""
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'))
await ensure_thresholds_table(db)
if data.enabled is not None:
await db.execute(
"INSERT OR REPLACE INTO automod (guild_id, enabled) VALUES (?, ?)",
(guild_id, 1 if data.enabled else 0)
(guild_id, 1 if data.enabled else 0),
)
if data.punishments is not None:
for event, punishment in data.punishments.items():
# Build canonical enabled events from events{} and/or legacy punishments{}
events_payload = data.events
if events_payload is None and data.punishments is not None:
events_payload = {}
for raw_key, raw_pun in data.punishments.items():
eid = normalize_event_id(raw_key)
if not eid:
continue
if eid == "anti_nsfw_link":
events_payload[eid] = AutomodEventConfig(
enabled=True, punishment="block_message", readonly_punishment=True
)
else:
pun = normalize_punishment(raw_pun) or "Mute"
events_payload[eid] = AutomodEventConfig(enabled=True, punishment=pun)
nsfw_enabled: bool | None = None
if events_payload is not None:
await db.execute(
"INSERT OR REPLACE INTO automod_punishments (guild_id, event, punishment) VALUES (?, ?, ?)",
(guild_id, event, punishment)
"DELETE FROM automod_punishments WHERE guild_id = ?", (guild_id,)
)
for raw_id, cfg in events_payload.items():
eid = normalize_event_id(raw_id)
if not eid or not cfg.enabled:
if eid == "anti_nsfw_link":
nsfw_enabled = False
continue
db_name = EVENT_ID_TO_DB[eid]
if eid == "anti_nsfw_link":
await db.execute(
"INSERT INTO automod_punishments (guild_id, event, punishment) VALUES (?, ?, ?)",
(guild_id, db_name, "Block message"),
)
nsfw_enabled = True
else:
pun = normalize_punishment(cfg.punishment) or "Mute"
await db.execute(
"INSERT INTO automod_punishments (guild_id, event, punishment) VALUES (?, ?, ?)",
(guild_id, db_name, pun),
)
# Full-replace: omitted/disabled NSFW must drop the Discord rule
if nsfw_enabled is None:
nsfw_enabled = False
if data.ignored_roles is not None:
await db.execute("DELETE FROM automod_ignored WHERE guild_id = ? AND type = 'role'", (guild_id,))
for role_id in data.ignored_roles:
if data.thresholds is not None:
await set_thresholds(db, guild_id, data.thresholds)
ignored_roles = data.ignored_roles
ignored_channels = data.ignored_channels
if ignored_roles is not None:
ignored_roles = list(dict.fromkeys(ignored_roles))[:MAX_IGNORED]
await db.execute(
"DELETE FROM automod_ignored WHERE guild_id = ? AND type = 'role'",
(guild_id,),
)
for role_id in ignored_roles:
await db.execute(
"INSERT OR REPLACE INTO automod_ignored (guild_id, type, id) VALUES (?, 'role', ?)",
(guild_id, role_id)
(guild_id, role_id),
)
if data.ignored_channels is not None:
await db.execute("DELETE FROM automod_ignored WHERE guild_id = ? AND type = 'channel'", (guild_id,))
for channel_id in data.ignored_channels:
if ignored_channels is not None:
ignored_channels = list(dict.fromkeys(ignored_channels))[:MAX_IGNORED]
await db.execute(
"DELETE FROM automod_ignored WHERE guild_id = ? AND type = 'channel'",
(guild_id,),
)
for channel_id in ignored_channels:
await db.execute(
"INSERT OR REPLACE INTO automod_ignored (guild_id, type, id) VALUES (?, 'channel', ?)",
(guild_id, channel_id)
(guild_id, channel_id),
)
if data.logging_channel is not None:
if data.clear_logging:
await db.execute(
"DELETE FROM automod_logging WHERE guild_id = ?", (guild_id,)
)
elif data.logging_channel is not None:
if data.logging_channel == 0:
await db.execute(
"DELETE FROM automod_logging WHERE guild_id = ?", (guild_id,)
)
else:
await db.execute(
"INSERT OR REPLACE INTO automod_logging (guild_id, log_channel) VALUES (?, ?)",
(guild_id, data.logging_channel)
(guild_id, data.logging_channel),
)
await db.commit()
# Resolve current ignore lists for NSFW sync if not in this payload
if ignored_roles is None or ignored_channels is None:
cursor = await db.execute(
"SELECT type, id FROM automod_ignored WHERE guild_id = ?", (guild_id,)
)
items = await cursor.fetchall()
if ignored_roles is None:
ignored_roles = [r[1] for r in items if r[0] == "role"]
if ignored_channels is None:
ignored_channels = [r[1] for r in items if r[0] == "channel"]
if nsfw_enabled is None and (data.ignored_roles is not None or data.ignored_channels is not None):
# Keep Discord rule exempts in sync when ignores change
cursor = await db.execute(
"SELECT 1 FROM automod_punishments WHERE guild_id = ? AND event = ?",
(guild_id, EVENT_ID_TO_DB["anti_nsfw_link"]),
)
nsfw_enabled = bool(await cursor.fetchone())
if nsfw_enabled is not None:
await _sync_nsfw_rule(
bot,
guild_id,
enabled=nsfw_enabled,
ignored_roles=ignored_roles or [],
ignored_channels=ignored_channels or [],
)
return {"status": "success", "guild_id": guild_id}
@router.get("/{guild_id}/tickets", response_model=TicketConfig, summary="Get Ticket config", description="Retrieves the support ticket system setup, categories, and staff roles.")
@@ -197,7 +398,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 +464,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 +523,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 +558,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 +601,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 +633,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 +669,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 +691,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 +739,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 +765,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 +790,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 +805,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 +818,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 +829,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 +863,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 +902,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 +931,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 +967,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 +976,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 +984,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 +1021,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: "Axiom" = Depends(get_bot)):
import aiosqlite
def to_id(val):
@@ -903,7 +1104,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 +1126,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 +1151,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 +1176,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 +1201,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: "Axiom" = Depends(get_bot)):
"""
Retrieves the logging configuration for a specific guild.
"""
@@ -1013,7 +1214,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 +1245,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: "Axiom" = Depends(get_bot)):
"""
Updates the logging configuration for a specific guild.
"""
@@ -1076,8 +1277,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: "Axiom" = 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 +1317,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: "Axiom" = Depends(get_bot)):
guild = bot.get_guild(guild_id)
if not guild:
raise HTTPException(status_code=404, detail="Guild not found")
@@ -1136,7 +1337,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: "Axiom" = Depends(get_bot)):
guild = bot.get_guild(guild_id)
if not guild:
raise HTTPException(status_code=404, detail="Guild not found")
@@ -1164,7 +1365,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 +1386,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 +1410,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 +1447,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 +1465,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 +1488,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,19 +1,18 @@
# ╔══════════════════════════════════════════════════════════════════╗
# ║ ║
# ║ ░█▀▀░█▀█░█▀▄░█▀▀░█░█ ░█▀▄░█▀▀░█░█░█▀▀
# ║ ░█░░░█░█░█░█░█▀▀░▄▀▄ ░█░█░█▀▀░▀▄▀░▀▀█
# ║ ░▀▀▀░▀▀▀░▀▀░░▀▀▀░▀░▀ ░▀▀░░▀▀▀░░▀░░▀▀▀
# ║ +-+-+-+-+-+-+-+-+
# ║ |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 pydantic import BaseModel, HttpUrl
from typing import Dict, List, Optional
from typing import Any, Dict, List, Optional
# --- Bot Schemas ---
@@ -32,6 +31,8 @@ class BotStatus(BaseModel):
guild_count: int
user_count: int
shards: Optional[int]
shard_ids: Optional[List[int]] = None
shard_latencies: Optional[List[Dict[str, Any]]] = None
# --- Guild Schemas ---
@@ -68,13 +69,24 @@ class PrefixConfig(BaseModel):
guild_id: int
prefix: str
class AutomodEventConfig(BaseModel):
enabled: bool = False
punishment: Optional[str] = None # Mute | Kick | Ban | block_message (NSFW)
readonly_punishment: bool = False
class AutomodConfig(BaseModel):
guild_id: int
enabled: bool
punishments: Dict[str, str]
ignored_roles: List[int]
ignored_channels: List[int]
logging_channel: Optional[int]
# Legacy flat map (API event ids or bot names) — kept for older clients
punishments: Dict[str, str] = {}
events: Dict[str, AutomodEventConfig] = {}
thresholds: Dict[str, Dict[str, float]] = {}
threshold_meta: Dict[str, List[Dict[str, Any]]] = {}
ignored_roles: List[int] = []
ignored_channels: List[int] = []
logging_channel: Optional[int] = None
limits: Dict[str, int] = {"max_ignored_roles": 10, "max_ignored_channels": 10}
class TicketCategory(BaseModel):
name: str
@@ -300,10 +312,14 @@ class TicketUpdate(BaseModel):
class AutomodUpdate(BaseModel):
enabled: Optional[bool] = None
punishments: Optional[Dict[str, str]] = None
punishments: Optional[Dict[str, str]] = None # legacy
events: Optional[Dict[str, AutomodEventConfig]] = None
thresholds: Optional[Dict[str, Dict[str, float]]] = None
ignored_roles: Optional[List[int]] = None
ignored_channels: Optional[List[int]] = None
# Use a sentinel-friendly optional: omit = no change; null = clear logging
logging_channel: Optional[int] = None
clear_logging: Optional[bool] = None
class LevelingUpdate(BaseModel):
enabled: Optional[bool] = None

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 Axiom Bot Dashboard.
The bot instance will be attached to app.state.bot in Axiom.py at runtime.
"""
app = FastAPI(
title=f"{BRAND_NAME} Bot API",

BIN
bot/assets/logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 188 KiB

3
bot/assets/logo.svg Normal file

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 500 KiB

View File

@@ -1,21 +1,22 @@
# ╔══════════════════════════════════════════════════════════════════╗
# ║ ║
# ║ ░█▀▀░█▀█░█▀▄░█▀▀░█░█ ░█▀▄░█▀▀░█░█░█▀▀
# ║ ░█░░░█░█░█░█░█▀▀░▄▀▄ ░█░█░█▀▀░▀▄▀░▀▀█
# ║ ░▀▀▀░▀▀▀░▀▀░░▀▀▀░▀░▀ ░▀▀░░▀▀▀░░▀░░▀▀▀
# ║ +-+-+-+-+-+-+-+-+
# ║ |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 __future__ import annotations
from core import zyrox
from colorama import Fore, Style, init
from colorama import Fore, Style
from core import Axiom
from utils.config import BotName
from .commands.help import Help
from .commands.general import General
@@ -25,7 +26,7 @@ from .commands.welcome import Welcomer
from .commands.fun import Fun
from .commands.Games import Games
from .commands.extra import Extra
from .commands.owner import Owner
from .commands.owner import Owner, Badges
from .commands.voice import Voice
from .commands.afk import afk
from .commands.ignore import Ignore
@@ -39,8 +40,6 @@ from .commands.blacklist import Blacklist
from .commands.block import Block
from .commands.nightmode import Nightmode
from .commands.tracking import Tracking
from .commands.owner import Badges
#from .commands.map import Map
from .commands.autoresponder import AutoResponder
from .commands.customrole import Customrole
from .commands.autorole import AutoRole
@@ -83,9 +82,7 @@ from .commands.Birthday import Birthdays
from .commands.nitro import Nitro
from .commands.image import ImageCommands
from .commands.youtube import Youtube
#____________ Events _____________
#from .events.autoblacklist import AutoBlacklist
from .events.Errors import Errors
from .events.on_guild import Guild
from .events.autorole import Autorole2
@@ -94,43 +91,37 @@ from .events.greet2 import greet
from .events.mention import Mention
from .events.react import React
from .events.autoreact import AutoReactListener
#from .events.topgg import TopGG
from .events.ai import AIResponses
from .events.stickymessage import StickyMessageListener
########-------HELP-------########
from .zyrox.antinuke import _antinuke
from .zyrox.extra import _extra
from .zyrox.general import _general
from .zyrox.automod import _automod
from .zyrox.moderation import _moderation
#from .zyrox.inviteTracker import _inviteTracker
from .zyrox.music import _music
from .zyrox.fun import _fun
from .zyrox.games import _games
from .zyrox.ignore import _ignore
from .zyrox.server import _server
from .zyrox.voice import _voice
from .zyrox.welcome import _welcome
from .zyrox.giveaway import _giveaway
from .zyrox.ticket import _ticket
#from .axon.vanityroles import Vanityroles69999
from .zyrox.logging import _logging
from .zyrox.vanity import _vanity
from .zyrox.inviteTracker import inviteTracker
from .zyrox.counting import _Counting
from .zyrox.j2c import _J2C
from .zyrox.ai import _ai
from .zyrox.booster import __boost
from .zyrox.leveling import _leveling
from .zyrox.sticky import _sticky
from .zyrox.verify import _verify
from .zyrox.encryption import _encrypt
from .zyrox.mc import _mc
from .zyrox.joindm import _joindm
from .zyrox.birth import _birth
#########ANTINUKE#########
from .axiom.antinuke import _antinuke
from .axiom.extra import _extra
from .axiom.general import _general
from .axiom.automod import _automod
from .axiom.moderation import _moderation
from .axiom.music import _music
from .axiom.fun import _fun
from .axiom.games import _games
from .axiom.ignore import _ignore
from .axiom.server import _server
from .axiom.voice import _voice
from .axiom.welcome import _welcome
from .axiom.giveaway import _giveaway
from .axiom.ticket import _ticket
from .axiom.logging import _logging
from .axiom.vanity import _vanity
from .axiom.inviteTracker import inviteTracker
from .axiom.counting import _Counting
from .axiom.j2c import _J2C
from .axiom.ai import _ai
from .axiom.booster import __boost
from .axiom.leveling import _leveling
from .axiom.sticky import _sticky
from .axiom.verify import _verify
from .axiom.encryption import _encrypt
from .axiom.mc import _mc
from .axiom.joindm import _joindm
from .axiom.birth import _birth
from .antinuke.anti_member_update import AntiMemberUpdate
from .antinuke.antiban import AntiBan
@@ -150,15 +141,6 @@ from .antinuke.antiwebhook import AntiWebhookUpdate
from .antinuke.antiwebhookcr import AntiWebhookCreate
from .antinuke.antiwebhookdl import AntiWebhookDelete
#Extra Optional Events
#from .antinuke.antiemocr import AntiEmojiCreate
#from .antinuke.antiemodl import AntiEmojiDelete
#from .antinuke.antiemoup import AntiEmojiUpdate
#from .antinuke.antisticker import AntiSticker
#from .antinuke.antiunban import AntiUnban
############ AUTOMOD ############
from .automod.antispam import AntiSpam
from .automod.anticaps import AntiCaps
from .automod.antilink import AntiLink
@@ -166,7 +148,6 @@ from .automod.anti_invites import AntiInvite
from .automod.anti_mass_mention import AntiMassMention
from .automod.anti_emoji_spam import AntiEmojiSpam
from .moderation.ban import Ban
from .moderation.unban import Unban
from .moderation.timeout import Mute
@@ -180,197 +161,49 @@ from .moderation.warn import Warn
from .moderation.role import Role
from .moderation.message import Message
from .moderation.moderation import Moderation
from .moderation.mod_hub import ModHub
from .moderation.topcheck import TopCheck
from .moderation.snipe import Snipe
from utils.config import BotName
async def setup(bot: zyrox):
cogs_to_load = [
Help, General, Moderation, Automod, Welcomer, Fun, Games, Extra,
Voice, Owner, Customrole, afk, Embed, Media, Ignore, TicketCog, Logging,
Invcrole, Steal, Timer,
Blacklist, Block, Nightmode, Badges, Antinuke, Whitelist,
Unwhitelist, Extraowner, Blackjack, Slots, Guild, Errors, Autorole2, Autorole, greet, AutoResponder,
Mention, AutoRole, React, AntiMemberUpdate, AntiBan, AntiBotAdd,
AntiChannelCreate, AntiChannelDelete, AntiChannelUpdate, AntiEveryone, AntiGuildUpdate,
AntiIntegration, AntiKick, AntiPrune, AntiRoleCreate, AntiRoleDelete,
AntiRoleUpdate, AntiWebhookUpdate, AntiWebhookCreate,
AntiWebhookDelete, AntiSpam, AntiCaps, AntiLink, AntiInvite, AntiMassMention, Stats, Status, NoPrefix, FilterCog, AutoReaction, AutoReactListener, Ban, Unban, Mute, Unmute, Lock, Unlock, Hide, Unhide, Kick, Warn, Role, Message, Moderation, TopCheck, Snipe, Global, QR, VanityRoles, ReactionRoles, Messages, TranslateCog, FastGreet, Jail, inviteTracker,Counting,AI
]
# Load order preserved from legacy manual registration.
COG_CLASSES: tuple[type, ...] = (
Help, General, Music, Automod, Welcomer, Fun, Tracking, Games, Extra,
Voice, Owner, Customrole, afk, Embed, Media, Ignore, Invcrole, Giveaway,
Steal, Booster, Timer, Blacklist, Block, Nightmode, Badges, Antinuke,
Whitelist, Unwhitelist, Extraowner, Slots, Blackjack, Stats, Emergency,
Status, NoPrefix, FilterCog, Global, TicketCog, Logging, QR, VanityRoles,
ReactionRoles, Messages, TranslateCog, FastGreet, Jail, JoinToCreate, AI,
StaffDMCog, Leveling, StickyMessage, Verification, Minecraft, encryption,
calculator, joindm, Birthdays, Nitro, ImageCommands, Youtube,
_antinuke, _extra, _general, _automod, _moderation, _music, _fun, _games,
_ignore, _server, _voice, _welcome, _giveaway, _ticket, _logging, _vanity,
inviteTracker, Counting, _Counting, _J2C, _ai, __boost, _leveling, _sticky,
_verify, _encrypt, _mc, _joindm, _birth,
Guild, Errors, Autorole2, Autorole, greet, AutoResponder, Mention, AutoRole,
React, AutoReaction, AutoReactListener, NotifCommands, StickyMessageListener,
AIResponses,
AntiMemberUpdate, AntiBan, AntiBotAdd, AntiChannelCreate, AntiChannelDelete,
AntiChannelUpdate, AntiEveryone, AntiGuildUpdate, AntiIntegration, AntiKick,
AntiPrune, AntiRoleCreate, AntiRoleDelete, AntiRoleUpdate, AntiWebhookUpdate,
AntiWebhookCreate, AntiWebhookDelete,
AntiSpam, AntiCaps, AntiInvite, AntiLink, AntiMassMention, AntiEmojiSpam,
Ban, Unban, Mute, Unmute, Lock, Unlock, Hide, Unhide, Kick, Warn, Role,
Message, Moderation, ModHub, TopCheck, Snipe,
)
await bot.add_cog(Help(bot))
await bot.add_cog(General(bot))
await bot.add_cog(Music(bot))
await bot.add_cog(Automod(bot))
await bot.add_cog(Welcomer(bot))
await bot.add_cog(Fun(bot))
await bot.add_cog(Tracking(bot))
await bot.add_cog(Games(bot))
await bot.add_cog(Extra(bot))
await bot.add_cog(Voice(bot))
await bot.add_cog(Owner(bot))
await bot.add_cog(Customrole(bot))
await bot.add_cog(afk(bot))
await bot.add_cog(Embed(bot))
await bot.add_cog(Media(bot))
await bot.add_cog(Ignore(bot))
await bot.add_cog(Invcrole(bot))
await bot.add_cog(Giveaway(bot))
await bot.add_cog(Steal(bot))
await bot.add_cog(Booster(bot))
await bot.add_cog(Timer(bot))
await bot.add_cog(Blacklist(bot))
await bot.add_cog(Block(bot))
await bot.add_cog(Nightmode(bot))
await bot.add_cog(Badges(bot))
await bot.add_cog(Antinuke(bot))
await bot.add_cog(Whitelist(bot))
await bot.add_cog(Unwhitelist(bot))
await bot.add_cog(Extraowner(bot))
await bot.add_cog(Slots(bot))
await bot.add_cog(Blackjack(bot))
await bot.add_cog(Stats(bot))
await bot.add_cog(Emergency(bot))
await bot.add_cog(Status(bot))
await bot.add_cog(NoPrefix(bot))
await bot.add_cog(FilterCog(bot))
await bot.add_cog(Global(bot))
# await bot.add_cog(Map(bot))
await bot.add_cog(TicketCog(bot))
await bot.add_cog(Logging(bot))
await bot.add_cog(QR(bot))
await bot.add_cog(VanityRoles(bot))
await bot.add_cog(ReactionRoles(bot))
await bot.add_cog(Messages(bot))
await bot.add_cog(TranslateCog(bot))
await bot.add_cog(FastGreet(bot))
await bot.add_cog(Jail(bot))
await bot.add_cog(JoinToCreate(bot))
await bot.add_cog(AI(bot))
await bot.add_cog(StaffDMCog(bot))
await bot.add_cog(Leveling(bot))
await bot.add_cog(StickyMessage(bot))
await bot.add_cog(Verification(bot))
await bot.add_cog(Minecraft(bot))
await bot.add_cog(encryption(bot))
await bot.add_cog(calculator(bot))
await bot.add_cog(joindm(bot))
await bot.add_cog(Birthdays(bot))
await bot.add_cog(Nitro(bot))
await bot.add_cog(ImageCommands(bot))
await bot.add_cog(Youtube(bot))
async def setup(bot: Axiom) -> None:
loaded = 0
for cog_cls in COG_CLASSES:
try:
await bot.add_cog(cog_cls(bot))
loaded += 1
print(Fore.GREEN + Style.BRIGHT + f"Loaded cog: {cog_cls.__name__}")
except Exception as e:
print(
Fore.RED
+ Style.BRIGHT
+ f"Failed cog {getattr(cog_cls, '__name__', cog_cls)}: {type(e).__name__}: {e}"
)
await bot.add_cog(_antinuke(bot))
await bot.add_cog(_extra(bot))
await bot.add_cog(_general(bot))
await bot.add_cog(_automod(bot))
await bot.add_cog(_moderation(bot))
await bot.add_cog(_music(bot))
await bot.add_cog(_fun(bot))
await bot.add_cog(_games(bot))
await bot.add_cog(_ignore(bot))
await bot.add_cog(_server(bot))
await bot.add_cog(_voice(bot))
await bot.add_cog(_welcome(bot))
await bot.add_cog(_giveaway(bot))
await bot.add_cog(_ticket(bot))
await bot.add_cog(_logging(bot))
await bot.add_cog(_vanity(bot))
await bot.add_cog(inviteTracker(bot))
await bot.add_cog(Counting(bot))
await bot.add_cog(_Counting(bot))
await bot.add_cog(_J2C(bot))
await bot.add_cog(_ai(bot))
await bot.add_cog(__boost(bot))
await bot.add_cog(_leveling(bot))
await bot.add_cog(_sticky(bot))
await bot.add_cog(_verify(bot))
await bot.add_cog(_encrypt(bot))
await bot.add_cog(_mc(bot))
await bot.add_cog(_joindm(bot))
await bot.add_cog(_birth(bot))
#await bot.add_cog(AutoBlacklist(bot))
await bot.add_cog(Guild(bot))
await bot.add_cog(Errors(bot))
await bot.add_cog(Autorole2(bot))
await bot.add_cog(Autorole(bot))
await bot.add_cog(greet(bot))
await bot.add_cog(AutoResponder(bot))
await bot.add_cog(Mention(bot))
await bot.add_cog(AutoRole(bot))
await bot.add_cog(React(bot))
await bot.add_cog(AutoReaction(bot))
await bot.add_cog(AutoReactListener(bot))
await bot.add_cog(NotifCommands(bot))
await bot.add_cog(StickyMessageListener(bot))
await bot.add_cog(AIResponses(bot))
await bot.add_cog(AntiMemberUpdate(bot))
await bot.add_cog(AntiBan(bot))
await bot.add_cog(AntiBotAdd(bot))
await bot.add_cog(AntiChannelCreate(bot))
await bot.add_cog(AntiChannelDelete(bot))
await bot.add_cog(AntiChannelUpdate(bot))
await bot.add_cog(AntiEveryone(bot))
await bot.add_cog(AntiGuildUpdate(bot))
await bot.add_cog(AntiIntegration(bot))
await bot.add_cog(AntiKick(bot))
await bot.add_cog(AntiPrune(bot))
await bot.add_cog(AntiRoleCreate(bot))
await bot.add_cog(AntiRoleDelete(bot))
await bot.add_cog(AntiRoleUpdate(bot))
await bot.add_cog(AntiWebhookUpdate(bot))
await bot.add_cog(AntiWebhookCreate(bot))
await bot.add_cog(AntiWebhookDelete(bot))
#Extra Optional Events
#await bot.add_cog(AntiEmojiCreate(bot))
#await bot.add_cog(AntiEmojiDelete(bot))
#await bot.add_cog(AntiEmojiUpdate(bot))
#await bot.add_cog(AntiSticker(bot))
#await bot.add_cog(AntiUnban(bot))
await bot.add_cog(AntiSpam(bot))
await bot.add_cog(AntiCaps(bot))
await bot.add_cog(AntiInvite(bot))
await bot.add_cog(AntiLink(bot))
await bot.add_cog(AntiMassMention(bot))
await bot.add_cog(AntiEmojiSpam(bot))
await bot.add_cog(Ban(bot))
await bot.add_cog(Unban(bot))
await bot.add_cog(Mute(bot))
await bot.add_cog(Unmute(bot))
await bot.add_cog(Lock(bot))
await bot.add_cog(Unlock(bot))
await bot.add_cog(Hide(bot))
await bot.add_cog(Unhide(bot))
await bot.add_cog(Kick(bot))
await bot.add_cog(Warn(bot))
await bot.add_cog(Role(bot))
await bot.add_cog(Message(bot))
await bot.add_cog(Moderation(bot))
await bot.add_cog(TopCheck(bot))
await bot.add_cog(Snipe(bot))
for cog in cogs_to_load:
print(Fore.RED + Style.BRIGHT + f"Loaded cog: {cog.__name__}")
print(Fore.RED + Style.BRIGHT + f"All {BotName} Cogs loaded successfully.")
print(Fore.GREEN + Style.BRIGHT + f"Loaded {loaded}/{len(COG_CLASSES)} {BotName} cogs.")

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
import discord
from discord.ext import commands
@@ -61,7 +61,7 @@ class AntiIntegration(commands.Cog):
return True
async def is_blacklisted_guild(self, guild_id):
async with aiosqlite.connect('db/block.db') as block_db:
async with aiosqlite.connect(db_path('block.db')) as block_db:
cursor = await block_db.execute("SELECT 1 FROM guild_blacklist WHERE guild_id = ?", (str(guild_id),))
return await cursor.fetchone() is not None
@@ -70,7 +70,7 @@ class AntiIntegration(commands.Cog):
if await self.is_blacklisted_guild(guild.id):
return
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:
antinuke_status = await cursor.fetchone()
@@ -89,7 +89,7 @@ class AntiIntegration(commands.Cog):
if executor.id in {guild.owner_id, self.bot.user.id}:
return
async with aiosqlite.connect('db/anti.db') as db:
async with aiosqlite.connect(db_path('anti.db')) as db:
async with db.execute("SELECT owner_id FROM extraowners WHERE guild_id = ? AND owner_id = ?",
(guild.id, executor.id)) as cursor:
extraowner_status = await cursor.fetchone()

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
import discord
from discord.ext import commands
@@ -26,7 +26,7 @@ class AntiMemberUpdate(commands.Cog):
self.cooldowns = {}
async def is_blacklisted_guild(self, guild_id):
async with aiosqlite.connect('db/block.db') as block_db:
async with aiosqlite.connect(db_path('block.db')) as block_db:
cursor = await block_db.execute("SELECT 1 FROM guild_blacklist WHERE guild_id = ?", (str(guild_id),))
return await cursor.fetchone() is not None
@@ -71,7 +71,7 @@ class AntiMemberUpdate(commands.Cog):
if await self.is_blacklisted_guild(guild.id):
return
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:
antinuke_status = await cursor.fetchone()
if not antinuke_status or not antinuke_status[0]:
@@ -88,7 +88,7 @@ class AntiMemberUpdate(commands.Cog):
if executor.id in {guild.owner_id, self.bot.user.id}:
return
async with aiosqlite.connect('db/anti.db') as db:
async with aiosqlite.connect(db_path('anti.db')) as db:
async with db.execute("SELECT owner_id FROM extraowners WHERE guild_id = ? AND owner_id = ?",
(guild.id, executor.id)) as cursor:
extra_owner_status = await cursor.fetchone()

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
import discord
from discord.ext import commands
@@ -59,7 +59,7 @@ class AntiBan(commands.Cog):
@commands.Cog.listener()
async def on_member_ban(self, guild, user):
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:
antinuke_status = await cursor.fetchone()
if not antinuke_status or not antinuke_status[0]:

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
import discord
from discord.ext import commands
@@ -63,7 +63,7 @@ class AntiBotAdd(commands.Cog):
return
guild = member.guild
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:
antinuke_status = await cursor.fetchone()

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
import discord
from discord.ext import commands
@@ -89,7 +89,7 @@ class AntiChannelCreate(commands.Cog):
async def on_guild_channel_create(self, channel):
guild = channel.guild
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:
antinuke_status = await cursor.fetchone()
if not antinuke_status or not antinuke_status[0]:

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
import discord
from discord.ext import commands
@@ -60,7 +60,7 @@ class AntiChannelDelete(commands.Cog):
@commands.Cog.listener()
async def on_guild_channel_delete(self, channel):
guild = channel.guild
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:
antinuke_status = await cursor.fetchone()
if not antinuke_status or not antinuke_status[0]:

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
import discord
from discord.ext import commands
@@ -60,7 +60,7 @@ class AntiChannelUpdate(commands.Cog):
@commands.Cog.listener()
async def on_guild_channel_update(self, before, after):
guild = before.guild
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:
antinuke_status = await cursor.fetchone()
if not antinuke_status or not antinuke_status[0]:

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
import discord
from discord.ext import commands
@@ -44,7 +44,7 @@ class AntiEveryone(commands.Cog):
guild = message.guild
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:
antinuke_status = await cursor.fetchone()

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
import discord
from discord.ext import commands
@@ -61,7 +61,7 @@ class AntiGuildUpdate(commands.Cog):
return True
async def is_blacklisted_guild(self, guild_id):
async with aiosqlite.connect('db/block.db') as block_db:
async with aiosqlite.connect(db_path('block.db')) as block_db:
cursor = await block_db.execute("SELECT 1 FROM guild_blacklist WHERE guild_id = ?", (str(guild_id),))
return await cursor.fetchone() is not None
@@ -71,7 +71,7 @@ class AntiGuildUpdate(commands.Cog):
if await self.is_blacklisted_guild(guild.id):
return
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:
antinuke_status = await cursor.fetchone()
@@ -93,7 +93,7 @@ class AntiGuildUpdate(commands.Cog):
if executor.id in {guild.owner_id, self.bot.user.id}:
return
async with aiosqlite.connect('db/anti.db') as db:
async with aiosqlite.connect(db_path('anti.db')) as db:
async with db.execute("SELECT serverup FROM whitelisted_users WHERE guild_id = ? AND user_id = ?",
(guild.id, executor.id)) as cursor:
whitelist_status = await cursor.fetchone()

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
import discord
from discord.ext import commands
@@ -26,7 +26,7 @@ class AntiKick(commands.Cog):
self.cooldowns = {}
async def is_blacklisted_guild(self, guild_id):
async with aiosqlite.connect('db/block.db') as block_db:
async with aiosqlite.connect(db_path('block.db')) as block_db:
cursor = await block_db.execute("SELECT 1 FROM guild_blacklist WHERE guild_id = ?", (str(guild_id),))
return await cursor.fetchone() is not None
@@ -70,7 +70,7 @@ class AntiKick(commands.Cog):
if await self.is_blacklisted_guild(member.guild.id):
return
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 = ?", (member.guild.id,)) as cursor:
antinuke_status = await cursor.fetchone()
if not antinuke_status or not antinuke_status[0]:
@@ -87,7 +87,7 @@ class AntiKick(commands.Cog):
if executor.id in {member.guild.owner_id, self.bot.user.id}:
return
async with aiosqlite.connect('db/anti.db') as db:
async with aiosqlite.connect(db_path('anti.db')) as db:
async with db.execute("SELECT owner_id FROM extraowners WHERE guild_id = ? AND owner_id = ?",
(member.guild.id, executor.id)) as cursor:
extraowner_status = await cursor.fetchone()

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
import discord
from discord.ext import commands
@@ -42,7 +42,7 @@ class AntiPrune(commands.Cog):
@commands.Cog.listener()
async def on_member_remove(self, member):
guild = member.guild
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:
antinuke_status = await cursor.fetchone()

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
import discord
from discord.ext import commands
@@ -26,7 +26,7 @@ class AntiRoleCreate(commands.Cog):
self.cooldowns = {}
async def is_blacklisted_guild(self, guild_id):
async with aiosqlite.connect('db/block.db') as block_db:
async with aiosqlite.connect(db_path('block.db')) as block_db:
cursor = await block_db.execute("SELECT 1 FROM guild_blacklist WHERE guild_id = ?", (str(guild_id),))
return await cursor.fetchone() is not None
@@ -71,7 +71,7 @@ class AntiRoleCreate(commands.Cog):
if await self.is_blacklisted_guild(guild.id):
return
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:
antinuke_status = await cursor.fetchone()
if not antinuke_status or not antinuke_status[0]:
@@ -89,7 +89,7 @@ class AntiRoleCreate(commands.Cog):
if executor.id in {guild.owner_id, self.bot.user.id}:
return
async with aiosqlite.connect('db/anti.db') as db:
async with aiosqlite.connect(db_path('anti.db')) as db:
async with db.execute("SELECT owner_id FROM extraowners WHERE guild_id = ? AND owner_id = ?",
(guild.id, executor.id)) as cursor:
extra_owner_status = await cursor.fetchone()

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
import discord
from discord.ext import commands
@@ -26,7 +26,7 @@ class AntiRoleDelete(commands.Cog):
self.cooldowns = {}
async def is_blacklisted_guild(self, guild_id):
async with aiosqlite.connect('db/block.db') as block_db:
async with aiosqlite.connect(db_path('block.db')) as block_db:
cursor = await block_db.execute("SELECT 1 FROM guild_blacklist WHERE guild_id = ?", (str(guild_id),))
return await cursor.fetchone() is not None
@@ -71,7 +71,7 @@ class AntiRoleDelete(commands.Cog):
if await self.is_blacklisted_guild(guild.id):
return
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:
antinuke_status = await cursor.fetchone()
if not antinuke_status or not antinuke_status[0]:
@@ -89,7 +89,7 @@ class AntiRoleDelete(commands.Cog):
if executor.id in {guild.owner_id, self.bot.user.id}:
return
async with aiosqlite.connect('db/anti.db') as db:
async with aiosqlite.connect(db_path('anti.db')) as db:
async with db.execute("SELECT owner_id FROM extraowners WHERE guild_id = ? AND owner_id = ?",
(guild.id, executor.id)) as cursor:
extra_owner_status = await cursor.fetchone()

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
import discord
from discord.ext import commands
@@ -26,7 +26,7 @@ class AntiRoleUpdate(commands.Cog):
self.cooldowns = {}
async def is_blacklisted_guild(self, guild_id):
async with aiosqlite.connect('db/block.db') as block_db:
async with aiosqlite.connect(db_path('block.db')) as block_db:
cursor = await block_db.execute("SELECT 1 FROM guild_blacklist WHERE guild_id = ?", (str(guild_id),))
return await cursor.fetchone() is not None
@@ -71,7 +71,7 @@ class AntiRoleUpdate(commands.Cog):
if await self.is_blacklisted_guild(guild.id):
return
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:
antinuke_status = await cursor.fetchone()
if not antinuke_status or not antinuke_status[0]:
@@ -89,7 +89,7 @@ class AntiRoleUpdate(commands.Cog):
if executor.id in {guild.owner_id, self.bot.user.id}:
return
async with aiosqlite.connect('db/anti.db') as db:
async with aiosqlite.connect(db_path('anti.db')) as db:
async with db.execute("SELECT rlup FROM whitelisted_users WHERE guild_id = ? AND user_id = ?",
(guild.id, executor.id)) as cursor:
whitelist_status = await cursor.fetchone()

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
import discord
from discord.ext import commands
@@ -58,7 +58,7 @@ class AntiWebhookUpdate(commands.Cog):
return True
async def is_blacklisted_guild(self, guild_id):
async with aiosqlite.connect('db/block.db') as block_db:
async with aiosqlite.connect(db_path('block.db')) as block_db:
cursor = await block_db.execute("SELECT 1 FROM guild_blacklist WHERE guild_id = ?", (str(guild_id),))
return await cursor.fetchone() is not None
@@ -68,7 +68,7 @@ class AntiWebhookUpdate(commands.Cog):
if await self.is_blacklisted_guild(guild.id):
return
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:
antinuke_status = await cursor.fetchone()
@@ -87,7 +87,7 @@ class AntiWebhookUpdate(commands.Cog):
if executor.id in {guild.owner_id, self.bot.user.id}:
return
async with aiosqlite.connect('db/anti.db') as db:
async with aiosqlite.connect(db_path('anti.db')) as db:
async with db.execute("SELECT mngweb FROM whitelisted_users WHERE guild_id = ? AND user_id = ?",
(guild.id, executor.id)) as cursor:
whitelist_status = await cursor.fetchone()

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
import discord
from discord.ext import commands
@@ -58,7 +58,7 @@ class AntiWebhookCreate(commands.Cog):
return True
async def is_blacklisted_guild(self, guild_id):
async with aiosqlite.connect('db/block.db') as block_db:
async with aiosqlite.connect(db_path('block.db')) as block_db:
cursor = await block_db.execute("SELECT 1 FROM guild_blacklist WHERE guild_id = ?", (str(guild_id),))
return await cursor.fetchone() is not None
@@ -68,7 +68,7 @@ class AntiWebhookCreate(commands.Cog):
if await self.is_blacklisted_guild(guild.id):
return
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:
antinuke_status = await cursor.fetchone()
@@ -87,7 +87,7 @@ class AntiWebhookCreate(commands.Cog):
if executor.id in {guild.owner_id, self.bot.user.id}:
return
async with aiosqlite.connect('db/anti.db') as db:
async with aiosqlite.connect(db_path('anti.db')) as db:
async with db.execute("SELECT mngweb FROM whitelisted_users WHERE guild_id = ? AND user_id = ?",
(guild.id, executor.id)) as cursor:
whitelist_status = await cursor.fetchone()

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
import discord
from discord.ext import commands
@@ -58,7 +58,7 @@ class AntiWebhookDelete(commands.Cog):
return True
async def is_blacklisted_guild(self, guild_id):
async with aiosqlite.connect('db/block.db') as block_db:
async with aiosqlite.connect(db_path('block.db')) as block_db:
cursor = await block_db.execute("SELECT 1 FROM guild_blacklist WHERE guild_id = ?", (str(guild_id),))
return await cursor.fetchone() is not None
@@ -68,7 +68,7 @@ class AntiWebhookDelete(commands.Cog):
if await self.is_blacklisted_guild(guild.id):
return
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:
antinuke_status = await cursor.fetchone()
@@ -87,7 +87,7 @@ class AntiWebhookDelete(commands.Cog):
if executor.id in {guild.owner_id, self.bot.user.id}:
return
async with aiosqlite.connect('db/anti.db') as db:
async with aiosqlite.connect(db_path('anti.db')) as db:
async with db.execute("SELECT mngweb FROM whitelisted_users WHERE guild_id = ? AND user_id = ?",
(guild.id, executor.id)) as cursor:
whitelist_status = await cursor.fetchone()

View File

@@ -1,3 +1,4 @@
from utils.db_paths import db_path
import discord
from discord.ext import commands
import aiosqlite
@@ -29,7 +30,7 @@ class AntiEmojiCreate(commands.Cog):
@commands.Cog.listener()
async def on_guild_emojis_update(self, guild, before, after):
if len(after) > len(before):
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:
antinuke_status = await cursor.fetchone()

View File

@@ -1,3 +1,4 @@
from utils.db_paths import db_path
import discord
from discord.ext import commands
import aiosqlite
@@ -29,7 +30,7 @@ class AntiEmojiDelete(commands.Cog):
@commands.Cog.listener()
async def on_guild_emojis_update(self, guild, before, after):
if len(after) < len(before):
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:
antinuke_status = await cursor.fetchone()

View File

@@ -1,3 +1,4 @@
from utils.db_paths import db_path
import discord
from discord.ext import commands
import aiosqlite
@@ -29,7 +30,7 @@ class AntiEmojiUpdate(commands.Cog):
@commands.Cog.listener()
async def on_guild_emojis_update(self, guild, before, after):
if len(after) == len(before): # An emoji was updated
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:
antinuke_status = await cursor.fetchone()

View File

@@ -1,3 +1,4 @@
from utils.db_paths import db_path
import discord
from discord.ext import commands
from datetime import timedelta, datetime
@@ -34,7 +35,7 @@ class AntiSticker(commands.Cog):
else:
action = discord.AuditLogAction.sticker_update
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:
antinuke_status = await cursor.fetchone()

View File

@@ -1,3 +1,4 @@
from utils.db_paths import db_path
import discord
from discord.ext import commands
import aiosqlite
@@ -26,7 +27,7 @@ class AntiUnban(commands.Cog):
@commands.Cog.listener()
async def on_member_unban(self, guild, user):
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:
antinuke_status = await cursor.fetchone()

View File

@@ -1,16 +1,17 @@
# ╔══════════════════════════════════════════════════════════════════╗
# ║ ║
# ║ ░█▀▀░█▀█░█▀▄░█▀▀░█░█ ░█▀▄░█▀▀░█░█░█▀▀
# ║ ░█░░░█░█░█░█░█▀▀░▄▀▄ ░█░█░█▀▀░▀▄▀░▀▀█
# ║ ░▀▀▀░▀▀▀░▀▀░░▀▀▀░▀░▀ ░▀▀░░▀▀▀░░▀░░▀▀▀
# ║ +-+-+-+-+-+-+-+-+
# ║ |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 utils.automod_settings import get_thresholds
import discord
from utils.emoji import TICK
@@ -23,38 +24,37 @@ import asyncio
class AntiEmojiSpam(commands.Cog):
def __init__(self, bot):
self.bot = bot
self.emoji_threshold = 5
async def is_automod_enabled(self, guild_id):
async with aiosqlite.connect("db/automod.db") as db:
async with aiosqlite.connect(db_path("automod.db")) as db:
cursor = await db.execute("SELECT enabled FROM automod WHERE guild_id = ?", (guild_id,))
result = await cursor.fetchone()
return result is not None and result[0] == 1
async def is_anti_emoji_spam_enabled(self, guild_id):
async with aiosqlite.connect("db/automod.db") as db:
async with aiosqlite.connect(db_path("automod.db")) as db:
cursor = await db.execute("SELECT punishment FROM automod_punishments WHERE guild_id = ? AND event = 'Anti emoji spam'", (guild_id,))
result = await cursor.fetchone()
return result is not None
async def get_ignored_channels(self, guild_id):
async with aiosqlite.connect("db/automod.db") as db:
async with aiosqlite.connect(db_path("automod.db")) as db:
cursor = await db.execute("SELECT id FROM automod_ignored WHERE guild_id = ? AND type = 'channel'", (guild_id,))
return [row[0] for row in await cursor.fetchall()]
async def get_ignored_roles(self, guild_id):
async with aiosqlite.connect("db/automod.db") as db:
async with aiosqlite.connect(db_path("automod.db")) as db:
cursor = await db.execute("SELECT id FROM automod_ignored WHERE guild_id = ? AND type = 'role'", (guild_id,))
return [row[0] for row in await cursor.fetchall()]
async def get_punishment(self, guild_id):
async with aiosqlite.connect("db/automod.db") as db:
async with aiosqlite.connect(db_path("automod.db")) as db:
cursor = await db.execute("SELECT punishment FROM automod_punishments WHERE guild_id = ? AND event = 'Anti emoji spam'", (guild_id,))
result = await cursor.fetchone()
return result[0] if result else None
async def log_action(self, guild, user, channel, action, reason):
async with aiosqlite.connect("db/automod.db") as db:
async with aiosqlite.connect(db_path("automod.db")) as db:
cursor = await db.execute("SELECT log_channel FROM automod_logging WHERE guild_id = ?", (guild.id,))
log_channel_id = await cursor.fetchone()
@@ -118,17 +118,20 @@ class AntiEmojiSpam(commands.Cog):
emoji_count = len(emoji_pattern.findall(message.content))
th = await get_thresholds(guild_id, "anti_emoji_spam")
emoji_threshold = int(th.get("max_emojis", 5))
mute_minutes = float(th.get("mute_minutes", 1))
if emoji_count > self.emoji_threshold:
if emoji_count > emoji_threshold:
punishment = await self.get_punishment(guild_id)
action_taken = None
reason = f"Emoji Spam ({emoji_count} emojis)"
try:
if punishment == "Mute":
timeout_duration = discord.utils.utcnow() + timedelta(minutes=1)
timeout_duration = discord.utils.utcnow() + timedelta(minutes=mute_minutes)
await user.edit(timed_out_until=timeout_duration, reason=reason)
action_taken = "Muted for 1 minute"
action_taken = f"Muted for {int(mute_minutes)} minutes"
elif punishment == "Kick":
await user.kick(reason=reason)
action_taken = "Kicked"

View File

@@ -1,16 +1,17 @@
# ╔══════════════════════════════════════════════════════════════════╗
# ║ ║
# ║ ░█▀▀░█▀█░█▀▄░█▀▀░█░█ ░█▀▄░█▀▀░█░█░█▀▀
# ║ ░█░░░█░█░█░█░█▀▀░▄▀▄ ░█░█░█▀▀░▀▄▀░▀▀█
# ║ ░▀▀▀░▀▀▀░▀▀░░▀▀▀░▀░▀ ░▀▀░░▀▀▀░░▀░░▀▀▀
# ║ +-+-+-+-+-+-+-+-+
# ║ |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 utils.automod_settings import get_thresholds
import discord
from utils.emoji import TICK
@@ -26,35 +27,35 @@ class AntiInvite(commands.Cog):
self.invite_pattern = re.compile(r'(https?://)?(www\.)?(discord\.gg|discordapp\.com/invite|discord\.com/invite)/\S+')
async def is_automod_enabled(self, guild_id):
async with aiosqlite.connect("db/automod.db") as db:
async with aiosqlite.connect(db_path("automod.db")) as db:
cursor = await db.execute("SELECT enabled FROM automod WHERE guild_id = ?", (guild_id,))
result = await cursor.fetchone()
return result is not None and result[0] == 1
async def is_anti_invites_enabled(self, guild_id):
async with aiosqlite.connect("db/automod.db") as db:
async with aiosqlite.connect(db_path("automod.db")) as db:
cursor = await db.execute("SELECT punishment FROM automod_punishments WHERE guild_id = ? AND event = 'Anti invites'", (guild_id,))
result = await cursor.fetchone()
return result is not None
async def get_ignored_channels(self, guild_id):
async with aiosqlite.connect("db/automod.db") as db:
async with aiosqlite.connect(db_path("automod.db")) as db:
cursor = await db.execute("SELECT id FROM automod_ignored WHERE guild_id = ? AND type = 'channel'", (guild_id,))
return [row[0] for row in await cursor.fetchall()]
async def get_ignored_roles(self, guild_id):
async with aiosqlite.connect("db/automod.db") as db:
async with aiosqlite.connect(db_path("automod.db")) as db:
cursor = await db.execute("SELECT id FROM automod_ignored WHERE guild_id = ? AND type = 'role'", (guild_id,))
return [row[0] for row in await cursor.fetchall()]
async def get_punishment(self, guild_id):
async with aiosqlite.connect("db/automod.db") as db:
async with aiosqlite.connect(db_path("automod.db")) as db:
cursor = await db.execute("SELECT punishment FROM automod_punishments WHERE guild_id = ? AND event = 'Anti invites'", (guild_id,))
result = await cursor.fetchone()
return result[0] if result else None
async def log_action(self, guild, user, channel, action, reason):
async with aiosqlite.connect("db/automod.db") as db:
async with aiosqlite.connect(db_path("automod.db")) as db:
cursor = await db.execute("SELECT log_channel FROM automod_logging WHERE guild_id = ?", (guild.id,))
log_channel_id = await cursor.fetchone()
@@ -105,15 +106,17 @@ class AntiInvite(commands.Cog):
if any(invite.code == invite_code for invite in invite):
return
th = await get_thresholds(guild_id, "anti_invites")
mute_minutes = float(th.get("mute_minutes", 12))
punishment = await self.get_punishment(guild_id)
action_taken = None
reason = "Posted an invite link"
try:
if punishment == "Mute":
timeout_duration = discord.utils.utcnow() + timedelta(minutes=12)
timeout_duration = discord.utils.utcnow() + timedelta(minutes=mute_minutes)
await user.edit(timed_out_until=timeout_duration, reason="Posted an invite link")
action_taken = "Muted for 12 minutes"
action_taken = f"Muted for {int(mute_minutes)} minutes"
elif punishment == "Kick":
await user.kick(reason="Posted an invite link")
action_taken = "Kicked"

View File

@@ -1,16 +1,17 @@
# ╔══════════════════════════════════════════════════════════════════╗
# ║ ║
# ║ ░█▀▀░█▀█░█▀▄░█▀▀░█░█ ░█▀▄░█▀▀░█░█░█▀▀
# ║ ░█░░░█░█░█░█░█▀▀░▄▀▄ ░█░█░█▀▀░▀▄▀░▀▀█
# ║ ░▀▀▀░▀▀▀░▀▀░░▀▀▀░▀░▀ ░▀▀░░▀▀▀░░▀░░▀▀▀
# ║ +-+-+-+-+-+-+-+-+
# ║ |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 utils.automod_settings import get_thresholds
import discord
from utils.emoji import TICK
@@ -22,39 +23,38 @@ import asyncio
class AntiMassMention(commands.Cog):
def __init__(self, bot):
self.bot = bot
self.mass_mention_threshold = 5
async def is_automod_enabled(self, guild_id):
async with aiosqlite.connect("db/automod.db") as db:
async with aiosqlite.connect(db_path("automod.db")) as db:
cursor = await db.execute("SELECT enabled FROM automod WHERE guild_id = ?", (guild_id,))
result = await cursor.fetchone()
return result is not None and result[0] == 1
async def is_anti_mass_mention_enabled(self, guild_id):
async with aiosqlite.connect("db/automod.db") as db:
async with aiosqlite.connect(db_path("automod.db")) as db:
cursor = await db.execute("SELECT punishment FROM automod_punishments WHERE guild_id = ? AND event = 'Anti mass mention'", (guild_id,))
result = await cursor.fetchone()
return result is not None
async def get_ignored_channels(self, guild_id):
async with aiosqlite.connect("db/automod.db") as db:
async with aiosqlite.connect(db_path("automod.db")) as db:
cursor = await db.execute("SELECT id FROM automod_ignored WHERE guild_id = ? AND type = 'channel'", (guild_id,))
return [row[0] for row in await cursor.fetchall()]
async def get_ignored_roles(self, guild_id):
async with aiosqlite.connect("db/automod.db") as db:
async with aiosqlite.connect(db_path("automod.db")) as db:
cursor = await db.execute("SELECT id FROM automod_ignored WHERE guild_id = ? AND type = 'role'", (guild_id,))
return [row[0] for row in await cursor.fetchall()]
async def get_punishment(self, guild_id):
async with aiosqlite.connect("db/automod.db") as db:
async with aiosqlite.connect(db_path("automod.db")) as db:
cursor = await db.execute("SELECT punishment FROM automod_punishments WHERE guild_id = ? AND event = 'Anti mass mention'", (guild_id,))
result = await cursor.fetchone()
return result[0] if result else None
async def log_action(self, guild, user, channel, action, reason):
async with aiosqlite.connect("db/automod.db") as db:
async with aiosqlite.connect(db_path("automod.db")) as db:
cursor = await db.execute("SELECT log_channel FROM automod_logging WHERE guild_id = ?", (guild.id,))
log_channel_id = await cursor.fetchone()
@@ -97,17 +97,21 @@ class AntiMassMention(commands.Cog):
return
th = await get_thresholds(guild_id, "anti_mass_mention")
mention_threshold = int(th.get("max_mentions", 5))
mute_minutes = float(th.get("mute_minutes", 3))
mention_count = message.content.count("<@")
if mention_count >= self.mass_mention_threshold:
if mention_count >= mention_threshold:
punishment = await self.get_punishment(guild_id)
action_taken = None
reason = f"Mass Mention ({mention_count} mentions)"
try:
if punishment == "Mute":
timeout_duration = discord.utils.utcnow() + timedelta(minutes=3)
timeout_duration = discord.utils.utcnow() + timedelta(minutes=mute_minutes)
await user.edit(timed_out_until=timeout_duration, reason=reason)
action_taken = "Muted for 3 minutes"
action_taken = f"Muted for {int(mute_minutes)} minutes"
elif punishment == "Kick":
await user.kick(reason=reason)
action_taken = "Kicked"

View File

@@ -1,16 +1,17 @@
# ╔══════════════════════════════════════════════════════════════════╗
# ║ ║
# ║ ░█▀▀░█▀█░█▀▄░█▀▀░█░█ ░█▀▄░█▀▀░█░█░█▀▀
# ║ ░█░░░█░█░█░█░█▀▀░▄▀▄ ░█░█░█▀▀░▀▄▀░▀▀█
# ║ ░▀▀▀░▀▀▀░▀▀░░▀▀▀░▀░▀ ░▀▀░░▀▀▀░░▀░░▀▀▀
# ║ +-+-+-+-+-+-+-+-+
# ║ |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 utils.automod_settings import get_thresholds
import discord
from utils.emoji import TICK
@@ -22,39 +23,37 @@ from datetime import timedelta
class AntiCaps(commands.Cog):
def __init__(self, bot):
self.bot = bot
self.caps_threshold = 70
self.mute_duration = 2 * 60
async def is_automod_enabled(self, guild_id):
async with aiosqlite.connect("db/automod.db") as db:
async with aiosqlite.connect(db_path("automod.db")) as db:
cursor = await db.execute("SELECT enabled FROM automod WHERE guild_id = ?", (guild_id,))
result = await cursor.fetchone()
return result is not None and result[0] == 1
async def is_anti_caps_enabled(self, guild_id):
async with aiosqlite.connect("db/automod.db") as db:
async with aiosqlite.connect(db_path("automod.db")) as db:
cursor = await db.execute("SELECT punishment FROM automod_punishments WHERE guild_id = ? AND event = 'Anti caps'", (guild_id,))
result = await cursor.fetchone()
return result is not None
async def get_ignored_channels(self, guild_id):
async with aiosqlite.connect("db/automod.db") as db:
async with aiosqlite.connect(db_path("automod.db")) as db:
cursor = await db.execute("SELECT id FROM automod_ignored WHERE guild_id = ? AND type = 'channel'", (guild_id,))
return [row[0] for row in await cursor.fetchall()]
async def get_ignored_roles(self, guild_id):
async with aiosqlite.connect("db/automod.db") as db:
async with aiosqlite.connect(db_path("automod.db")) as db:
cursor = await db.execute("SELECT id FROM automod_ignored WHERE guild_id = ? AND type = 'role'", (guild_id,))
return [row[0] for row in await cursor.fetchall()]
async def get_punishment(self, guild_id):
async with aiosqlite.connect("db/automod.db") as db:
async with aiosqlite.connect(db_path("automod.db")) as db:
cursor = await db.execute("SELECT punishment FROM automod_punishments WHERE guild_id = ? AND event = 'Anti caps'", (guild_id,))
result = await cursor.fetchone()
return result[0] if result else None
async def log_action(self, guild, user, channel, action, reason):
async with aiosqlite.connect("db/automod.db") as db:
async with aiosqlite.connect(db_path("automod.db")) as db:
cursor = await db.execute("SELECT log_channel FROM automod_logging WHERE guild_id = ?", (guild.id,))
log_channel_id = await cursor.fetchone()
@@ -74,9 +73,6 @@ class AntiCaps(commands.Cog):
@commands.Cog.listener()
async def on_message(self, message):
if len(message.content) < 45:
return
if message.author.bot:
return
@@ -85,6 +81,14 @@ class AntiCaps(commands.Cog):
channel = message.channel
guild_id = guild.id
th = await get_thresholds(guild_id, "anti_caps")
min_length = int(th.get("min_length", 45))
caps_threshold = float(th.get("percent", 70))
mute_minutes = float(th.get("mute_minutes", 1))
if len(message.content) < min_length:
return
if not await self.is_automod_enabled(guild_id) or not await self.is_anti_caps_enabled(guild_id):
return
@@ -103,16 +107,16 @@ class AntiCaps(commands.Cog):
caps_count = sum(1 for c in message.content if c.isupper())
caps_percentage = (caps_count / len(message.content)) * 100
if caps_percentage > self.caps_threshold:
if caps_percentage > caps_threshold:
punishment = await self.get_punishment(guild_id)
action_taken = None
reason = "Excessive Caps"
try:
if punishment == "Mute":
timeout_duration = discord.utils.utcnow() + timedelta(minutes=1)
timeout_duration = discord.utils.utcnow() + timedelta(minutes=mute_minutes)
await user.edit(timed_out_until=timeout_duration, reason="Excessive Caps")
action_taken = "Muted for 1 minutes"
action_taken = f"Muted for {int(mute_minutes)} minutes"
elif punishment == "Kick":
await user.kick(reason="Excessive Caps")
action_taken = "Kicked"

View File

@@ -1,16 +1,17 @@
# ╔══════════════════════════════════════════════════════════════════╗
# ║ ║
# ║ ░█▀▀░█▀█░█▀▄░█▀▀░█░█ ░█▀▄░█▀▀░█░█░█▀▀
# ║ ░█░░░█░█░█░█░█▀▀░▄▀▄ ░█░█░█▀▀░▀▄▀░▀▀█
# ║ ░▀▀▀░▀▀▀░▀▀░░▀▀▀░▀░▀ ░▀▀░░▀▀▀░░▀░░▀▀▀
# ║ +-+-+-+-+-+-+-+-+
# ║ |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 utils.automod_settings import get_thresholds
import discord
from utils.emoji import TICK
@@ -29,35 +30,35 @@ class AntiLink(commands.Cog):
self.spotify_pattern = re.compile(r'^https://open\.spotify\.com/track/\S+')
async def is_automod_enabled(self, guild_id):
async with aiosqlite.connect("db/automod.db") as db:
async with aiosqlite.connect(db_path("automod.db")) as db:
cursor = await db.execute("SELECT enabled FROM automod WHERE guild_id = ?", (guild_id,))
result = await cursor.fetchone()
return result is not None and result[0] == 1
async def is_anti_link_enabled(self, guild_id):
async with aiosqlite.connect("db/automod.db") as db:
async with aiosqlite.connect(db_path("automod.db")) as db:
cursor = await db.execute("SELECT punishment FROM automod_punishments WHERE guild_id = ? AND event = 'Anti link'", (guild_id,))
result = await cursor.fetchone()
return result is not None
async def get_ignored_channels(self, guild_id):
async with aiosqlite.connect("db/automod.db") as db:
async with aiosqlite.connect(db_path("automod.db")) as db:
cursor = await db.execute("SELECT id FROM automod_ignored WHERE guild_id = ? AND type = 'channel'", (guild_id,))
return [row[0] for row in await cursor.fetchall()]
async def get_ignored_roles(self, guild_id):
async with aiosqlite.connect("db/automod.db") as db:
async with aiosqlite.connect(db_path("automod.db")) as db:
cursor = await db.execute("SELECT id FROM automod_ignored WHERE guild_id = ? AND type = 'role'", (guild_id,))
return [row[0] for row in await cursor.fetchall()]
async def get_punishment(self, guild_id):
async with aiosqlite.connect("db/automod.db") as db:
async with aiosqlite.connect(db_path("automod.db")) as db:
cursor = await db.execute("SELECT punishment FROM automod_punishments WHERE guild_id = ? AND event = 'Anti link'", (guild_id,))
result = await cursor.fetchone()
return result[0] if result else None
async def log_action(self, guild, user, channel, action, reason):
async with aiosqlite.connect("db/automod.db") as db:
async with aiosqlite.connect(db_path("automod.db")) as db:
cursor = await db.execute("SELECT log_channel FROM automod_logging WHERE guild_id = ?", (guild.id,))
log_channel_id = await cursor.fetchone()
@@ -107,15 +108,17 @@ class AntiLink(commands.Cog):
if self.spotify_pattern.search(message.content):
return
th = await get_thresholds(guild_id, "anti_link")
mute_minutes = float(th.get("mute_minutes", 7))
punishment = await self.get_punishment(guild_id)
action_taken = None
reason = "Posted a link"
try:
if punishment == "Mute":
timeout_duration = discord.utils.utcnow() + timedelta(minutes=7)
timeout_duration = discord.utils.utcnow() + timedelta(minutes=mute_minutes)
await user.edit(timed_out_until=timeout_duration, reason=reason)
action_taken = "Muted for 7 minutes"
action_taken = f"Muted for {int(mute_minutes)} minutes"
elif punishment == "Kick":
await user.kick(reason=reason)
action_taken = "Kicked"

View File

@@ -1,16 +1,17 @@
# ╔══════════════════════════════════════════════════════════════════╗
# ║ ║
# ║ ░█▀▀░█▀█░█▀▄░█▀▀░█░█ ░█▀▄░█▀▀░█░█░█▀▀
# ║ ░█░░░█░█░█░█░█▀▀░▄▀▄ ░█░█░█▀▀░▀▄▀░▀▀█
# ║ ░▀▀▀░▀▀▀░▀▀░░▀▀▀░▀░▀ ░▀▀░░▀▀▀░░▀░░▀▀▀
# ║ +-+-+-+-+-+-+-+-+
# ║ |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 utils.automod_settings import get_thresholds
import discord
from utils.emoji import TICK
@@ -22,41 +23,39 @@ from datetime import timedelta
class AntiSpam(commands.Cog):
def __init__(self, bot):
self.bot = bot
self.spam_threshold = 5
self.mute_duration = 12 * 60
self.recent_messages = {}
async def is_automod_enabled(self, guild_id):
async with aiosqlite.connect("db/automod.db") as db:
async with aiosqlite.connect(db_path("automod.db")) as db:
cursor = await db.execute("SELECT enabled FROM automod WHERE guild_id = ?", (guild_id,))
result = await cursor.fetchone()
return result is not None and result[0] == 1
async def is_anti_spam_enabled(self, guild_id):
async with aiosqlite.connect("db/automod.db") as db:
async with aiosqlite.connect(db_path("automod.db")) as db:
cursor = await db.execute("SELECT punishment FROM automod_punishments WHERE guild_id = ? AND event = 'Anti spam'", (guild_id,))
result = await cursor.fetchone()
return result is not None
async def get_ignored_channels(self, guild_id):
async with aiosqlite.connect("db/automod.db") as db:
async with aiosqlite.connect(db_path("automod.db")) as db:
cursor = await db.execute("SELECT id FROM automod_ignored WHERE guild_id = ? AND type = 'channel'", (guild_id,))
return [row[0] for row in await cursor.fetchall()]
async def get_ignored_roles(self, guild_id):
async with aiosqlite.connect("db/automod.db") as db:
async with aiosqlite.connect(db_path("automod.db")) as db:
cursor = await db.execute("SELECT id FROM automod_ignored WHERE guild_id = ? AND type = 'role'", (guild_id,))
return [row[0] for row in await cursor.fetchall()]
async def get_punishment(self, guild_id):
async with aiosqlite.connect("db/automod.db") as db:
async with aiosqlite.connect(db_path("automod.db")) as db:
cursor = await db.execute("SELECT punishment FROM automod_punishments WHERE guild_id = ? AND event = 'Anti spam'", (guild_id,))
result = await cursor.fetchone()
return result[0] if result else None
async def log_action(self, guild, user, channel, action, reason):
async with aiosqlite.connect("db/automod.db") as db:
async with aiosqlite.connect(db_path("automod.db")) as db:
cursor = await db.execute("SELECT log_channel FROM automod_logging WHERE guild_id = ?", (guild.id,))
log_channel_id = await cursor.fetchone()
@@ -99,21 +98,26 @@ class AntiSpam(commands.Cog):
return
current_time = message.created_at.timestamp()
th = await get_thresholds(guild_id, "anti_spam")
window = float(th.get("window_seconds", 10))
spam_threshold = int(th.get("max_messages", 5))
mute_minutes = float(th.get("mute_minutes", 12))
user_messages = self.recent_messages.get(user.id, [])
user_messages = [msg for msg in user_messages if current_time - msg < 10]
user_messages = [msg for msg in user_messages if current_time - msg < window]
user_messages.append(current_time)
self.recent_messages[user.id] = user_messages
if len(user_messages) > self.spam_threshold:
if len(user_messages) > spam_threshold:
punishment = await self.get_punishment(guild_id)
action_taken = None
reason = "Spamming"
try:
if punishment == "Mute":
timeout_duration = discord.utils.utcnow() + timedelta(minutes=12)
timeout_duration = discord.utils.utcnow() + timedelta(minutes=mute_minutes)
await user.edit(timed_out_until=timeout_duration, reason="Spamming")
action_taken = "Muted for 12 minutes"
action_taken = f"Muted for {int(mute_minutes)} minutes"
elif punishment == "Kick":
await user.kick(reason="Spamming")
action_taken = "Kicked"

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
# ║ ║
# ╚══════════════════════════════════════════════════════════════════╝

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
# ║ ║
# ╚══════════════════════════════════════════════════════════════════╝

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
# ║ ║
# ╚══════════════════════════════════════════════════════════════════╝

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
# ║ ║
# ╚══════════════════════════════════════════════════════════════════╝

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
# ║ ║
# ╚══════════════════════════════════════════════════════════════════╝

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
# ║ ║
# ╚══════════════════════════════════════════════════════════════════╝

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
# ║ ║
# ╚══════════════════════════════════════════════════════════════════╝

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
# ║ ║
# ╚══════════════════════════════════════════════════════════════════╝

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
# ║ ║
# ╚══════════════════════════════════════════════════════════════════╝

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
# ║ ║
# ╚══════════════════════════════════════════════════════════════════╝

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
# ║ ║
# ╚══════════════════════════════════════════════════════════════════╝

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
# ║ ║
# ╚══════════════════════════════════════════════════════════════════╝

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
# ║ ║
# ╚══════════════════════════════════════════════════════════════════╝

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
# ║ ║
# ╚══════════════════════════════════════════════════════════════════╝

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 jsondb_path
import discord
from discord.ext import commands, tasks
@@ -56,7 +56,7 @@ class Birthdays(commands.Cog):
@commands.has_permissions(administrator=True)
@commands.guild_only()
async def birthday_setup(self, ctx: commands.Context, channel: discord.TextChannel, role: discord.Role):
db = read_db('jsondb/birthday_logs.json')
db = read_db(jsondb_path('birthday_logs.json'))
guild_id = str(ctx.guild.id)
if guild_id not in db:
@@ -65,7 +65,7 @@ class Birthdays(commands.Cog):
db[guild_id]["birthday_channel_id"] = channel.id
db[guild_id]["birthday_role_id"] = role.id
write_db('jsondb/birthday_logs.json', db)
write_db(jsondb_path('birthday_logs.json'), db)
await ctx.send(view=CV2("Birthday Setup", f"Birthday log channel set to {channel.mention} and birthday role set to {role.mention}."))
@@ -104,9 +104,9 @@ class Birthdays(commands.Cog):
return
date = f"{month}-{day}-{year}"
db = read_db('jsondb/birthdays.json')
db = read_db(jsondb_path('birthdays.json'))
db[str(ctx.author.id)] = date
write_db('jsondb/birthdays.json', db)
write_db(jsondb_path('birthdays.json'), db)
await ctx.send(view=CV2("Success", f"Your birthday has been set to {date}."))
except asyncio.TimeoutError:
@@ -117,11 +117,11 @@ class Birthdays(commands.Cog):
help="Remove your birthday.")
@commands.guild_only()
async def remove_birthday(self, ctx: commands.Context):
db = read_db('jsondb/birthdays.json')
db = read_db(jsondb_path('birthdays.json'))
if str(ctx.author.id) in db:
del db[str(ctx.author.id)]
write_db('jsondb/birthdays.json', db)
write_db(jsondb_path('birthdays.json'), db)
await ctx.send(view=CV2("Success", "Your birthday has been removed."))
else:
await ctx.send(view=CV2("Error", "You have no birthday set."))
@@ -133,7 +133,7 @@ class Birthdays(commands.Cog):
async def list_birthdays(self, ctx: commands.Context):
now = datetime.datetime.now()
today_date = now.strftime("%m-%d")
db = read_db('jsondb/birthdays.json')
db = read_db(jsondb_path('birthdays.json'))
members_with_birthday = [ctx.guild.get_member(int(user_id)) for user_id, date in db.items() if date.startswith(today_date)]
@@ -148,7 +148,7 @@ class Birthdays(commands.Cog):
help="Check your birthday.")
@commands.guild_only()
async def check_birthday(self, ctx: commands.Context):
db = read_db('jsondb/birthdays.json')
db = read_db(jsondb_path('birthdays.json'))
if str(ctx.author.id) in db:
date = db[str(ctx.author.id)]
@@ -160,8 +160,8 @@ class Birthdays(commands.Cog):
async def check_birthdays(self):
now = datetime.datetime.now()
today_date = now.strftime("%m-%d")
db = read_db('jsondb/birthdays.json')
guild_settings = read_db('jsondb/birthday_logs.json')
db = read_db(jsondb_path('birthdays.json'))
guild_settings = read_db(jsondb_path('birthday_logs.json'))
for user_id, birthday in db.items():
if birthday.startswith(today_date):

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,21 +1,20 @@
# ╔══════════════════════════════════════════════════════════════════╗
# ║ ║
# ║ ░█▀▀░█▀█░█▀▄░█▀▀░█░█ ░█▀▄░█▀▀░█░█░█▀▀
# ║ ░█░░░█░█░█░█░█▀▀░▄▀▄ ░█░█░█▀▀░▀▄▀░▀▀█
# ║ ░▀▀▀░▀▀▀░▀▀░░▀▀▀░▀░▀ ░▀▀░░▀▀▀░░▀░░▀▀▀
# ║ +-+-+-+-+-+-+-+-+
# ║ |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
# ║ ║
# ╚══════════════════════════════════════════════════════════════════╝
import discord
from discord.ext import commands
import os
from core import Cog, zyrox, Context
from core import Cog, Axiom, Context
import games as games
from utils.Tools import *
from utils.cv2 import CV2
@@ -26,15 +25,30 @@ import asyncio
class Games(Cog):
"""Zyrox Games"""
"""Axiom Games"""
def __init__(self, client: zyrox):
def __init__(self, client: Axiom):
self.client = client
@commands.hybrid_group(
name="game",
description="Play mini-games with friends or the bot.",
fallback="help",
invoke_without_command=True,
)
@blacklist_check()
@ignore_check()
@commands.cooldown(1, 3, commands.BucketType.user)
@commands.guild_only()
async def game(self, ctx: Context):
"""Games root — use `/game <subcommand>` or `>game <subcommand>`."""
if ctx.subcommand_passed is None:
await ctx.send_help(ctx.command)
ctx.command.reset_cooldown(ctx)
@commands.hybrid_command(name="chess",
@game.command(name="chess",
help="Play Chess with a user.",
usage="Chess <user>")
usage="game chess <user>")
@blacklist_check()
@ignore_check()
@commands.cooldown(1, 3, commands.BucketType.user)
@@ -50,10 +64,10 @@ class Games(Cog):
await game.start(ctx)
@commands.hybrid_command(name="rps",
@game.command(name="rps",
help="Play Rock Paper Scissor with bot/user.",
aliases=["rockpaperscissors"],
usage="Rockpaperscissors")
usage="game rps [user]")
@blacklist_check()
@ignore_check()
@commands.cooldown(1, 3, commands.BucketType.user)
@@ -63,10 +77,10 @@ class Games(Cog):
game = btn.BetaRockPaperScissors(player)
await game.start(ctx, timeout=120)
@commands.hybrid_command(name="tic-tac-toe",
@game.command(name="tictactoe",
help="play tic-tac-toe game with a user.",
aliases=["ttt", "tictactoe"],
usage="Ticktactoe <member>")
aliases=["ttt", "tic-tac-toe"],
usage="game tictactoe <member>")
@blacklist_check()
@ignore_check()
@commands.cooldown(1, 3, commands.BucketType.user)
@@ -81,9 +95,9 @@ class Games(Cog):
game = btn.BetaTictactoe(cross=ctx.author, circle=player)
await game.start(ctx, timeout=30)
@commands.hybrid_command(name="wordle",
@game.command(name="wordle",
help="Wordle Game | Play with bot.",
usage="Wordle")
usage="game wordle")
@blacklist_check()
@ignore_check()
@commands.cooldown(1, 3, commands.BucketType.user)
@@ -93,10 +107,10 @@ class Games(Cog):
game = games.Wordle()
await game.start(ctx, timeout=120)
@commands.hybrid_command(name="2048",
@game.command(name="2048",
help="Play 2048 game with bot.",
aliases=["twenty48"],
usage="2048")
usage="game 2048")
@blacklist_check()
@ignore_check()
@commands.cooldown(1, 3, commands.BucketType.user)
@@ -106,10 +120,10 @@ class Games(Cog):
game = btn.BetaTwenty48()
await game.start(ctx, win_at=2048)
@commands.hybrid_command(name="memory-game",
@game.command(name="memory",
help="How strong is your memory?",
aliases=["memory"],
usage="memory-game")
aliases=["memory-game"],
usage="game memory")
@blacklist_check()
@ignore_check()
@commands.cooldown(1, 3, commands.BucketType.user)
@@ -119,10 +133,10 @@ class Games(Cog):
game = btn.MemoryGame()
await game.start(ctx)
@commands.hybrid_command(name="number-slider",
@game.command(name="slider",
help="slide numbers with bot",
aliases=["slider"],
usage="slider")
aliases=["number-slider"],
usage="game slider")
@blacklist_check()
@ignore_check()
@commands.cooldown(1, 3, commands.BucketType.user)
@@ -132,10 +146,10 @@ class Games(Cog):
game = btn.NumberSlider()
await game.start(ctx)
@commands.hybrid_command(name="battleship",
@game.command(name="battleship",
help="Play battleship game with your friend.",
aliases=["battle-ship"],
usage="battleship <user>")
usage="game battleship <user>")
@blacklist_check()
@ignore_check()
@commands.cooldown(1, 3, commands.BucketType.user)
@@ -165,10 +179,10 @@ class Games(Cog):
async def _end_country_guesser(self, ctx: Context):
await self.country_guesser_game.end_game_manually(ctx)"""
@commands.hybrid_command(name="connectfour",
@game.command(name="connectfour",
help="Play Connect Four game with user.",
aliases=["c4", "connect-four", "connect4"],
usage="connectfour <user>")
usage="game connectfour <user>")
@blacklist_check()
@ignore_check()
@commands.cooldown(1, 3, commands.BucketType.user)
@@ -185,10 +199,10 @@ class Games(Cog):
@commands.hybrid_command(name="lights-out",
@game.command(name="lightsout",
help="Play Lights Show game with bot.",
aliases=["lightsout"],
usage="Lights-out")
aliases=["lights-out"],
usage="game lightsout")
@blacklist_check()
@ignore_check()
@commands.cooldown(1, 3, commands.BucketType.user)

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
import discord
from discord.ext import commands
@@ -23,7 +23,7 @@ from utils.config import *
class Invcrole(commands.Cog):
def __init__(self, bot):
self.bot = bot
self.db_path = 'db/invc.db'
self.db_path = db_path('invc.db')
self.bot.loop.create_task(self.create_table())
async def create_table(self):

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
import discord
import aiosqlite
@@ -27,7 +27,7 @@ class Media(commands.Cog):
async def set_db(self):
async with aiosqlite.connect('db/media.db') as db:
async with aiosqlite.connect(db_path('media.db')) as db:
await db.execute('''
CREATE TABLE IF NOT EXISTS media_channels (
guild_id INTEGER PRIMARY KEY,
@@ -47,7 +47,13 @@ class Media(commands.Cog):
async def on_ready(self):
await self.set_db()
@commands.hybrid_group(name="media", help="Setup Media channel, Media channel will not allow users to send messages other than media files.", invoke_without_command=True)
@commands.hybrid_group(
name="media",
description="Setup Media channel; only media files are allowed.",
help="Setup Media channel, Media channel will not allow users to send messages other than media files.",
fallback="help",
invoke_without_command=True,
)
@blacklist_check()
@ignore_check()
@commands.cooldown(1, 3, commands.BucketType.user)
@@ -62,7 +68,7 @@ class Media(commands.Cog):
@commands.cooldown(1, 3, commands.BucketType.user)
@commands.has_permissions(administrator=True)
async def setup(self, ctx, *, channel: discord.TextChannel):
async with aiosqlite.connect('db/media.db') as db:
async with aiosqlite.connect(db_path('media.db')) as db:
async with db.execute('SELECT channel_id FROM media_channels WHERE guild_id = ?', (ctx.guild.id,)) as cursor:
result = await cursor.fetchone()
if result:
@@ -80,7 +86,7 @@ class Media(commands.Cog):
@commands.cooldown(1, 3, commands.BucketType.user)
@commands.has_permissions(administrator=True)
async def remove(self, ctx):
async with aiosqlite.connect('db/media.db') as db:
async with aiosqlite.connect(db_path('media.db')) as db:
async with db.execute('SELECT channel_id FROM media_channels WHERE guild_id = ?', (ctx.guild.id,)) as cursor:
result = await cursor.fetchone()
if not result:
@@ -98,7 +104,7 @@ class Media(commands.Cog):
@commands.cooldown(1, 3, commands.BucketType.user)
@commands.has_permissions(administrator=True)
async def config(self, ctx):
async with aiosqlite.connect('db/media.db') as db:
async with aiosqlite.connect(db_path('media.db')) as db:
async with db.execute('SELECT channel_id FROM media_channels WHERE guild_id = ?', (ctx.guild.id,)) as cursor:
result = await cursor.fetchone()
if not result:
@@ -124,7 +130,7 @@ class Media(commands.Cog):
@commands.cooldown(1, 3, commands.BucketType.user)
@commands.has_permissions(administrator=True)
async def bypass_add(self, ctx, user: discord.Member):
async with aiosqlite.connect('db/media.db') as db:
async with aiosqlite.connect(db_path('media.db')) as db:
async with db.execute('SELECT COUNT(*) FROM media_bypass WHERE guild_id = ?', (ctx.guild.id,)) as cursor:
count = await cursor.fetchone()
if count[0] >= 25:
@@ -148,7 +154,7 @@ class Media(commands.Cog):
@commands.cooldown(1, 3, commands.BucketType.user)
@commands.has_permissions(administrator=True)
async def bypass_remove(self, ctx, user: discord.Member):
async with aiosqlite.connect('db/media.db') as db:
async with aiosqlite.connect(db_path('media.db')) as db:
async with db.execute('SELECT 1 FROM media_bypass WHERE guild_id = ? AND user_id = ?', (ctx.guild.id, user.id)) as cursor:
result = await cursor.fetchone()
if not result:
@@ -166,7 +172,7 @@ class Media(commands.Cog):
@commands.cooldown(1, 3, commands.BucketType.user)
@commands.has_permissions(administrator=True)
async def bypass_show(self, ctx):
async with aiosqlite.connect('db/media.db') as db:
async with aiosqlite.connect(db_path('media.db')) as db:
async with db.execute('SELECT user_id FROM media_bypass WHERE guild_id = ?', (ctx.guild.id,)) as cursor:
result = await cursor.fetchall()
if not result:
@@ -183,16 +189,16 @@ class Media(commands.Cog):
if message.author.bot:
return
async with aiosqlite.connect('db/media.db') as db:
async with aiosqlite.connect(db_path('media.db')) as db:
async with db.execute('SELECT channel_id FROM media_channels WHERE guild_id = ?', (message.guild.id,)) as cursor:
media_channel = await cursor.fetchone()
if media_channel and message.channel.id == media_channel[0]:
async with aiosqlite.connect('db/block.db') as block_db:
async with aiosqlite.connect(db_path('block.db')) as block_db:
async with block_db.execute('SELECT 1 FROM user_blacklist WHERE user_id = ?', (message.author.id,)) as cursor:
blacklisted = await cursor.fetchone()
async with aiosqlite.connect('db/media.db') as db:
async with aiosqlite.connect(db_path('media.db')) as db:
async with db.execute('SELECT 1 FROM media_bypass WHERE guild_id = ? AND user_id = ?', (message.guild.id, message.author.id)) as cursor:
bypassed = await cursor.fetchone()
@@ -221,7 +227,7 @@ class Media(commands.Cog):
]
if len(self.infractions[message.author.id]) >= 5:
async with aiosqlite.connect('db/block.db') as block_db:
async with aiosqlite.connect(db_path('block.db')) as block_db:
await block_db.execute('INSERT OR IGNORE INTO user_blacklist (user_id) VALUES (?)', (message.author.id,))
await block_db.commit()

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
import discord
from discord.ext import commands
@@ -24,7 +24,7 @@ from utils.cv2 import CV2, build_container
from utils.emoji import TICK, MENTION, SEED, TIME
from utils.config import *
DB_PATH = "db/afk.db"
DB_PATH = db_path("afk.db")
THEME_COLOR = 0xFF0000
FOOTER_TEXT = f"Developed by {BRAND_NAME}"

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
import os
import discord
@@ -323,19 +323,19 @@ class AI (commands .Cog ):
import os
db_path ="db/ai_data.db"
if os .path .exists (db_path ):
ai_db = db_path("ai_data.db")
if os .path .exists (ai_db ):
try :
test_conn =await aiosqlite .connect (db_path )
test_conn =await aiosqlite .connect (ai_db )
await test_conn .execute ("SELECT name FROM sqlite_master WHERE type='table';")
await test_conn .close ()
except Exception as e :
os .remove (db_path )
os .remove (ai_db )
logger .info ("Removed corrupted AI database, creating new one")
self .bot .db =await aiosqlite .connect (db_path )
self .bot .db =await aiosqlite .connect (ai_db )
logger .info ("AI database connection initialized")
await self .bot .db .execute ("""
@@ -401,12 +401,12 @@ class AI (commands .Cog ):
import aiosqlite
import os
db_path ="db/ai_data.db"
if not os .path .exists (db_path ):
ai_db = db_path("ai_data.db")
if not os .path .exists (ai_db ):
logger .info ("AI database doesn't exist, will be created on first use")
return
self .bot .db =await aiosqlite .connect (db_path )
self .bot .db =await aiosqlite .connect (ai_db )
logger .info ("AI database connection initialized for loading")
@@ -590,7 +590,7 @@ class AI (commands .Cog ):
system_context .append ({
"role":"system",
"content":"You are a Discord bot with many features including moderation, entertainment, music, games, AI capabilities, and utilities. Support server: https://discord.gg/codexdev"
"content":"You are a Discord bot with many features including moderation, entertainment, music, games, AI capabilities, and utilities. Support server: https://discord.gg/hexahost"
})
else :
@@ -602,7 +602,7 @@ You have a caring, helpful personality and can remember conversations with users
Be natural, conversational, and genuine in your responses. Don't be overly formal or robotic. Use the conversation history to provide personalized responses that feel like talking to a real friend who happens to be very knowledgeable and helpful.
Support server: https://discord.gg/codexdev"""
Support server: https://discord.gg/hexahost"""
})

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
import discord
from utils.emoji import CROSS, MANAGER, REDDOT, TICK
@@ -31,7 +31,7 @@ class Unwhitelist(commands.Cog):
#@commands.Cog.listener()
async def initialize_db(self):
self.db = await aiosqlite.connect('db/anti.db')
self.db = await aiosqlite.connect(db_path('anti.db'))
@commands.hybrid_command(name='unwhitelist', aliases=['unwl'], help="Unwhitelist a user from antinuke")
@commands.has_permissions(administrator=True)

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
import discord
from utils.emoji import ARROWRED, CROSS, DISABLE, ENABLE, MANAGER, TICK
@@ -32,7 +32,7 @@ class Whitelist(commands.Cog):
#@commands.Cog.listener()
async def initialize_db(self):
self.db = await aiosqlite.connect('db/anti.db')
self.db = await aiosqlite.connect(db_path('anti.db'))
await self.db.execute('''
CREATE TABLE IF NOT EXISTS whitelisted_users (
guild_id INTEGER,
@@ -57,16 +57,34 @@ class Whitelist(commands.Cog):
''')
await self.db.commit()
@commands.hybrid_command(name='whitelist', aliases=['wl'], help="Whitelists a user from antinuke for a specific action.")
@commands.hybrid_group(
name="whitelist",
aliases=["wl"],
description="Manage antinuke whitelist.",
fallback="help",
invoke_without_command=True,
help="Whitelists a user from antinuke for a specific action.",
)
@blacklist_check()
@ignore_check()
@commands.cooldown(1, 5, commands.BucketType.user)
@commands.max_concurrency(1, per=commands.BucketType.default, wait=False)
@commands.guild_only()
@commands.has_permissions(administrator=True)
async def whitelist(self, ctx):
"""Whitelist root — use `/whitelist <subcommand>` or `>whitelist <subcommand>`."""
if ctx.subcommand_passed is None:
await ctx.send_help(ctx.command)
ctx.command.reset_cooldown(ctx)
async def whitelist(self, ctx, member: discord.Member = None):
@whitelist.command(name="add", help="Whitelists a user from antinuke for a specific action.")
@blacklist_check()
@ignore_check()
@commands.cooldown(1, 5, commands.BucketType.user)
@commands.max_concurrency(1, per=commands.BucketType.default, wait=False)
@commands.guild_only()
@commands.has_permissions(administrator=True)
async def whitelist_add(self, ctx, member: discord.Member = None):
if ctx.guild.member_count < 2:
view = CV2(f"{CROSS} Error", "Your Server Doesn't Meet My 30 Member Criteria")
return await ctx.send(view=view)
@@ -101,7 +119,7 @@ class Whitelist(commands.Cog):
view = CV2(
"__Whitelist Commands__",
"**Adding a user to the whitelist means that no actions will be taken against them if they trigger the Anti-Nuke Module.**",
f"**Usage**\n{ARROWRED} `{prefix}whitelist @user/id`\n{ARROWRED} `{prefix}wl @user`"
f"**Usage**\n{ARROWRED} `{prefix}whitelist add @user/id`\n{ARROWRED} `{prefix}wl add @user`"
)
return await ctx.send(view=view)
@@ -252,7 +270,7 @@ class Whitelist(commands.Cog):
await msg.edit(view=None)
@commands.hybrid_command(name='whitelisted', aliases=['wlist'], help="Shows the list of whitelisted users.")
@whitelist.command(name="list", aliases=["whitelisted", "wlist"], help="Shows the list of whitelisted users.")
@blacklist_check()
@ignore_check()
@commands.cooldown(1, 5, commands.BucketType.user)
@@ -308,7 +326,7 @@ class Whitelist(commands.Cog):
await ctx.send(view=view)
@commands.hybrid_command(name="whitelistreset", aliases=['wlreset'], help="Resets the whitelisted users.")
@whitelist.command(name="reset", aliases=["whitelistreset", "wlreset"], help="Resets the whitelisted users.")
@blacklist_check()
@ignore_check()
@commands.cooldown(1, 10, commands.BucketType.user)

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
import discord
from utils.emoji import CROSS, EMOTE, TICK, ZSAFE, ZSETTINGS
@@ -31,7 +31,7 @@ class Antinuke(commands.Cog):
self.bot.loop.create_task(self.initialize_db())
async def initialize_db(self):
self.db = await aiosqlite.connect('db/anti.db')
self.db = await aiosqlite.connect(db_path('anti.db'))
await self.db.execute('''
CREATE TABLE IF NOT EXISTS antinuke (
guild_id INTEGER PRIMARY KEY,

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
import discord
from utils.emoji import CROSS, DISABLE, ENABLE, TICK, TICK_ALT
@@ -113,7 +113,7 @@ class Automod(commands.Cog):
self.bot.loop.create_task(self.init_db())
async def get_exempt_roles_channels(self, guild_id):
async with aiosqlite.connect("db/automod.db") as db:
async with aiosqlite.connect(db_path("automod.db")) as db:
roles_cursor = await db.execute("SELECT id FROM automod_ignored WHERE guild_id = ? AND type = 'role'", (guild_id,))
channels_cursor = await db.execute("SELECT id FROM automod_ignored WHERE guild_id = ? AND type = 'channel'", (guild_id,))
@@ -124,18 +124,18 @@ class Automod(commands.Cog):
async def is_automod_enabled(self, guild_id):
async with aiosqlite.connect("db/automod.db") as db:
async with aiosqlite.connect(db_path("automod.db")) as db:
cursor = await db.execute("SELECT enabled FROM automod WHERE guild_id = ?", (guild_id,))
result = await cursor.fetchone()
return result is not None and result[0] == 1
async def update_punishments(self, guild_id, event, punishment):
async with aiosqlite.connect("db/automod.db") as db:
async with aiosqlite.connect(db_path("automod.db")) as db:
await db.execute("INSERT OR REPLACE INTO automod_punishments (guild_id, event, punishment) VALUES (?, ?, ?)", (guild_id, event, punishment))
await db.commit()
async def get_current_punishments(self, guild_id):
async with aiosqlite.connect("db/automod.db") as db:
async with aiosqlite.connect(db_path("automod.db")) as db:
async with db.execute(
"SELECT event, punishment FROM automod_punishments WHERE guild_id = ? AND event != 'Anti NSFW link'",
(guild_id,)
@@ -143,7 +143,7 @@ class Automod(commands.Cog):
return await cursor.fetchall()
async def is_anti_nsfw_enabled(self, guild_id):
async with aiosqlite.connect("db/automod.db") as db:
async with aiosqlite.connect(db_path("automod.db")) as db:
cursor = await db.execute("SELECT punishment FROM automod_punishments WHERE guild_id = ? AND event = 'Anti NSFW link'", (guild_id,))
result = await cursor.fetchone()
return result is not None
@@ -151,7 +151,7 @@ class Automod(commands.Cog):
async def init_db(self):
async with aiosqlite.connect("db/automod.db") as db:
async with aiosqlite.connect(db_path("automod.db")) as db:
await db.execute("""
CREATE TABLE IF NOT EXISTS automod (
guild_id INTEGER PRIMARY KEY,
@@ -181,13 +181,30 @@ class Automod(commands.Cog):
PRIMARY KEY (guild_id)
)
""")
await db.execute("""
CREATE TABLE IF NOT EXISTS automod_thresholds (
guild_id INTEGER,
event TEXT,
key TEXT,
value REAL,
PRIMARY KEY (guild_id, event, key)
)
""")
await db.commit()
@commands.hybrid_group(invoke_without_command=True)
@commands.hybrid_group(
name="automod",
aliases=["am"],
invoke_without_command=True,
with_app_command=True,
description="Configure server Automod (enable, disable, punishments, ignores).",
fallback="help",
)
@blacklist_check()
@ignore_check()
@commands.cooldown(1, 4, commands.BucketType.user)
async def automod(self, ctx):
"""Automod root — use `/automod <subcommand>` or `>automod <subcommand>`."""
if ctx.subcommand_passed is None:
await ctx.send_help(ctx.command)
ctx.command.reset_cooldown(ctx)
@@ -271,7 +288,7 @@ class Automod(commands.Cog):
async def enable_automod(self, ctx, guild_id, selected_events, interaction):
async with aiosqlite.connect("db/automod.db") as db:
async with aiosqlite.connect(db_path("automod.db")) as db:
await db.execute("INSERT OR REPLACE INTO automod (guild_id, enabled) VALUES (?, 1)", (guild_id,))
for event in selected_events:
await db.execute("INSERT OR REPLACE INTO automod_punishments (guild_id, event, punishment) VALUES (?, ?, ?)", (guild_id, event, self.default_punishment))
@@ -328,7 +345,7 @@ class Automod(commands.Cog):
log_channel = await interaction.guild.create_text_channel(f"{BRAND_NAME.lower()}-automod", overwrites=overwrites)
guild_id = interaction.guild.id
async with aiosqlite.connect("db/automod.db") as db:
async with aiosqlite.connect(db_path("automod.db")) as db:
await db.execute("INSERT OR REPLACE INTO automod_logging (guild_id, log_channel) VALUES (?, ?)", (guild_id, log_channel.id))
await db.commit()
@@ -440,7 +457,7 @@ class Automod(commands.Cog):
await ctx.send(view=CV2(f"Automod Settings for {ctx.guild.name}", f"Uhh, looks like your server hasn\'t enabled Automoderation.\n\nCurrent Status: {DISABLE} Disabled\nTo Enable use `{ctx.prefix}automod enable`"))
return
async with aiosqlite.connect("db/automod.db") as db:
async with aiosqlite.connect(db_path("automod.db")) as db:
cursor = await db.execute("SELECT 1 FROM automod_ignored WHERE guild_id = ? AND type = 'channel' AND id = ?", (guild_id, channel.id))
if await cursor.fetchone() is not None:
await ctx.send(view=CV2("__Channel Already Whitelisted!__", f"{CROSS} The channel {channel.mention} is already in the ignore list.\n\n➜ Use **{ctx.prefix}automod unignore channel {channel.mention}** to remove it."))
@@ -491,7 +508,7 @@ class Automod(commands.Cog):
await ctx.send(view=CV2(f"Automod Settings for {ctx.guild.name}", f"Uhh, looks like your server hasn\'t enabled Automoderation.\n\nCurrent Status: {DISABLE} Disabled\nTo Enable use `{ctx.prefix}automod enable`"))
return
async with aiosqlite.connect("db/automod.db") as db:
async with aiosqlite.connect(db_path("automod.db")) as db:
cursor = await db.execute("SELECT 1 FROM automod_ignored WHERE guild_id = ? AND type = 'role' AND id = ?", (guild_id, role.id))
if await cursor.fetchone() is not None:
@@ -545,7 +562,7 @@ class Automod(commands.Cog):
return
async with aiosqlite.connect("db/automod.db") as db:
async with aiosqlite.connect(db_path("automod.db")) as db:
cursor = await db.execute("SELECT type, id FROM automod_ignored WHERE guild_id = ?", (guild_id,))
ignored_items = await cursor.fetchall()
@@ -592,7 +609,7 @@ class Automod(commands.Cog):
await ctx.send(view=CV2(f"Automod Settings for {ctx.guild.name}", f"Uhh, looks like your server hasn\'t enabled Automoderation.\n\nCurrent Status: {DISABLE} Disabled\nTo Enable use `{ctx.prefix}automod enable`"))
return
async with aiosqlite.connect("db/automod.db") as db:
async with aiosqlite.connect(db_path("automod.db")) as db:
await db.execute("DELETE FROM automod_ignored WHERE guild_id = ?", (guild_id,))
await db.commit()
await ctx.send(view=CV2(f"Automod Settings for {ctx.guild.name}", f"** {TICK} | All ignored channels and roles have been reset!**\n\nTo view current Automod settings use `{ctx.prefix}automod config`"))
@@ -639,7 +656,7 @@ class Automod(commands.Cog):
except discord.HTTPException:
pass
async with aiosqlite.connect("db/automod.db") as db:
async with aiosqlite.connect(db_path("automod.db")) as db:
result = await db.execute("DELETE FROM automod_ignored WHERE guild_id = ? AND type = 'channel' AND id = ?", (guild_id, channel.id))
await db.commit()
@@ -682,7 +699,7 @@ class Automod(commands.Cog):
pass
async with aiosqlite.connect("db/automod.db") as db:
async with aiosqlite.connect(db_path("automod.db")) as db:
result = await db.execute("DELETE FROM automod_ignored WHERE guild_id = ? AND type = 'role' AND id = ?", (guild_id, role.id))
await db.commit()
@@ -719,7 +736,7 @@ class Automod(commands.Cog):
elif view.value:
async with aiosqlite.connect("db/automod.db") as db:
async with aiosqlite.connect(db_path("automod.db")) as db:
await db.execute("DELETE FROM automod WHERE guild_id = ?", (guild_id,))
await db.execute("DELETE FROM automod_punishments WHERE guild_id = ?", (guild_id,))
await db.execute("DELETE FROM automod_ignored WHERE guild_id = ?", (guild_id,))
@@ -768,7 +785,7 @@ class Automod(commands.Cog):
items_str.append(f"**{event}**: {punishment or 'None'}")
if await self.is_anti_nsfw_enabled(guild_id):
items_str.append("**Anti NSFW Links**: Block Message")
async with aiosqlite.connect("db/automod.db") as db:
async with aiosqlite.connect(db_path("automod.db")) as db:
cursor = await db.execute("SELECT log_channel FROM automod_logging WHERE guild_id = ?", (guild_id,))
log_channel_id = await cursor.fetchone()
if log_channel_id and log_channel_id[0]:
@@ -799,7 +816,7 @@ class Automod(commands.Cog):
await ctx.send(view=CV2(f"Automod Settings for {ctx.guild.name}", f"Uhh, looks like your server hasn\'t enabled Automoderation.\n\nCurrent Status: {DISABLE} Disabled\nTo Enable use `{ctx.prefix}automod enable`"))
return
async with aiosqlite.connect("db/automod.db") as db:
async with aiosqlite.connect(db_path("automod.db")) as db:
await db.execute("INSERT OR REPLACE INTO automod_logging (guild_id, log_channel) VALUES (?, ?)", (guild_id, channel.id))
await db.commit()
await ctx.send(view=CV2(f"Automod Settings for {ctx.guild.name}", f"**{TICK} | Automoderation Logging channel set to {channel.mention}.**\n\n➜ Use `{ctx.prefix}automod config` to view current Automod settings."))
@@ -809,7 +826,7 @@ class Automod(commands.Cog):
async def on_guild_remove(self, guild):
guild_id = guild.id
async with aiosqlite.connect("db/automod.db") as db:
async with aiosqlite.connect(db_path("automod.db")) as db:
await db.execute("DELETE FROM automod WHERE guild_id = ?", (guild_id,))
await db.execute("DELETE FROM automod_punishments WHERE guild_id = ?", (guild_id,))
await db.execute("DELETE FROM automod_ignored WHERE guild_id = ?", (guild_id,))

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
import discord
from utils.emoji import CROSS, ICONS_WARNING, TICK
@@ -28,7 +28,7 @@ from utils.cv2 import CV2, build_container
class AutoReaction(commands.Cog):
def __init__(self, bot):
self.bot = bot
self.db_path = 'db/autoreact.db'
self.db_path = db_path('autoreact.db')
self.bot.loop.create_task(self.setup_database())
async def setup_database(self):

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
import discord
from utils.emoji import CROSS, TICK
@@ -25,7 +25,7 @@ from utils.cv2 import CV2, build_container
DB_PATH = "db/autoresponder.db"
DB_PATH = db_path("autoresponder.db")
class AutoResponder(commands.Cog):
def __init__(self, bot):

View File

@@ -1,18 +1,18 @@
# ╔══════════════════════════════════════════════════════════════════╗
# ║ ║
# ║ ░█▀▀░█▀█░█▀▄░█▀▀░█░█ ░█▀▄░█▀▀░█░█░█▀▀
# ║ ░█░░░█░█░█░█░█▀▀░▄▀▄ ░█░█░█▀▀░▀▄▀░▀▀█
# ║ ░▀▀▀░▀▀▀░▀▀░░▀▀▀░▀░▀ ░▀▀░░▀▀▀░░▀░░▀▀▀
# ║ +-+-+-+-+-+-+-+-+
# ║ |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 __future__ import annotations
from utils.db_paths import db_path
import discord
from utils.emoji import CROSS, ICONS_WARNING, TICK
import aiosqlite
@@ -33,7 +33,7 @@ logging.basicConfig(
datefmt="%H:%M:%S",
)
DATABASE_PATH = 'db/autorole.db'
DATABASE_PATH = db_path('autorole.db')
class BasicView(discord.ui.View):
def __init__(self, ctx: commands.Context, timeout=60):

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
import discord
from utils.emoji import CROSS, TICK
@@ -55,7 +55,7 @@ class BlacklistWordSource(menus.ListPageSource):
return embed
DB_PATH = "db/blword.db"
DB_PATH = db_path("blword.db")
async def create_blacklist_table():

Some files were not shown because too many files have changed in this diff Show More