Table of Contents
- Architecture Overview
- System Architecture
- Core Components
- 1. PterodactylBot (pterodisbot.py)
- 2. PterodactylAPI (pterodisbot.py)
- 3. ServerMetricsGraphs (server_metrics_graphs.py)
- 4. ServerMetricsManager (server_metrics_graphs.py)
- 5. ServerStatusView (pterodisbot.py)
- Data Flow
- Configuration System
- Persistent Storage
- Async Architecture
- Error Handling Strategy
- Performance Optimizations
Architecture Overview
The bot follows a modular, async-first architecture designed for reliability, performance, and maintainability.
System Architecture
┌─────────────────────────────────────────────────────────────┐
│ Discord Interface │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ Slash │ │ Button │ │ Status │ │
│ │ Commands │ │ Interactions │ │ Embeds │ │
│ └──────┬───────┘ └──────┬───────┘ └──────┬───────┘ │
└─────────┼──────────────────┼──────────────────┼─────────────┘
│ │ │
▼ ▼ ▼
┌─────────────────────────────────────────────────────────────┐
│ PterodactylBot (Core Orchestrator) │
│ ┌────────────────────────────────────────────────────┐ │
│ │ • Command routing and validation │ │
│ │ • Embed lifecycle management │ │
│ │ • State tracking and change detection │ │
│ │ • Background task scheduling │ │
│ └────────────────────────────────────────────────────┘ │
└───────┬───────────────────────┬─────────────────┬───────────┘
│ │ │
▼ ▼ ▼
┌──────────────┐ ┌──────────────────┐ ┌──────────────┐
│ Pterodactyl │ │ Metrics Manager │ │ Storage │
│ API │ │ │ │ Layer │
│ │ │ • Data tracking │ │ │
│ • Client API │ │ • Graph gen. │ │ • Embed loc. │
│ • App API │ │ • Trend analysis │ │ • State data │
│ • Resource │ │ • FIFO queues │ │ • JSON pers. │
│ monitoring │ │ • Multi-vCPU │ │ │
└──────────────┘ └──────────────────┘ └──────────────┘
│ │
▼ ▼
┌─────────────────────────────────────────────────────────────┐
│ External Systems & Data Stores │
│ ┌──────────────┐ ┌──────────────┐ │
│ │ Pterodactyl │ │ File │ │
│ │ Panel │ │ System │ │
│ └──────────────┘ └──────────────┘ │
└─────────────────────────────────────────────────────────────┘
Core Components
1. PterodactylBot (pterodisbot.py)
Main orchestrator class that coordinates all bot operations.
Responsibilities:
- Discord.py bot initialization and lifecycle
- Slash command routing and validation
- Embed creation, tracking, and lifecycle management
- Background task scheduling and execution
- State management and change detection
- Error handling and recovery
Key Methods:
setup_hook(): Initializes API clients and background tasksget_server_status_embed(): Generates Discord embeds with current server dataupdate_status(): Background task for intelligent embed updatesrefresh_all_embeds(): Complete embed refresh across all channelstrack_new_embed(): Persists embed location data
Design Patterns:
- Observer Pattern: Monitors server state changes
- Strategy Pattern: Different update strategies based on state changes
- Factory Pattern: Creates embeds and views dynamically
2. PterodactylAPI (pterodisbot.py)
Abstraction layer for all Pterodactyl Panel API interactions.
Responsibilities:
- HTTP request management with aiohttp
- API authentication (dual key support)
- Request/response serialization
- Error handling and retry logic
- Rate limit management
API Coverage:
- Client API (
ptlc_*): Server resources, power actions - Application API (
ptla_*): Server lists, allocations, details
Key Features:
- Async/await throughout for non-blocking I/O
- Request locking to prevent race conditions
- Automatic retry with exponential backoff
- Comprehensive error response handling
3. ServerMetricsGraphs (server_metrics_graphs.py)
Time-series data tracking and visualization for individual servers.
Responsibilities:
- Historical data collection (1-minute sliding window)
- FIFO queue management (6 data points max)
- Graph generation using matplotlib
- Multi-vCPU scaling calculations
- Trend analysis and statistics
Graph Features:
- CPU Graph: Dynamic scaling for multi-vCPU servers
- Memory Graph: Adaptive Y-axis based on usage
- Combined Graph: Dual subplot for comprehensive view
- Discord Optimized: Dark theme matching Discord's interface
Data Structure:
# Each data point: (timestamp, cpu_percent, memory_mb)
deque([
(datetime(...), 45.5, 1024.0),
(datetime(...), 50.2, 1100.0),
# ... up to 6 points
], maxlen=6)
4. ServerMetricsManager (server_metrics_graphs.py)
Global coordinator for all server metrics tracking.
Responsibilities:
- Lifecycle management of ServerMetricsGraphs instances
- Server discovery and cleanup
- Bulk operations across all tracked servers
- Memory management
Key Features:
- Lazy initialization of graph instances
- Automatic cleanup of removed servers
- Summary statistics generation
- Thread-safe operations
5. ServerStatusView (pterodisbot.py)
Discord UI component providing interactive server controls.
Responsibilities:
- Button state management
- User authorization and validation
- Power action execution
- Connection info display
Buttons:
- 🟢 Start: Sends
startsignal to server - 🔴 Stop: Sends
stopsignal to server - 🔵 Restart: Sends
restartsignal to server - 📍 Show Address: Displays IP and port
Security:
- Guild ID validation
- Role-based access control
- Interaction-level authorization checks
- Ephemeral responses for sensitive data
Data Flow
Server Status Update Flow
1. Background Task (every 10s)
├─> Fetch all servers from Pterodactyl
├─> Update server cache
└─> For each tracked embed:
├─> Get current resources
├─> Check state changes:
│ ├─> Power state changed? → UPDATE
│ ├─> CPU change >50%? → UPDATE
│ ├─> First check? → UPDATE
│ └─> 10min force update? → UPDATE
├─> If running: Collect metrics
├─> Generate embed + view
├─> Update Discord message
└─> Update state tracking
2. Metrics Collection (running servers only)
├─> Extract CPU/memory data
├─> Add to ServerMetricsGraphs
├─> Check sufficient data (6 points)
└─> Generate graph if available
3. State Tracking
├─> Store: (state, cpu_usage, last_force_update)
├─> Compare with previous state
└─> Determine if update needed
User Interaction Flow
1. User Types /server_status
├─> Guild validation
├─> Fetch all servers
├─> Generate statistics
├─> Create dropdown menu
└─> Send ephemeral response
2. User Selects Server
├─> Validate selection
├─> Check for existing embed
├─> Delete old embed if exists
├─> Create new status embed
├─> Track embed location
└─> Persist to JSON
3. User Clicks Power Button
├─> Interaction check
│ ├─> Verify guild ID
│ └─> Check user role
├─> Send power action to API
├─> Await confirmation
└─> Send ephemeral response
Configuration System
The bot uses a multi-layer configuration system:
1. Environment Variables (Docker/container environments)
↓
2. config.ini file (traditional deployments)
↓
3. Validation layer (startup checks)
↓
4. Runtime constants
Validation Checks:
- Required sections and keys present
- API key prefix validation (
ptlc_andptla_) - Guild ID format (valid integer)
- URL format (includes protocol)
- Raises
ConfigValidationErroron failure
Persistent Storage
Embed Locations (embed/embed_locations.json)
{
"server_abc123": {
"channel_id": "123456789",
"message_id": "987654321"
}
}
Operations:
- Load: On bot startup
- Save: After each embed create/delete
- Cleanup: Automatic on missing messages
Server State Tracking (in-memory)
{
"server_abc123": (
"running", # Current state
45.5, # Last CPU usage
1699123456.0 # Last force update timestamp
)
}
Purpose:
- Change detection for smart updates
- Reduces unnecessary Discord API calls
- Tracks force update intervals
Async Architecture
The bot is built on asyncio for concurrent operations:
# Concurrent API requests
async with asyncio.gather(*[
api.get_server_resources(id1),
api.get_server_resources(id2),
api.get_server_resources(id3)
]):
# Process results
Benefits:
- Non-blocking I/O operations
- Concurrent server status checks
- Responsive to Discord interactions
- Efficient resource utilization
Synchronization:
asyncio.Lock()for API rate limitingasyncio.Lock()for embed update cycles- No blocking operations in event loop
Error Handling Strategy
Levels:
- Graceful Degradation: Continue operating with reduced functionality
- Automatic Retry: Retry failed operations with backoff
- User Notification: Inform users of transient errors
- Logging: Comprehensive error logging for debugging
- Crash Prevention: Catch and handle all exceptions
Example:
try:
resources = await api.get_server_resources(server_id)
except Exception as e:
logger.error(f"Failed to fetch resources: {e}")
# Use cached data or display offline state
return {'attributes': {'current_state': 'offline'}}
Performance Optimizations
1. Smart Update Logic
Only updates embeds when necessary:
- Power state changes (always)
- Significant CPU changes (>50% delta)
- Force update interval (every 10 minutes)
- Initial server checks
Impact: ~90% reduction in Discord API calls
2. FIFO Metric Queues
collections.deque(maxlen=6) automatically rotates old data:
- O(1) append operations
- Automatic memory management
- No manual cleanup needed
3. Request Locking
Prevents concurrent API access:
async with self.lock:
# Only one request at a time
response = await self.session.request(...)
Benefits:
- Avoids rate limits
- Prevents race conditions
- Ensures ordered operations
4. Caching Strategy
- Server list cached between updates
- State tracking prevents redundant checks
- Embed locations loaded once at startup
Support
- Issues: https://git.serendipity.systems/k.eaven/pterodactyl-discord-bot/issues
- Documentation: Check README.md and Wiki
- License: GPL-3.0 (see LICENSE file)
Important Note
This is private git infrastructure. If you want to contribute to any project hosted on this site or create your own repositories here, please email the admin (kimura.eaven@gmail.com) to set up an account for you.
Thank you for contributing to Pterodactyl Discord Bot! 🎉
Your contributions help make Pterodactyl server management more accessible for everyone in the community.
Support
- Issues: https://git.serendipity.systems/k.eaven/pterodactyl-discord-bot/issues
- Documentation: Check README.md and Wiki
- License: GPL-3.0 (see LICENSE file)
Important Note
This is private git infrastructure. If you want to contribute to any project hosted on this site or create your own repositories here, please email the admin (kimura.eaven@gmail.com) to set up an account for you.
Thank you for contributing to Pterodactyl Discord Bot! 🎉
Your contributions help make Pterodactyl server management more accessible for everyone in the community.