Refactor deploy/push scripts and enhance game docs generator
- Add comprehensive headers to deploy_gsp.sh and push_to_github.sh - Make scripts configurable via environment variables - Update push_to_github.sh to support GITHUB_TOKEN env var - Enhance generate_game_docs.py with: * Command-line argument support (--games, --force, --todo-only) * Extraction of detailed startup parameters from XML * Prevention of overwriting existing files unless --force is used * Comprehensive parameter documentation with options and defaults Co-authored-by: iaretechnician <2749183+iaretechnician@users.noreply.github.com>
This commit is contained in:
parent
d3c83c33b1
commit
f8ae24e87b
4 changed files with 498 additions and 108 deletions
|
|
@ -1,4 +1,40 @@
|
|||
#!/usr/bin/env bash
|
||||
#
|
||||
# GSP Deployment Script
|
||||
# =====================
|
||||
# This script deploys the Game Server Panel (GSP) from GitHub to a web server.
|
||||
#
|
||||
# HOW IT WORKS:
|
||||
# 1. Clones/updates the GSP repository to a staging directory
|
||||
# 2. Syncs files to the web root using rsync (preserving configs)
|
||||
# 3. Sets proper permissions for OGP panel operation
|
||||
#
|
||||
# CONFIGURATION:
|
||||
# All settings can be configured via environment variables or by editing
|
||||
# the defaults in the "Config" section below.
|
||||
#
|
||||
# ENVIRONMENT VARIABLES:
|
||||
# - REPO_URL: Git repository URL (default: https://github.com/GameServerPanel/GSP.git)
|
||||
# - STAGE_DIR: Staging directory for git clone (default: $HOME/gsp_stage)
|
||||
# - WEB_ROOT: Live web server directory (default: /var/www/html/panel)
|
||||
# - OWNER: File owner user (default: www-data)
|
||||
# - GROUP: File owner group (default: www-data)
|
||||
# - SUDO: Command prefix for privilege escalation (default: sudo, set empty to skip)
|
||||
# - DRY_RUN: Set to 1 to test without making changes (default: 0)
|
||||
#
|
||||
# EXAMPLE USAGE:
|
||||
# # Use defaults:
|
||||
# ./deploy_gsp.sh
|
||||
#
|
||||
# # Custom web root:
|
||||
# WEB_ROOT=/home/panel/public_html ./deploy_gsp.sh
|
||||
#
|
||||
# # Dry run to test:
|
||||
# DRY_RUN=1 ./deploy_gsp.sh
|
||||
#
|
||||
# # Different user/group:
|
||||
# OWNER=apache GROUP=apache ./deploy_gsp.sh
|
||||
#
|
||||
set -Eeuo pipefail
|
||||
umask 022
|
||||
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@
|
|||
<h2 id="quick-info">Quick Info</h2>
|
||||
<div style="background: #1e3a5f; padding: 20px; border-left: 4px solid #3b82f6; margin: 20px 0; border-radius: 4px;">
|
||||
<ul style="color: #e5e7eb; line-height: 1.8; margin: 0;">
|
||||
<li><strong style="color: #ffffff;">Default Port:</strong> <code style="background: #0f172a; padding: 2px 6px; border-radius: 3px; color: #a5b4fc;">28015</code></li>
|
||||
<li><strong style="color: #ffffff;">Default Port:</strong> <code style="background: #0f172a; padding: 2px 6px; border-radius: 3px; color: #a5b4fc;">Varies (see configuration)</code></li>
|
||||
<li><strong style="color: #ffffff;">Protocol:</strong> TCP/UDP</li>
|
||||
<li><strong style="color: #ffffff;">Minimum RAM:</strong> 1GB</li>
|
||||
<li><strong style="color: #ffffff;">Engine:</strong> Various</li>
|
||||
|
|
@ -38,33 +38,7 @@
|
|||
<h2 id="ports">🔌 Network Ports</h2>
|
||||
<div style="background: #1e3a5f; padding: 20px; border-left: 4px solid #3b82f6; margin: 20px 0; border-radius: 4px;">
|
||||
<h3 style="color: #ffffff; margin-top: 0;">Required Ports</h3>
|
||||
<p style="color: #e5e7eb;">The following ports are used by this game server:</p>
|
||||
<table style="width: 100%; color: #e5e7eb; border-collapse: collapse;">
|
||||
<thead>
|
||||
<tr style="background: #0f172a;">
|
||||
<th style="padding: 10px; text-align: left; color: #ffffff;">Port</th>
|
||||
<th style="padding: 10px; text-align: left; color: #ffffff;">Protocol</th>
|
||||
<th style="padding: 10px; text-align: left; color: #ffffff;">Purpose</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr style="border-bottom: 1px solid #374151;">
|
||||
<td style="padding: 10px;"><code style="background: #0f172a; padding: 2px 6px; border-radius: 3px;">28015</code></td>
|
||||
<td style="padding: 10px;">UDP</td>
|
||||
<td style="padding: 10px;">Game port</td>
|
||||
</tr>
|
||||
<tr style="border-bottom: 1px solid #374151;">
|
||||
<td style="padding: 10px;"><code style="background: #0f172a; padding: 2px 6px; border-radius: 3px;">28016</code></td>
|
||||
<td style="padding: 10px;">TCP</td>
|
||||
<td style="padding: 10px;">RCON</td>
|
||||
</tr>
|
||||
<tr style="border-bottom: 1px solid #374151;">
|
||||
<td style="padding: 10px;"><code style="background: #0f172a; padding: 2px 6px; border-radius: 3px;">28082</code></td>
|
||||
<td style="padding: 10px;">TCP</td>
|
||||
<td style="padding: 10px;">Web panel (if enabled)</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<p style="color: #e5e7eb;">The Rust server typically uses a configurable port. Check your server configuration files for the specific port settings.</p>
|
||||
|
||||
<h3 style="color: #ffffff; margin-top: 20px;">Firewall Configuration</h3>
|
||||
<p style="color: #e5e7eb;">Allow server ports through your firewall:</p>
|
||||
|
|
@ -194,68 +168,116 @@ setadminpassword [password]
|
|||
|
||||
<h2 id="parameters">⚙️ Startup Parameters</h2>
|
||||
|
||||
<h3>Basic Startup</h3>
|
||||
<pre><code># Generic startup command structure
|
||||
./server_executable [parameters]
|
||||
</code></pre>
|
||||
<h3>Command Line Template</h3>
|
||||
<p>The server uses the following command line template:</p>
|
||||
<pre><code>-batchmode -nographics +server.ip %IP% %PORT% %QUERY_PORT% %PLAYERS% %HOSTNAME% %IDENTITY% %DESCRIPTION% %WORLDSIZE% %SEED% %SALT% %TICKRATE% %MAP% %BCK% %SAVEINTERNAL% %SECURE% %RCONWEB% %CONTROL_PASSWORD% -logfile output.txt</code></pre>
|
||||
|
||||
<h3>Common Parameters</h3>
|
||||
<ul>
|
||||
<li><code>-port [number]</code> - Set the server port</li>
|
||||
<li><code>-maxplayers [number]</code> - Maximum player slots</li>
|
||||
<li><code>-map [name]</code> - Starting map/level</li>
|
||||
<li><code>-console</code> - Enable console output</li>
|
||||
<li><code>-nographics</code> - Run without graphics (headless mode)</li>
|
||||
</ul>
|
||||
<h3>Available Startup Parameters</h3>
|
||||
<p>The following parameters can be configured when starting the server:</p>
|
||||
|
||||
<h3>Creating a Start Script</h3>
|
||||
<div style="background: #1e3a5f; padding: 20px; border-left: 4px solid #3b82f6; margin: 20px 0; border-radius: 4px;">
|
||||
|
||||
<p><strong>Linux (start.sh):</strong></p>
|
||||
<pre><code>#!/bin/bash
|
||||
cd /path/to/server
|
||||
./server_executable [parameters] 2>&1 | tee server.log
|
||||
</code></pre>
|
||||
<pre><code>chmod +x start.sh
|
||||
./start.sh
|
||||
</code></pre>
|
||||
<div style="margin-bottom: 20px; padding-bottom: 20px; border-bottom: 1px solid #374151;">
|
||||
<h4 style="color: #ffffff; margin-top: 0;">
|
||||
<code style="background: #0f172a; padding: 4px 8px; border-radius: 3px; color: #a5b4fc;">+server.identity</code>
|
||||
<span style="color: #e5e7eb; font-weight: normal; font-size: 0.9em;"> - +server.identity</span>
|
||||
</h4>
|
||||
<p style="color: #e5e7eb; margin: 10px 0;">Changes path to your server data (e.g. rust/server/my_server_identity).</p>
|
||||
<p style="color: #fbbf24;"><strong>Default:</strong> <code style="background: #0f172a; padding: 2px 6px; border-radius: 3px;">server_identity</code></p>
|
||||
</div>
|
||||
|
||||
<p><strong>Windows (start.bat):</strong></p>
|
||||
<pre><code>@echo off
|
||||
cd /d "%~dp0"
|
||||
server_executable.exe [parameters]
|
||||
pause
|
||||
</code></pre>
|
||||
<div style="margin-bottom: 20px; padding-bottom: 20px; border-bottom: 1px solid #374151;">
|
||||
<h4 style="color: #ffffff; margin-top: 0;">
|
||||
<code style="background: #0f172a; padding: 4px 8px; border-radius: 3px; color: #a5b4fc;">+server.description</code>
|
||||
<span style="color: #e5e7eb; font-weight: normal; font-size: 0.9em;"> - +server.description</span>
|
||||
</h4>
|
||||
<p style="color: #e5e7eb; margin: 10px 0;">Server Description shown on server browser</p>
|
||||
<p style="color: #fbbf24;"><strong>Default:</strong> <code style="background: #0f172a; padding: 2px 6px; border-radius: 3px;">Plain old Rust Server</code></p>
|
||||
</div>
|
||||
|
||||
<h3>Running as a Service</h3>
|
||||
<div style="margin-bottom: 20px; padding-bottom: 20px; border-bottom: 1px solid #374151;">
|
||||
<h4 style="color: #ffffff; margin-top: 0;">
|
||||
<code style="background: #0f172a; padding: 4px 8px; border-radius: 3px; color: #a5b4fc;">+server.worldsize</code>
|
||||
<span style="color: #e5e7eb; font-weight: normal; font-size: 0.9em;"> - +server.worldsize</span>
|
||||
</h4>
|
||||
<p style="color: #e5e7eb; margin: 10px 0;">Defines the size of the map generated (min 1000, max 8000).</p>
|
||||
<p style="color: #fbbf24;"><strong>Default:</strong> <code style="background: #0f172a; padding: 2px 6px; border-radius: 3px;">1000</code></p>
|
||||
</div>
|
||||
|
||||
<p><strong>Linux (systemd):</strong></p>
|
||||
<pre><code># Create service file: /etc/systemd/system/gameserver.service
|
||||
[Unit]
|
||||
Description=Rust Server
|
||||
After=network.target
|
||||
<div style="margin-bottom: 20px; padding-bottom: 20px; border-bottom: 1px solid #374151;">
|
||||
<h4 style="color: #ffffff; margin-top: 0;">
|
||||
<code style="background: #0f172a; padding: 4px 8px; border-radius: 3px; color: #a5b4fc;">+server.seed</code>
|
||||
<span style="color: #e5e7eb; font-weight: normal; font-size: 0.9em;"> - +server.seed</span>
|
||||
</h4>
|
||||
<p style="color: #e5e7eb; margin: 10px 0;">Defines the map generation seed.</p>
|
||||
<p style="color: #fbbf24;"><strong>Default:</strong> <code style="background: #0f172a; padding: 2px 6px; border-radius: 3px;">0</code></p>
|
||||
</div>
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User=gameserver
|
||||
WorkingDirectory=/home/gameserver/server
|
||||
ExecStart=/home/gameserver/server/start.sh
|
||||
Restart=on-failure
|
||||
RestartSec=10
|
||||
<div style="margin-bottom: 20px; padding-bottom: 20px; border-bottom: 1px solid #374151;">
|
||||
<h4 style="color: #ffffff; margin-top: 0;">
|
||||
<code style="background: #0f172a; padding: 4px 8px; border-radius: 3px; color: #a5b4fc;">+server.salt</code>
|
||||
<span style="color: #e5e7eb; font-weight: normal; font-size: 0.9em;"> - +server.salt</span>
|
||||
</h4>
|
||||
<p style="color: #e5e7eb; margin: 10px 0;">Defines the randomization to mining resources.</p>
|
||||
<p style="color: #fbbf24;"><strong>Default:</strong> <code style="background: #0f172a; padding: 2px 6px; border-radius: 3px;">0</code></p>
|
||||
</div>
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
</code></pre>
|
||||
<div style="margin-bottom: 20px; padding-bottom: 20px; border-bottom: 1px solid #374151;">
|
||||
<h4 style="color: #ffffff; margin-top: 0;">
|
||||
<code style="background: #0f172a; padding: 4px 8px; border-radius: 3px; color: #a5b4fc;">+server.tickrate</code>
|
||||
<span style="color: #e5e7eb; font-weight: normal; font-size: 0.9em;"> - +server.tickrate</span>
|
||||
</h4>
|
||||
<p style="color: #e5e7eb; margin: 10px 0;">Defines the server tickrate (going higher than 30 is not recommended).</p>
|
||||
<p style="color: #fbbf24;"><strong>Default:</strong> <code style="background: #0f172a; padding: 2px 6px; border-radius: 3px;">30</code></p>
|
||||
</div>
|
||||
|
||||
<pre><code># Enable and start service
|
||||
sudo systemctl daemon-reload
|
||||
sudo systemctl enable gameserver
|
||||
sudo systemctl start gameserver
|
||||
sudo systemctl status gameserver
|
||||
</code></pre>
|
||||
<div style="margin-bottom: 20px; padding-bottom: 20px; border-bottom: 1px solid #374151;">
|
||||
<h4 style="color: #ffffff; margin-top: 0;">
|
||||
<code style="background: #0f172a; padding: 4px 8px; border-radius: 3px; color: #a5b4fc;">+server.level</code>
|
||||
<span style="color: #e5e7eb; font-weight: normal; font-size: 0.9em;"> - +server.level</span>
|
||||
</h4>
|
||||
<p style="color: #e5e7eb; margin: 10px 0;">Defines the map of the server.</p>
|
||||
<p style="color: #e5e7eb;"><strong>Options:</strong></p>
|
||||
<ul style="color: #e5e7eb; margin-left: 20px;">
|
||||
<li><code style="background: #0f172a; padding: 2px 6px; border-radius: 3px; color: #a5b4fc;">Barren</code> - Barren</li>
|
||||
<li><code style="background: #0f172a; padding: 2px 6px; border-radius: 3px; color: #a5b4fc;">CraggyIsland</code> - Craggy Island</li>
|
||||
<li><code style="background: #0f172a; padding: 2px 6px; border-radius: 3px; color: #a5b4fc;">HapisIsland</code> - Hapis Island</li>
|
||||
<li><code style="background: #0f172a; padding: 2px 6px; border-radius: 3px; color: #a5b4fc;">Procedural Map</code> - Procedural Map</li>
|
||||
<li><code style="background: #0f172a; padding: 2px 6px; border-radius: 3px; color: #a5b4fc;">SavasIsland</code> - Savas Island</li>
|
||||
<li><code style="background: #0f172a; padding: 2px 6px; border-radius: 3px; color: #a5b4fc;">SavasIsland_koth</code> - Savas Island KoTH</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<h2 id="troubleshooting">🔧 Troubleshooting</h2>
|
||||
<div style="margin-bottom: 20px; padding-bottom: 20px; border-bottom: 1px solid #374151;">
|
||||
<h4 style="color: #ffffff; margin-top: 0;">
|
||||
<code style="background: #0f172a; padding: 4px 8px; border-radius: 3px; color: #a5b4fc;">+backup</code>
|
||||
<span style="color: #e5e7eb; font-weight: normal; font-size: 0.9em;"> - +backup</span>
|
||||
</h4>
|
||||
<p style="color: #e5e7eb; margin: 10px 0;">Enable automatic backups.</p>
|
||||
</div>
|
||||
|
||||
<h3>Server Won't Start</h3>
|
||||
<div style="margin-bottom: 20px; padding-bottom: 20px; border-bottom: 1px solid #374151;">
|
||||
<h4 style="color: #ffffff; margin-top: 0;">
|
||||
<code style="background: #0f172a; padding: 4px 8px; border-radius: 3px; color: #a5b4fc;">+server.saveinterval</code>
|
||||
<span style="color: #e5e7eb; font-weight: normal; font-size: 0.9em;"> - +server.saveinterval</span>
|
||||
</h4>
|
||||
<p style="color: #e5e7eb; margin: 10px 0;">Interval between the server saves the map.</p>
|
||||
<p style="color: #fbbf24;"><strong>Default:</strong> <code style="background: #0f172a; padding: 2px 6px; border-radius: 3px;">600</code></p>
|
||||
</div>
|
||||
|
||||
<div style="margin-bottom: 20px; padding-bottom: 20px; border-bottom: 1px solid #374151;">
|
||||
<h4 style="color: #ffffff; margin-top: 0;">
|
||||
<code style="background: #0f172a; padding: 4px 8px; border-radius: 3px; color: #a5b4fc;">+rcon.web</code>
|
||||
<span style="color: #e5e7eb; font-weight: normal; font-size: 0.9em;"> - +rcon.web</span>
|
||||
</h4>
|
||||
<p style="color: #e5e7eb; margin: 10px 0;">If set to enabled, use websocket RCON. If set to disabled, use legacy source engine RCON.</p>
|
||||
<p style="color: #e5e7eb;"><strong>Options:</strong></p>
|
||||
<ul style="color: #e5e7eb; margin-left: 20px;">
|
||||
<li><code style="background: #0f172a; padding: 2px 6px; border-radius: 3px; color: #a5b4fc;">0</code> - Disabled</li>
|
||||
<li><code style="background: #0f172a; padding: 2px 6px; border-radius: 3px; color: #a5b4fc;">1</code> - Enabled</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h4>Check Server Logs</h4>
|
||||
<pre><code># View recent log entries
|
||||
|
|
|
|||
|
|
@ -1,26 +1,82 @@
|
|||
#!/usr/bin/env bash
|
||||
#
|
||||
# GSP GitHub Push Script
|
||||
# ======================
|
||||
# This script commits local changes in your GSP panel directory and pushes
|
||||
# them to GitHub via a Pull Request.
|
||||
#
|
||||
# HOW IT WORKS:
|
||||
# 1. Initializes git in the panel directory (if needed)
|
||||
# 2. Commits all changes (excluding sensitive files like config.inc.php)
|
||||
# 3. Creates a timestamped branch
|
||||
# 4. Attempts to push to upstream repo (requires write access)
|
||||
# 5. If no write access, creates/uses a fork and submits PR from there
|
||||
#
|
||||
# CONFIGURATION:
|
||||
# Configure settings via environment variables or by editing the defaults below.
|
||||
#
|
||||
# ENVIRONMENT VARIABLES:
|
||||
# - PANEL_DIR: Path to your GSP panel installation (default: /var/www/html/panel)
|
||||
# - TOKEN_FILE: File containing GitHub Personal Access Token (default: ~/.github-token)
|
||||
# - GITHUB_TOKEN: GitHub token directly (used if TOKEN_FILE doesn't exist)
|
||||
# - UPSTREAM_REPO: Target repository in "owner/repo" format (default: GameServerPanel/GSP)
|
||||
# - BR_PREFIX: Branch name prefix for PRs (default: panel-sync)
|
||||
# - GIT_USER_NAME: Git commit author name (default: Server Sync Bot)
|
||||
# - GIT_USER_EMAIL: Git commit author email (default: server-sync@local)
|
||||
#
|
||||
# GITHUB TOKEN SETUP:
|
||||
# You need a GitHub Personal Access Token with 'repo' scope.
|
||||
# Create one at: https://github.com/settings/tokens
|
||||
#
|
||||
# Option 1: Store in file (recommended):
|
||||
# echo "your_token_here" > ~/.github-token
|
||||
# chmod 600 ~/.github-token
|
||||
#
|
||||
# Option 2: Use environment variable:
|
||||
# export GITHUB_TOKEN="your_token_here"
|
||||
#
|
||||
# EXAMPLE USAGE:
|
||||
# # Use defaults:
|
||||
# ./push_to_github.sh
|
||||
#
|
||||
# # Custom panel directory:
|
||||
# PANEL_DIR=/home/panel/public_html ./push_to_github.sh
|
||||
#
|
||||
# # Using environment token:
|
||||
# GITHUB_TOKEN="ghp_xxxx" ./push_to_github.sh
|
||||
#
|
||||
set -Eeuo pipefail
|
||||
umask 022
|
||||
|
||||
# ---------- HARD-CODED PROJECT SETTINGS ----------
|
||||
PANEL_DIR="/var/www/html/panel"
|
||||
TOKEN_FILE="/home/gameserver/git.token"
|
||||
# ---------- CONFIGURABLE SETTINGS ----------
|
||||
PANEL_DIR="${PANEL_DIR:-/var/www/html/panel}"
|
||||
TOKEN_FILE="${TOKEN_FILE:-$HOME/.github-token}"
|
||||
|
||||
UPSTREAM_REPO="GameServerPanel/GSP" # owner/repo
|
||||
UPSTREAM_REPO="${UPSTREAM_REPO:-GameServerPanel/GSP}" # owner/repo
|
||||
UPSTREAM_URL="https://github.com/${UPSTREAM_REPO}.git"
|
||||
|
||||
BR_PREFIX="panel-sync" # branch prefix for PRs
|
||||
GIT_USER_NAME="Server Sync Bot"
|
||||
GIT_USER_EMAIL="server-sync@local"
|
||||
BR_PREFIX="${BR_PREFIX:-panel-sync}" # branch prefix for PRs
|
||||
GIT_USER_NAME="${GIT_USER_NAME:-Server Sync Bot}"
|
||||
GIT_USER_EMAIL="${GIT_USER_EMAIL:-server-sync@local}"
|
||||
|
||||
log(){ printf '[%s] %s\n' "$(date +'%F %T')" "$*"; }
|
||||
die(){ echo "ERROR: $*" >&2; exit 1; }
|
||||
|
||||
# ---------- PRECHECKS ----------
|
||||
[[ -d "$PANEL_DIR" ]] || die "Panel dir not found: $PANEL_DIR"
|
||||
[[ -s "$TOKEN_FILE" ]] || die "Token file missing/empty: $TOKEN_FILE"
|
||||
TOKEN="$(<"$TOKEN_FILE")"
|
||||
[[ ${#TOKEN} -ge 10 ]] || die "Token in $TOKEN_FILE looks invalid"
|
||||
|
||||
# Try to get token from file or environment
|
||||
TOKEN=""
|
||||
if [[ -s "$TOKEN_FILE" ]]; then
|
||||
TOKEN="$(<"$TOKEN_FILE")"
|
||||
elif [[ -n "${GITHUB_TOKEN:-}" ]]; then
|
||||
TOKEN="$GITHUB_TOKEN"
|
||||
else
|
||||
die "GitHub token not found. Set GITHUB_TOKEN env var or create $TOKEN_FILE with your token.
|
||||
Get a token at: https://github.com/settings/tokens (requires 'repo' scope)"
|
||||
fi
|
||||
|
||||
[[ ${#TOKEN} -ge 10 ]] || die "Token looks invalid (too short)"
|
||||
|
||||
cd "$PANEL_DIR"
|
||||
if [[ ! -d ".git" ]]; then
|
||||
|
|
|
|||
|
|
@ -1,8 +1,42 @@
|
|||
#!/usr/bin/env python3
|
||||
"""
|
||||
Comprehensive Game Server Documentation Generator for GSP
|
||||
Generates PHP documentation files for all games in the "todo" category
|
||||
Based on the Minecraft template structure
|
||||
|
||||
This script generates PHP documentation files for game servers in the GSP billing module.
|
||||
|
||||
USAGE:
|
||||
# Generate docs for all incomplete games:
|
||||
python3 generate_game_docs.py
|
||||
|
||||
# Generate docs for specific game(s):
|
||||
python3 generate_game_docs.py --games minecraft csgo rust
|
||||
|
||||
# Regenerate docs (overwrite existing):
|
||||
python3 generate_game_docs.py --games minecraft --force
|
||||
|
||||
# Process all "todo" category games:
|
||||
python3 generate_game_docs.py --todo-only
|
||||
|
||||
OPTIONS:
|
||||
--games GAME1 GAME2 ... Generate docs for specific game folder names
|
||||
--force Overwrite existing documentation files
|
||||
--todo-only Only process games with category="todo"
|
||||
--help Show this help message
|
||||
|
||||
The generator extracts information from:
|
||||
- XML configurations (modules/config_games/server_configs/*.xml)
|
||||
- YAML knowledgepack (modules/billing/docs/gameserver_knowledgepack_v2.yaml)
|
||||
- Existing metadata.json files
|
||||
|
||||
Generated documentation includes:
|
||||
- Quick info (ports, RAM, Steam App ID)
|
||||
- Network ports and firewall configuration
|
||||
- Installation steps with SteamCMD commands
|
||||
- Server configuration files and settings
|
||||
- Detailed startup parameters from XML
|
||||
- Comprehensive troubleshooting guide
|
||||
- Performance optimization tips
|
||||
- Security best practices
|
||||
"""
|
||||
|
||||
import os
|
||||
|
|
@ -10,6 +44,7 @@ import sys
|
|||
import json
|
||||
import yaml
|
||||
import re
|
||||
import argparse
|
||||
from pathlib import Path
|
||||
from datetime import datetime
|
||||
import xml.etree.ElementTree as ET
|
||||
|
|
@ -115,6 +150,68 @@ class GameDocGenerator:
|
|||
|
||||
return ports
|
||||
|
||||
def extract_startup_parameters_from_xml(self, xml_root):
|
||||
"""Extract detailed startup parameters from XML server_params section"""
|
||||
startup_params = []
|
||||
|
||||
# Get CLI template and params
|
||||
cli_template = xml_root.find('cli_template')
|
||||
cli_template_text = cli_template.text if cli_template is not None else ""
|
||||
|
||||
cli_params_elem = xml_root.find('cli_params')
|
||||
cli_params_info = {}
|
||||
if cli_params_elem is not None:
|
||||
for param in cli_params_elem.findall('cli_param'):
|
||||
param_id = param.get('id', '')
|
||||
cli_string = param.get('cli_string', '')
|
||||
options = param.get('options', '')
|
||||
if param_id:
|
||||
cli_params_info[param_id] = {
|
||||
'cli_string': cli_string,
|
||||
'options': options
|
||||
}
|
||||
|
||||
# Extract server_params - these are the configurable startup parameters
|
||||
server_params = xml_root.find('server_params')
|
||||
if server_params is not None:
|
||||
for param in server_params.findall('param'):
|
||||
param_key = param.get('key', '')
|
||||
param_id = param.get('id', '')
|
||||
param_type = param.get('type', 'text')
|
||||
|
||||
# Get caption and description
|
||||
caption_elem = param.find('caption')
|
||||
desc_elem = param.find('desc')
|
||||
default_elem = param.find('default')
|
||||
|
||||
caption = caption_elem.text if caption_elem is not None else param_key
|
||||
description = desc_elem.text if desc_elem is not None else "No description available"
|
||||
default_value = default_elem.text if default_elem is not None else None
|
||||
|
||||
# For select type, get options
|
||||
options = []
|
||||
if param_type == 'select':
|
||||
for option in param.findall('option'):
|
||||
opt_value = option.get('value', '')
|
||||
opt_text = option.text if option.text else opt_value
|
||||
options.append({'value': opt_value, 'text': opt_text})
|
||||
|
||||
startup_params.append({
|
||||
'key': param_key,
|
||||
'id': param_id,
|
||||
'type': param_type,
|
||||
'caption': caption,
|
||||
'description': description,
|
||||
'default': default_value,
|
||||
'options': options
|
||||
})
|
||||
|
||||
return {
|
||||
'cli_template': cli_template_text,
|
||||
'cli_params': cli_params_info,
|
||||
'server_params': startup_params
|
||||
}
|
||||
|
||||
def extract_config_files_from_xml(self, xml_root):
|
||||
"""Extract configuration file paths from XML"""
|
||||
config_files = []
|
||||
|
|
@ -139,15 +236,17 @@ class GameDocGenerator:
|
|||
kb_info = self.get_game_info_from_knowledgepack(game_name)
|
||||
xml_config = self.get_xml_config(folder_name)
|
||||
|
||||
# Extract ports and configs
|
||||
# Extract ports, configs, and startup parameters
|
||||
ports_info = []
|
||||
config_files = []
|
||||
startup_params_data = {}
|
||||
if xml_config is not None:
|
||||
ports_info = self.extract_ports_from_xml(xml_config)
|
||||
config_files = self.extract_config_files_from_xml(xml_config)
|
||||
startup_params_data = self.extract_startup_parameters_from_xml(xml_config)
|
||||
|
||||
# Build the PHP document
|
||||
php_content = self.build_php_content(game_name, folder_name, kb_info, xml_config, ports_info, config_files)
|
||||
php_content = self.build_php_content(game_name, folder_name, kb_info, xml_config, ports_info, config_files, startup_params_data)
|
||||
|
||||
return php_content
|
||||
|
||||
|
|
@ -180,7 +279,7 @@ class GameDocGenerator:
|
|||
|
||||
return 'N/A'
|
||||
|
||||
def build_php_content(self, game_name, folder_name, kb_info, xml_config, ports_info, config_files):
|
||||
def build_php_content(self, game_name, folder_name, kb_info, xml_config, ports_info, config_files, startup_params_data):
|
||||
"""Build the complete PHP documentation content"""
|
||||
|
||||
# Extract data from various sources
|
||||
|
|
@ -495,7 +594,67 @@ setadminpassword [password]
|
|||
</code></pre>
|
||||
|
||||
<h2 id="parameters">⚙️ Startup Parameters</h2>
|
||||
'''
|
||||
|
||||
# Add detailed startup parameters from XML if available
|
||||
if startup_params_data and startup_params_data.get('server_params'):
|
||||
server_params = startup_params_data['server_params']
|
||||
cli_template = startup_params_data.get('cli_template', '')
|
||||
|
||||
if cli_template:
|
||||
php_doc += f'''
|
||||
<h3>Command Line Template</h3>
|
||||
<p>The server uses the following command line template:</p>
|
||||
<pre><code>{cli_template}</code></pre>
|
||||
'''
|
||||
|
||||
php_doc += '''
|
||||
<h3>Available Startup Parameters</h3>
|
||||
<p>The following parameters can be configured when starting the server:</p>
|
||||
|
||||
<div style="background: #1e3a5f; padding: 20px; border-left: 4px solid #3b82f6; margin: 20px 0; border-radius: 4px;">
|
||||
'''
|
||||
for param in server_params:
|
||||
param_key = param['key']
|
||||
caption = param['caption']
|
||||
description = param['description']
|
||||
param_type = param['type']
|
||||
default = param.get('default')
|
||||
options = param.get('options', [])
|
||||
|
||||
# Clean HTML from description
|
||||
description_clean = re.sub(r'<[^>]+>', '', description) if description else "No description available"
|
||||
|
||||
php_doc += f'''
|
||||
<div style="margin-bottom: 20px; padding-bottom: 20px; border-bottom: 1px solid #374151;">
|
||||
<h4 style="color: #ffffff; margin-top: 0;">
|
||||
<code style="background: #0f172a; padding: 4px 8px; border-radius: 3px; color: #a5b4fc;">{param_key}</code>
|
||||
<span style="color: #e5e7eb; font-weight: normal; font-size: 0.9em;"> - {caption}</span>
|
||||
</h4>
|
||||
<p style="color: #e5e7eb; margin: 10px 0;">{description_clean}</p>
|
||||
'''
|
||||
|
||||
if param_type == 'select' and options:
|
||||
php_doc += ''' <p style="color: #e5e7eb;"><strong>Options:</strong></p>
|
||||
<ul style="color: #e5e7eb; margin-left: 20px;">
|
||||
'''
|
||||
for opt in options:
|
||||
php_doc += f''' <li><code style="background: #0f172a; padding: 2px 6px; border-radius: 3px; color: #a5b4fc;">{opt['value']}</code> - {opt['text']}</li>\n'''
|
||||
php_doc += ''' </ul>
|
||||
'''
|
||||
|
||||
if default:
|
||||
php_doc += f''' <p style="color: #fbbf24;"><strong>Default:</strong> <code style="background: #0f172a; padding: 2px 6px; border-radius: 3px;">{default}</code></p>
|
||||
'''
|
||||
|
||||
php_doc += ''' </div>
|
||||
'''
|
||||
|
||||
php_doc += '''</div>
|
||||
'''
|
||||
else:
|
||||
# Fallback to generic parameters if no XML data
|
||||
php_doc += '''
|
||||
<h3>Basic Startup</h3>
|
||||
'''
|
||||
|
||||
|
|
@ -893,7 +1052,102 @@ sudo ufw enable
|
|||
|
||||
return processed, errors
|
||||
|
||||
def process_specific_games(self, game_names, force_overwrite=False):
|
||||
"""Process specific game folders by name"""
|
||||
processed = 0
|
||||
skipped = 0
|
||||
errors = []
|
||||
|
||||
for game_name in game_names:
|
||||
folder = self.docs_dir / game_name
|
||||
|
||||
if not folder.is_dir():
|
||||
error_msg = f"Game folder not found: {game_name}"
|
||||
print(f" ✗ {error_msg}")
|
||||
errors.append(error_msg)
|
||||
continue
|
||||
|
||||
metadata_file = folder / 'metadata.json'
|
||||
index_file = folder / 'index.php'
|
||||
|
||||
if not metadata_file.exists():
|
||||
error_msg = f"metadata.json not found for {game_name}"
|
||||
print(f" ✗ {error_msg}")
|
||||
errors.append(error_msg)
|
||||
continue
|
||||
|
||||
try:
|
||||
# Read metadata
|
||||
with open(metadata_file, 'r', encoding='utf-8') as f:
|
||||
content = f.read()
|
||||
content = content.lstrip('\ufeff')
|
||||
metadata = json.loads(content)
|
||||
|
||||
# Check if we should skip
|
||||
if index_file.exists() and not force_overwrite:
|
||||
print(f"Skipping {game_name} (file exists, use --force to overwrite)")
|
||||
skipped += 1
|
||||
continue
|
||||
|
||||
print(f"Processing: {game_name}")
|
||||
|
||||
# Generate new documentation
|
||||
php_content = self.generate_php_doc(folder.name, metadata)
|
||||
|
||||
# Write the new index.php
|
||||
with open(index_file, 'w', encoding='utf-8') as f:
|
||||
f.write(php_content)
|
||||
|
||||
# Update metadata if it was todo
|
||||
if metadata.get('category', '').lower() == 'todo':
|
||||
metadata['category'] = 'game'
|
||||
|
||||
# Mark as complete
|
||||
metadata['complete'] = True
|
||||
|
||||
with open(metadata_file, 'w', encoding='utf-8') as f:
|
||||
json.dump(metadata, f, indent=4, ensure_ascii=False)
|
||||
|
||||
processed += 1
|
||||
print(f" ✓ Generated documentation for {game_name}")
|
||||
|
||||
except Exception as e:
|
||||
error_msg = f"Error processing {game_name}: {e}"
|
||||
print(f" ✗ {error_msg}")
|
||||
errors.append(error_msg)
|
||||
|
||||
return processed, skipped, errors
|
||||
|
||||
def main():
|
||||
# Parse command line arguments
|
||||
parser = argparse.ArgumentParser(
|
||||
description='Generate comprehensive game server documentation for GSP',
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
epilog="""
|
||||
Examples:
|
||||
# Generate docs for all incomplete games:
|
||||
python3 generate_game_docs.py
|
||||
|
||||
# Generate docs for specific game(s):
|
||||
python3 generate_game_docs.py --games minecraft csgo rust
|
||||
|
||||
# Regenerate docs (overwrite existing):
|
||||
python3 generate_game_docs.py --games minecraft --force
|
||||
|
||||
# Process all "todo" category games:
|
||||
python3 generate_game_docs.py --todo-only
|
||||
"""
|
||||
)
|
||||
|
||||
parser.add_argument('--games', nargs='+', metavar='GAME',
|
||||
help='Generate docs for specific game folder names')
|
||||
parser.add_argument('--force', action='store_true',
|
||||
help='Overwrite existing documentation files')
|
||||
parser.add_argument('--todo-only', action='store_true',
|
||||
help='Only process games with category="todo"')
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
docs_dir = "/home/runner/work/GSP/GSP/modules/billing/docs"
|
||||
config_dir = "/home/runner/work/GSP/GSP/modules/config_games/server_configs"
|
||||
knowledgepack = "/home/runner/work/GSP/GSP/modules/billing/docs/gameserver_knowledgepack_v2.yaml"
|
||||
|
|
@ -908,6 +1162,27 @@ def main():
|
|||
generator.load_knowledgepack()
|
||||
generator.load_xml_configs()
|
||||
|
||||
processed = 0
|
||||
skipped = 0
|
||||
errors = []
|
||||
|
||||
# Determine which mode to run
|
||||
if args.games:
|
||||
# Process specific games
|
||||
print("\n" + "="*70)
|
||||
print(f"Processing {len(args.games)} specified game(s)...")
|
||||
if args.force:
|
||||
print("FORCE mode: Will overwrite existing files")
|
||||
print("="*70)
|
||||
processed, skipped, errors = generator.process_specific_games(args.games, args.force)
|
||||
elif args.todo_only:
|
||||
# Process only todo category games
|
||||
print("\n" + "="*70)
|
||||
print("Processing TODO category games...")
|
||||
print("="*70)
|
||||
processed, errors = generator.process_todo_folders()
|
||||
else:
|
||||
# Process incomplete games (default)
|
||||
print("\n" + "="*70)
|
||||
print("Processing INCOMPLETE game documentation...")
|
||||
print("="*70)
|
||||
|
|
@ -916,7 +1191,8 @@ def main():
|
|||
print(f"\n{'='*70}")
|
||||
print(f"Documentation generation complete!")
|
||||
print(f" ✓ Processed: {processed}")
|
||||
print(f" → Skipped (already complete): {skipped}")
|
||||
if skipped > 0:
|
||||
print(f" → Skipped: {skipped}")
|
||||
print(f" ✗ Errors: {len(errors)}")
|
||||
|
||||
if errors:
|
||||
|
|
@ -926,12 +1202,12 @@ def main():
|
|||
if len(errors) > 10:
|
||||
print(f" ... and {len(errors) - 10} more")
|
||||
|
||||
print(f"\nAll documentation has been enhanced with:")
|
||||
print(f" • Actual port information (not 'Check server configuration')")
|
||||
print(f"\nGenerated documentation includes:")
|
||||
print(f" • Actual port information from XML configs")
|
||||
print(f" • Steam App IDs and exact SteamCMD commands")
|
||||
print(f" • Configuration file details from XML configs")
|
||||
print(f" • Startup parameters extracted from XML")
|
||||
print(f" • Troubleshooting info from knowledgepack")
|
||||
print(f" • DETAILED startup parameters extracted from XML")
|
||||
print(f" • Comprehensive troubleshooting sections")
|
||||
print("="*70)
|
||||
|
||||
return 0 if not errors else 1
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue