From 99cfeec7b5bdd06c069aa8a8e1c205a847616307 Mon Sep 17 00:00:00 2001 From: Eaven Kimura Date: Mon, 26 Oct 2026 13:01:42 +0000 Subject: [PATCH] Update Architecture --- Architecture.md | 379 ++++++++++++++++++++++++------------------------ 1 file changed, 190 insertions(+), 189 deletions(-) diff --git a/Architecture.md b/Architecture.md index 3396feb..6740a9a 100644 --- a/Architecture.md +++ b/Architecture.md @@ -1,190 +1,191 @@ -# Architecture - -## Overview - -Pterodisbot is a modular, asynchronous Discord bot built with Python 3.8+ using the `discord.py` library. It follows a clean architecture pattern with clear separation of concerns across multiple modules. - -## System Architecture - -``` -┌─────────────────────────────────────────────────────────────────┐ -│ Discord Client │ -│ ┌─────────────┐ ┌─────────────┐ ┌─────────────────────────┐ │ -│ │ Slash Cmds │ │ Buttons │ │ Dropdown Menus │ │ -│ └──────┬──────┘ └──────┬──────┘ └───────────┬─────────────┘ │ -└─────────┼────────────────┼──────────────────────┼────────────────┘ - │ │ │ - ▼ ▼ ▼ -┌─────────────────────────────────────────────────────────────────┐ -│ PterodactylBot (commands.Bot) │ -│ ┌───────────────────────────────────────────────────────────┐ │ -│ │ Background Task: update_status (10s interval) │ │ -│ │ • Smart update detection (state changes, CPU, uptime) │ │ -│ │ • Rate limit protection │ │ -│ └───────────────────────────────────────────────────────────┘ │ -└─────────────────────────────┬───────────────────────────────────┘ - │ - ┌─────────────────────┼─────────────────────┐ - ▼ ▼ ▼ -┌───────────────┐ ┌───────────────┐ ┌───────────────┐ -│ EmbedManager │ │ PanelAPI │ │MetricsManager │ -│ │ │ │ │ │ -│ • Create │ │ • Client API │ │ • Data points │ -│ • Update │ │ • App API │ │ • Graphs │ -│ • Track │ │ • Auth │ │ • Trends │ -│ • Persist │ │ • Rate limit │ │ │ -└───────┬───────┘ └───────┬───────┘ └───────┬───────┘ - │ │ │ - ▼ ▼ ▼ -┌───────────────┐ ┌───────────────┐ ┌───────────────┐ -│ JSON Storage │ │Pterodactyl/Pelican│ │ Matplotlib │ -│(embed_locs) │ │ Panel API │ │ (PNG graphs) │ -└───────────────┘ └───────────────┘ └───────────────┘ -``` - -## Module Structure - -| Module | Responsibility | Key Classes | -|--------|---------------|-------------| -| `main.py` | Entry point, logging setup | `main()` | -| `config.py` | Configuration loading/validation | `Config`, `load_config()` | -| `bot.py` | Core bot, commands, background tasks | `PterodactylBot`, `setup_commands()` | -| `api.py` | Pterodactyl/Pelican Panel API client | `PanelAPI` | -| `embeds.py` | Embed creation, tracking, persistence | `EmbedManager` | -| `views.py` | Discord UI components (buttons, dropdowns) | `ServerStatusView`, `ServerDropdown` | -| `metrics.py` | Metrics collection & graph generation | `ServerMetricsManager`, `ServerMetricsGraphs` | -| `models.py` | Pydantic data models | `ServerData`, `ServerResources`, etc. | -| `exceptions.py` | Custom exception hierarchy | `APIError`, `ConfigValidationError`, etc. | -| `logging_config.py` | Logging configuration | `setup_logging()` | -| `generate_config.py` | Config generation from env vars | `generate_config_from_env()` | - -## Data Flow - -### 1. Bot Startup - -``` -main() → load_config() → PterodactylBot() → setup_commands() → bot.start() - ↓ - setup_hook() → api.initialize() - ↓ - embed_manager.load_locations() - ↓ - update_status.start() -``` - -### 2. Status Update Cycle (Every 10s) - -``` -update_status() → api.get_servers() → For each tracked embed: - → api.get_server_resources() - → metrics_manager.add_server_data() (if running) - → Smart update detection: - • Power state changed? → UPDATE - • CPU change >50%? → UPDATE - • First time seeing server? → UPDATE - • Running >10min? → UPDATE (uptime accuracy) - → embed_manager.update_single_embed() - → metrics_manager.generate_combined_graph() - → Discord message.edit() -``` - -### 3. User Interaction Flow - -``` -/server_status command - → api.get_servers() - → Create stats embed + dropdown - → User selects server - → api.get_server_resources() - → Delete old embed (if exists) - → embed_manager.create_server_embed() - → Send new embed with ServerStatusView - → embed_manager.track_embed() - -Button press (Start/Stop/Restart/Show Address) - → ServerStatusView.interaction_check() (guild + role) - → api.send_power_action() or api.get_server_default_allocation() - → Ephemeral response to user -``` - -## Concurrency Model - -- **Async/await** throughout for non-blocking I/O -- **asyncio.Lock** in `PanelAPI._request()` for rate limit protection -- **asyncio.Lock** in `PterodactylBot.update_status` for update cycle serialization -- **deque(maxlen=6)** for automatic metrics rotation (1 min history) -- **Background task** with `@tasks.loop(seconds=10)` for periodic updates - -## Persistence - -- **Embed locations**: JSON file (`embed/embed_locations.json`) -- **Metrics**: In-memory only (last 6 data points = 1 minute) -- **Configuration**: INI file (`config.ini`) or environment variables -- **Logs**: Rotating files (5MB, 3 backups) in `logs/` - -## Security Architecture - -``` -┌────────────────────────────────────────────────────────────┐ -│ Access Control Layers │ -├────────────────────────────────────────────────────────────┤ -│ 1. Guild Restriction (config.allowed_guild_id) │ -│ └─ Checked in: on_interaction, check_allowed_guild, │ -│ ServerStatusView.interaction_check │ -├────────────────────────────────────────────────────────────┤ -│ 2. Role-Based Access ("Game Server User" role) │ -│ └─ Checked in: ServerStatusView.interaction_check │ -├────────────────────────────────────────────────────────────┤ -│ 3. Admin Permissions (Discord Administrator) │ -│ └─ Required for: /refresh_embeds, /purge_embeds │ -└────────────────────────────────────────────────────────────┘ -``` - -## API Integration - -### Dual API Key System - -- **Client API Key** (`ptlc_` / `pacc_`): Server operations (power, resources) -- **Application API Key** (`ptla_` / `papp_`): Admin operations (list servers, details) - -### Supported Panels - -- **Pterodactyl Panel** (standard) -- **Pelican Panel** (fork, uses `pacc_`/`papp_` prefixes) -- Auto-detected via `Config.is_pelican_panel` property - -## Error Handling Strategy - -1. **Validation at startup** - Config validation fails fast -2. **Graceful degradation** - Failed embed updates don't crash the bot -3. **Structured exceptions** - Custom exception types for different failure modes -4. **Comprehensive logging** - DEBUG for operations, ERROR for failures -5. **Automatic cleanup** - Missing embeds removed from tracking - -## Deployment Architectures - -### Traditional - -``` -Python 3.8+ → pip install -r requirements.txt → python main.py -``` - -### Docker - -``` -Dockerfile → docker build → docker run -v config:/app -``` - -### Kubernetes - -``` -Deployment + Secret + PVC → kubectl apply -``` - -## Related Pages - -- [Features](/Features) - Detailed feature breakdown -- [Installation](/Installation) - Deployment guides -- [Configuration](/Configuration) - Config options -- [Usage](/Usage) - Commands and workflows +# Architecture + +## Overview + +Pterodisbot is a modular, asynchronous Discord bot built with Python 3.8+ using the `discord.py` library. It follows a clean architecture pattern with clear separation of concerns across multiple modules. + +## System Architecture + +``` +┌─────────────────────────────────────────────────────────────────┐ +│ Discord Client │ +│ ┌─────────────┐ ┌─────────────┐ ┌─────────────────────────┐ │ +│ │ Slash Cmds │ │ Buttons │ │ Dropdown Menus │ │ +│ └──────┬──────┘ └──────┬──────┘ └───────────┬─────────────┘ │ +└─────────┼────────────────┼──────────────────────┼───────────────┘ + │ │ │ + ▼ ▼ ▼ +┌─────────────────────────────────────────────────────────────────┐ +│ PterodactylBot (commands.Bot) │ +│ ┌───────────────────────────────────────────────────────────┐ │ +│ │ Background Task: update_status (10s interval) │ │ +│ │ • Smart update detection (state changes, CPU, uptime) │ │ +│ │ • Rate limit protection │ │ +│ └───────────────────────────────────────────────────────────┘ │ +└─────────────────────────────┬───────────────────────────────────┘ + │ + ┌─────────────────────┼─────────────────────┐ + ▼ ▼ ▼ +┌───────────────┐ ┌───────────────┐ ┌───────────────┐ +│ EmbedManager │ │ PanelAPI │ │MetricsManager │ +│ │ │ │ │ │ +│ • Create │ │ • Client API │ │ • Data points │ +│ • Update │ │ • App API │ │ • Graphs │ +│ • Track │ │ • Auth │ │ • Trends │ +│ • Persist │ │ • Rate limit │ │ │ +└───────┬───────┘ └───────┬───────┘ └───────┬───────┘ + │ │ │ + ▼ ▼ ▼ +┌───────────────┐ ┌───────────────┐ ┌───────────────┐ +│ JSON Storage │ │ Pterodactyl/ │ │ Matplotlib │ +│ (embed_locs) │ │ Pelican │ │ (PNG graphs) │ +| | | Panel API | | | +└───────────────┘ └───────────────┘ └───────────────┘ +``` + +## Module Structure + +| Module | Responsibility | Key Classes | +|--------|---------------|-------------| +| `main.py` | Entry point, logging setup | `main()` | +| `config.py` | Configuration loading/validation | `Config`, `load_config()` | +| `bot.py` | Core bot, commands, background tasks | `PterodactylBot`, `setup_commands()` | +| `api.py` | Pterodactyl/Pelican Panel API client | `PanelAPI` | +| `embeds.py` | Embed creation, tracking, persistence | `EmbedManager` | +| `views.py` | Discord UI components (buttons, dropdowns) | `ServerStatusView`, `ServerDropdown` | +| `metrics.py` | Metrics collection & graph generation | `ServerMetricsManager`, `ServerMetricsGraphs` | +| `models.py` | Pydantic data models | `ServerData`, `ServerResources`, etc. | +| `exceptions.py` | Custom exception hierarchy | `APIError`, `ConfigValidationError`, etc. | +| `logging_config.py` | Logging configuration | `setup_logging()` | +| `generate_config.py` | Config generation from env vars | `generate_config_from_env()` | + +## Data Flow + +### 1. Bot Startup + +``` +main() → load_config() → PterodactylBot() → setup_commands() → bot.start() + ↓ + setup_hook() → api.initialize() + ↓ + embed_manager.load_locations() + ↓ + update_status.start() +``` + +### 2. Status Update Cycle (Every 10s) + +``` +update_status() → api.get_servers() → For each tracked embed: + → api.get_server_resources() + → metrics_manager.add_server_data() (if running) + → Smart update detection: + • Power state changed? → UPDATE + • CPU change >50%? → UPDATE + • First time seeing server? → UPDATE + • Running >10min? → UPDATE (uptime accuracy) + → embed_manager.update_single_embed() + → metrics_manager.generate_combined_graph() + → Discord message.edit() +``` + +### 3. User Interaction Flow + +``` +/server_status command + → api.get_servers() + → Create stats embed + dropdown + → User selects server + → api.get_server_resources() + → Delete old embed (if exists) + → embed_manager.create_server_embed() + → Send new embed with ServerStatusView + → embed_manager.track_embed() + +Button press (Start/Stop/Restart/Show Address) + → ServerStatusView.interaction_check() (guild + role) + → api.send_power_action() or api.get_server_default_allocation() + → Ephemeral response to user +``` + +## Concurrency Model + +- **Async/await** throughout for non-blocking I/O +- **asyncio.Lock** in `PanelAPI._request()` for rate limit protection +- **asyncio.Lock** in `PterodactylBot.update_status` for update cycle serialization +- **deque(maxlen=6)** for automatic metrics rotation (1 min history) +- **Background task** with `@tasks.loop(seconds=10)` for periodic updates + +## Persistence + +- **Embed locations**: JSON file (`embed/embed_locations.json`) +- **Metrics**: In-memory only (last 6 data points = 1 minute) +- **Configuration**: INI file (`config.ini`) or environment variables +- **Logs**: Rotating files (5MB, 3 backups) in `logs/` + +## Security Architecture + +``` +┌────────────────────────────────────────────────────────────┐ +│ Access Control Layers │ +├────────────────────────────────────────────────────────────┤ +│ 1. Guild Restriction (config.allowed_guild_id) │ +│ └─ Checked in: on_interaction, check_allowed_guild, │ +│ ServerStatusView.interaction_check │ +├────────────────────────────────────────────────────────────┤ +│ 2. Role-Based Access ("Game Server User" role) │ +│ └─ Checked in: ServerStatusView.interaction_check │ +├────────────────────────────────────────────────────────────┤ +│ 3. Admin Permissions (Discord Administrator) │ +│ └─ Required for: /refresh_embeds, /purge_embeds │ +└────────────────────────────────────────────────────────────┘ +``` + +## API Integration + +### Dual API Key System + +- **Client API Key** (`ptlc_` / `pacc_`): Server operations (power, resources) +- **Application API Key** (`ptla_` / `papp_`): Admin operations (list servers, details) + +### Supported Panels + +- **Pterodactyl Panel** (standard) +- **Pelican Panel** (fork, uses `pacc_`/`papp_` prefixes) +- Auto-detected via `Config.is_pelican_panel` property + +## Error Handling Strategy + +1. **Validation at startup** - Config validation fails fast +2. **Graceful degradation** - Failed embed updates don't crash the bot +3. **Structured exceptions** - Custom exception types for different failure modes +4. **Comprehensive logging** - DEBUG for operations, ERROR for failures +5. **Automatic cleanup** - Missing embeds removed from tracking + +## Deployment Architectures + +### Traditional + +``` +Python 3.8+ → pip install -r requirements.txt → python main.py +``` + +### Docker + +``` +Dockerfile → docker build → docker run -v config:/app +``` + +### Kubernetes + +``` +Deployment + Secret + PVC → kubectl apply +``` + +## Related Pages + +- [Features](/Features) - Detailed feature breakdown +- [Installation](/Installation) - Deployment guides +- [Configuration](/Configuration) - Config options +- [Usage](/Usage) - Commands and workflows - [Contributing](/Contributing) - Development guidelines \ No newline at end of file