Update "Architecture"

k.eaven committed 2026-10-26 12:10:07 +00:00
1 parent eef0c5f317
commit 2b15333bb6
1 file changed
+190
+190
@@ -0,0 +1,190 @@
# 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
- [Contributing](/Contributing) - Development guidelines