- Create 3 new DB tables: workshop_game_profiles, workshop_cache, server_workshop_mods - Add WorkshopRepository (DB access layer for all 3 tables) - Add WorkshopInstaller (rsync/robocopy/custom_script copy logic, SteamCMD download via agent exec) - Add WorkshopUpdater (scheduled cache update functions grouped by agent) - Add WorkshopPreStart (pre-start mod sync helper) - Add WorkshopProfileController (admin CRUD for profiles) - Add WorkshopModController (user install/remove/toggle/load_order/sync) - Add admin views: profiles list + profile_form - Add user views: user_workshop_index + user_workshop_mods - Add cron_update.php CLI entry point (--all/--agent-id/--home-id/--profile-id/--workshop-id) - Add prestart_sync.php CLI helper for XML pre_start hook - Update workshop_admin.php to route to profile management - Update main.php to route to new mod management (legacy fallback preserved) - Update module.php with DB migration SQL and version bump to 2.1 - Update lang/en_US.php with all new strings Agent-Logs-Url: https://github.com/GameServerPanel/GSP/sessions/dbeebd0e-e7a5-469d-8a8c-e63193d1ebb0 Co-authored-by: iaretechnician <2749183+iaretechnician@users.noreply.github.com>
178 lines
5.5 KiB
PHP
178 lines
5.5 KiB
PHP
#!/usr/bin/env php
|
||
<?php
|
||
declare(strict_types=1);
|
||
/*
|
||
* OGP / GSP – Steam Workshop cron update script
|
||
*
|
||
* Usage:
|
||
* php modules/steam_workshop/cron_update.php --all
|
||
* php modules/steam_workshop/cron_update.php --agent-id=<ID>
|
||
* php modules/steam_workshop/cron_update.php --home-id=<ID>
|
||
* php modules/steam_workshop/cron_update.php --profile-id=<ID>
|
||
* php modules/steam_workshop/cron_update.php --workshop-id=<WID> --agent-id=<AID> --app-id=<APPID>
|
||
*
|
||
* This script:
|
||
* 1. Finds enabled installed mods from gsp_server_workshop_mods.
|
||
* 2. Groups them by agent_id and workshop_app_id.
|
||
* 3. For each unique (agent, appid, workshop_id), runs SteamCMD
|
||
* workshop_download_item validate on the agent.
|
||
* 4. Updates gsp_workshop_cache (status, last_checked, last_updated, last_error).
|
||
* 5. Does NOT copy into running servers.
|
||
* 6. Does NOT restart servers.
|
||
* 7. Logs all update attempts.
|
||
*
|
||
* Run from the panel root directory:
|
||
* cd /var/www/html && php modules/steam_workshop/cron_update.php --all
|
||
*/
|
||
|
||
// -----------------------------------------------------------------------
|
||
// Bootstrap: load panel includes
|
||
// -----------------------------------------------------------------------
|
||
|
||
// Determine panel root
|
||
$panelRoot = defined('PANEL_ROOT') ? PANEL_ROOT : realpath(__DIR__ . '/../../..');
|
||
if ($panelRoot === false) {
|
||
$panelRoot = __DIR__ . '/../../..';
|
||
}
|
||
chdir($panelRoot);
|
||
|
||
// Load configuration
|
||
if (!is_file('includes/config.inc.php')) {
|
||
fwrite(STDERR, "[ERROR] Cannot locate includes/config.inc.php. Run this script from the panel root.\n");
|
||
exit(1);
|
||
}
|
||
|
||
require_once 'includes/config.inc.php';
|
||
require_once 'includes/database.php';
|
||
require_once 'includes/database_mysqli.php';
|
||
require_once 'includes/lib_remote.php';
|
||
|
||
// Connect to database
|
||
if (!isset($db_host, $db_user, $db_pass, $db_name)) {
|
||
fwrite(STDERR, "[ERROR] Database configuration variables not set.\n");
|
||
exit(1);
|
||
}
|
||
|
||
$db = new OGPDatabaseMySQL();
|
||
/** @var int|true $connResult */
|
||
$connResult = $db->connect(
|
||
$db_host,
|
||
$db_user,
|
||
$db_pass,
|
||
$db_name,
|
||
$table_prefix ?? 'gsp_',
|
||
$db_port ?? null
|
||
);
|
||
|
||
if ($connResult !== true) {
|
||
fwrite(STDERR, "[ERROR] Database connection failed (code: {$connResult}).\n");
|
||
exit(1);
|
||
}
|
||
|
||
require_once __DIR__ . '/lib/WorkshopRepository.php';
|
||
require_once __DIR__ . '/lib/WorkshopInstaller.php';
|
||
require_once __DIR__ . '/lib/WorkshopUpdater.php';
|
||
|
||
$repo = new WorkshopRepository($db);
|
||
$installer = new WorkshopInstaller($repo);
|
||
$updater = new WorkshopUpdater($repo, $installer);
|
||
|
||
// -----------------------------------------------------------------------
|
||
// Parse CLI arguments
|
||
// -----------------------------------------------------------------------
|
||
|
||
$opts = getopt('', [
|
||
'all',
|
||
'agent-id:',
|
||
'home-id:',
|
||
'profile-id:',
|
||
'workshop-id:',
|
||
'app-id:',
|
||
'help',
|
||
]);
|
||
|
||
if (isset($opts['help']) || $opts === false || empty($opts)) {
|
||
echo <<<HELP
|
||
GSP Steam Workshop – cron cache updater
|
||
|
||
Usage:
|
||
php cron_update.php --all
|
||
php cron_update.php --agent-id=<ID>
|
||
php cron_update.php --home-id=<ID>
|
||
php cron_update.php --profile-id=<ID>
|
||
php cron_update.php --workshop-id=<WID> --agent-id=<AID> --app-id=<APPID>
|
||
|
||
HELP;
|
||
exit(0);
|
||
}
|
||
|
||
// -----------------------------------------------------------------------
|
||
// Execute the requested update
|
||
// -----------------------------------------------------------------------
|
||
|
||
function printResults(array $results): void
|
||
{
|
||
$ok = 0;
|
||
$fail = 0;
|
||
foreach ($results as $r) {
|
||
$status = $r['success'] ? 'OK ' : 'FAIL ';
|
||
if ($r['success']) {
|
||
$ok++;
|
||
} else {
|
||
$fail++;
|
||
}
|
||
$msg = $r['message'] ?? '';
|
||
echo "[{$status}] agent={$r['agent_id']} app={$r['workshop_app_id']} mod={$r['workshop_id']} – {$msg}\n";
|
||
}
|
||
echo "Done: {$ok} succeeded, {$fail} failed.\n";
|
||
}
|
||
|
||
if (isset($opts['all'])) {
|
||
echo "[INFO] Updating all enabled Workshop mods…\n";
|
||
$results = $updater->updateAll();
|
||
printResults($results);
|
||
exit(0);
|
||
}
|
||
|
||
if (isset($opts['agent-id']) && !isset($opts['workshop-id'])) {
|
||
$agentId = (int)$opts['agent-id'];
|
||
echo "[INFO] Updating Workshop mods for agent {$agentId}…\n";
|
||
$results = $updater->updateWorkshopCacheForAgent($agentId);
|
||
printResults($results);
|
||
exit(0);
|
||
}
|
||
|
||
if (isset($opts['home-id'])) {
|
||
$homeId = (int)$opts['home-id'];
|
||
echo "[INFO] Updating Workshop mods for home {$homeId}…\n";
|
||
$results = $updater->updateWorkshopCacheForHome($homeId);
|
||
printResults($results);
|
||
exit(0);
|
||
}
|
||
|
||
if (isset($opts['profile-id'])) {
|
||
$profileId = (int)$opts['profile-id'];
|
||
echo "[INFO] Updating Workshop mods for profile {$profileId}…\n";
|
||
$results = $updater->updateWorkshopCacheForProfile($profileId);
|
||
printResults($results);
|
||
exit(0);
|
||
}
|
||
|
||
if (isset($opts['workshop-id'], $opts['agent-id'], $opts['app-id'])) {
|
||
$workshopId = preg_replace('/[^0-9]/', '', (string)$opts['workshop-id']) ?? '';
|
||
$agentId = (int)$opts['agent-id'];
|
||
$appId = preg_replace('/[^0-9]/', '', (string)$opts['app-id']) ?? '';
|
||
|
||
if ($workshopId === '' || $appId === '') {
|
||
fwrite(STDERR, "[ERROR] --workshop-id and --app-id must be numeric.\n");
|
||
exit(1);
|
||
}
|
||
|
||
echo "[INFO] Updating single mod: agent={$agentId} app={$appId} mod={$workshopId}…\n";
|
||
$result = $updater->updateSingleWorkshopMod($agentId, $appId, $workshopId);
|
||
printResults([$result]);
|
||
exit(0);
|
||
}
|
||
|
||
fwrite(STDERR, "[ERROR] No valid option provided. Use --help for usage.\n");
|
||
exit(1);
|