Files
firefrost-services/services/modpack-version-checker/blueprint-extension/README.md
Claude (Chronicler #63) 7437b4fa7b docs(modpackchecker): Fix namespace in README, add icon to file structure
- Changed troubleshooting namespace to Pterodactyl\Http\Controllers
- Added icon.png to file structure documentation

Signed-off-by: Claude (Chronicler #63) <claude@firefrostgaming.com>
2026-04-06 10:12:23 +00:00

13 KiB
Raw Blame History

ModpackChecker — Pterodactyl Blueprint Extension

Version: 1.0.0
Author: Firefrost Gaming
License: Proprietary (Commercial product for BuiltByBit)

A Pterodactyl Panel extension that checks modpack versions across CurseForge, Modrinth, FTB, and Technic platforms. Shows update status on the dashboard and provides manual version checks from the server console.


Table of Contents

  1. Features
  2. Architecture Overview
  3. File Structure
  4. Installation
  5. Configuration
  6. Usage
  7. Development
  8. API Reference
  9. Troubleshooting
  10. Design Decisions

Features

Dashboard Badge

  • Shows a colored dot next to each server name on the dashboard
  • 🟠 Orange (Fire #FF6B35): Update available
  • 🟢 Teal (Frost #4ECDC4): Up to date
  • Hover for version details tooltip
  • Single API call per page load (cached globally)

Console Widget

  • "Check for Updates" button on each server's console page
  • Real-time version check against platform API
  • Shows modpack name, current version, and latest version

Admin Panel

  • Configure CurseForge API key
  • View extension status
  • (Future: Rate limit settings, notification preferences)

Supported Platforms

Platform ID Type API Key Required Status
CurseForge Numeric project ID Yes Working
Modrinth Project ID or slug No Working
FTB Numeric modpack ID No Working
Technic URL slug No Working

Note: Technic requires a dynamic build number parameter. The extension automatically fetches the current launcher build from Technic's API to avoid 401 errors.


Architecture Overview

┌─────────────────────────────────────────────────────────────────────────────┐
│                           MODPACK VERSION CHECKER                            │
│                            Architecture Diagram                              │
└─────────────────────────────────────────────────────────────────────────────┘

                    ┌─────────────────────────────────────┐
                    │     CRON JOB (runs every 4-6 hrs)   │
                    │     php artisan modpackchecker:check │
                    │                                     │
                    │  • Finds servers with MODPACK_*     │
                    │  • Calls platform APIs one by one   │
                    │  • 2-second delay between calls     │
                    │  • Stores results in database       │
                    └──────────────────┬──────────────────┘
                                       │
                                       ▼
                    ┌─────────────────────────────────────┐
                    │         DATABASE CACHE              │
                    │     modpackchecker_servers table    │
                    │                                     │
                    │  • server_id, server_uuid           │
                    │  • platform, modpack_id             │
                    │  • current_version, latest_version  │
                    │  • update_available (boolean)       │
                    │  • last_checked timestamp           │
                    └──────────────────┬──────────────────┘
                                       │
                    ┌──────────────────┴──────────────────┐
                    │                                     │
                    ▼                                     ▼
    ┌───────────────────────────┐       ┌───────────────────────────┐
    │    DASHBOARD BADGE        │       │    CONSOLE WIDGET         │
    │    (UpdateBadge.tsx)      │       │    (wrapper.tsx)          │
    │                           │       │                           │
    │  • Reads from cache ONLY  │       │  • Manual "Check" button  │
    │  • Never calls external   │       │  • LIVE API call          │
    │  • One API call per page  │       │  • Single server only     │
    │  • Shows 🟠 or 🟢 dot     │       │  • Shows full details     │
    └───────────────────────────┘       └───────────────────────────┘

Why This Architecture?

The Problem: A panel with 50 servers and 20 active users could generate thousands of API calls per day if each dashboard view triggered live checks.

The Solution:

  1. Cron job handles external API calls with rate limiting
  2. Dashboard reads from local cache only
  3. Console provides on-demand checks for specific servers

This was validated by Gemini AI during architectural review.


File Structure

blueprint-extension/
├── README.md                    # This file
├── conf.yml                     # Blueprint configuration
├── build.sh                     # Injection script (runs during blueprint -build)
├── icon.png                     # Extension icon (128x128, Gemini-designed)
│
├── app/                         # Merges into Pterodactyl's app/ via requests.app
│   ├── Console/
│   │   └── Commands/
│   │       └── CheckModpackUpdates.php  # Laravel cron command
│   └── Http/
│       └── Controllers/
│           └── ModpackAPIController.php # API endpoints (manualCheck, getStatus)
│
├── admin/
│   ├── controller.php           # Admin panel logic
│   └── view.blade.php           # Admin panel UI
│
├── database/
│   └── migrations/
│       └── 2026_04_06_000000_create_modpackchecker_servers_table.php
│
├── routes/
│   └── client.php               # API route definitions
│
└── views/
    ├── server/
    │   └── wrapper.tsx          # Console "Check for Updates" widget
    └── dashboard/
        └── UpdateBadge.tsx      # Dashboard status dot component

Why the app/ folder structure?

Blueprint's requests.app field merges the contents of your app/ folder directly into Pterodactyl's app/ directory. This means:

  1. PSR-4 Autoloading: Your classes are automatically found by Laravel's autoloader
  2. Correct Namespaces: Use Pterodactyl\Http\Controllers (not custom Blueprint namespaces)
  3. Case Sensitivity: Linux requires exact folder casing — Controllers/ not controllers/

This architecture was validated through painful debugging and Gemini AI consultation.


Installation

Prerequisites

  • Pterodactyl Panel v1.11+
  • Blueprint Framework (beta-2026-01 or newer)
  • PHP 8.1+
  • Node.js 18+

Steps

  1. Copy extension to Blueprint directory:

    cp -r blueprint-extension /var/www/pterodactyl/.blueprint/extensions/modpackchecker
    chown -R www-data:www-data /var/www/pterodactyl/.blueprint/extensions/modpackchecker
    
  2. Build the extension:

    cd /var/www/pterodactyl
    blueprint -build
    
  3. Compile frontend assets:

    export NODE_OPTIONS=--openssl-legacy-provider
    yarn build:production
    
  4. Run database migration:

    php artisan migrate
    
  5. Restart PHP-FPM:

    systemctl restart php8.3-fpm
    
  6. Set up cron job:

    # Add to /etc/crontab or crontab -e
    0 */6 * * * www-data cd /var/www/pterodactyl && php artisan modpackchecker:check >> /dev/null 2>&1
    

Configuration

Server Egg Variables

For modpack detection, set these variables in your server's egg:

Variable Description Example
MODPACK_PLATFORM Platform name modrinth, curseforge, ftb, technic
MODPACK_ID Platform-specific ID adrenaserver (Modrinth slug)
MODPACK_CURRENT_VERSION Installed version 1.7.0

CurseForge API Key

CurseForge requires an API key. To configure:

  1. Apply for API access at https://docs.curseforge.com/
  2. Go to Admin Panel → Extensions → ModpackChecker
  3. Enter your API key and save

Usage

Dashboard Badge

No action needed — badges appear automatically for servers that:

  • Have MODPACK_PLATFORM egg variable set
  • Have been checked by the cron job at least once

Manual Check

  1. Go to any server's console page
  2. Click "Check for Updates" button
  3. View results showing modpack name and version status

Cron Command

Run manually for testing:

cd /var/www/pterodactyl
php artisan modpackchecker:check

Output:

Starting modpack update check...
Found 12 servers with modpack configuration
Checking: ATM9 Server (a1b2c3d4-...)
  🟠 UPDATE AVAILABLE: All The Mods 9 - 0.2.60
Checking: Vanilla+ (e5f6g7h8-...)
  🟢 Up to date: Vanilla+ - 1.2.0
Modpack update check complete!

Development

Local Development

  1. Enable Blueprint developer mode in admin panel
  2. Make changes in .blueprint/dev/ or .blueprint/extensions/modpackchecker/
  3. Run blueprint -build after changes
  4. Run yarn build:production for frontend changes

Testing API Endpoints

# Manual check (requires auth token)
curl -X POST "https://panel.example.com/api/client/servers/{uuid}/ext/modpackchecker/check" \
  -H "Authorization: Bearer {token}"

# Get all statuses (requires auth token)
curl "https://panel.example.com/api/client/extensions/modpackchecker/status" \
  -H "Authorization: Bearer {token}"

Adding a New Platform

  1. Add check method to ModpackAPIController.php (e.g., checkNewPlatform())
  2. Add to the match() statement in checkVersion()
  3. Add same method to CheckModpackUpdates.php
  4. Update this README

API Reference

POST /api/client/servers/{server}/ext/modpackchecker/check

Manual version check for a specific server. Makes live API call.

Response:

{
    "success": true,
    "platform": "modrinth",
    "modpack_id": "adrenaserver",
    "modpack_name": "Adrenaserver",
    "latest_version": "1.7.0+1.21.1.fabric",
    "status": "checked"
}

GET /api/client/extensions/modpackchecker/status

Get cached status for all servers accessible to the authenticated user.

Response:

{
    "a1b2c3d4-...": {
        "update_available": true,
        "modpack_name": "All The Mods 9",
        "current_version": "0.2.51",
        "latest_version": "0.2.60"
    },
    "e5f6g7h8-...": {
        "update_available": false,
        "modpack_name": "Adrenaserver",
        "current_version": "1.7.0",
        "latest_version": "1.7.0"
    }
}

Troubleshooting

Badge not showing

  1. Check server has MODPACK_PLATFORM variable set
  2. Run cron command manually: php artisan modpackchecker:check
  3. Check modpackchecker_servers table for entries

"CurseForge API key not configured"

  1. Go to Admin → Extensions → ModpackChecker
  2. Enter your CurseForge API key
  3. Key must have mod read permissions

500 errors on check

  1. Check PHP error log: tail -f /var/log/php8.3-fpm.log
  2. Verify controller namespace: Pterodactyl\Http\Controllers
  3. Restart PHP-FPM: systemctl restart php8.3-fpm

Build.sh not running

  1. Ensure file is executable: chmod +x build.sh
  2. Check Blueprint version supports build scripts
  3. Run manually from panel root: bash .blueprint/extensions/modpackchecker/build.sh

Design Decisions

Why cache instead of live checks?

Rate limits. CurseForge allows ~1000 requests/day for personal keys. A busy panel could exhaust that in hours without caching.

Why 2-second sleep in cron?

Prevents burst traffic to APIs. 50 servers × 2 seconds = ~2 minute runtime, which is acceptable for a background job.

Why inline styles in React?

The component is injected into Pterodactyl's build. Adding CSS classes would require modifying their build pipeline. Inline styles are self-contained.

Why separate console widget and dashboard badge?

Different use cases:

  • Dashboard: Quick overview, needs to be fast → cached
  • Console: User wants current info → live API call is acceptable

Credits

Development Team:

  • Architecture design: Gemini AI
  • Implementation: Chroniclers #52, #62, #63 (Claude instances)
  • Project Lead: Michael "Frostystyle" Krause

Part of Firefrost Gaming
Fire + Frost + Foundation = Where Love Builds Legacy 🔥❄️💙