diff --git a/gsm-backend/services/serverUpdates.js b/gsm-backend/services/serverUpdates.js index 6b2eeae..69da6ab 100644 --- a/gsm-backend/services/serverUpdates.js +++ b/gsm-backend/services/serverUpdates.js @@ -89,6 +89,43 @@ async function sendUpdateNotification(server, updateInfo) { // SteamCMD Helper Functions // ============================================================================= +/** + * Find SteamCMD executable on the server + */ +async function findSteamCmd(ssh, hints = []) { + // Try hints first + for (const hint of hints) { + const result = await ssh.execCommand(`test -f "${hint}" && echo "${hint}"`); + if (result.stdout.trim()) { + return result.stdout.trim(); + } + } + + // Common locations to check + const commonPaths = [ + "/usr/games/steamcmd", + "/home/steam/steamcmd/steamcmd.sh", + "/home/steam/Steam/steamcmd.sh", + "$HOME/steamcmd/steamcmd.sh", + "$HOME/Steam/steamcmd.sh" + ]; + + for (const path of commonPaths) { + const result = await ssh.execCommand(`test -f ${path} && echo "${path}"`); + if (result.stdout.trim()) { + return result.stdout.trim(); + } + } + + // Try which as last resort + const whichResult = await ssh.execCommand("which steamcmd 2>/dev/null"); + if (whichResult.stdout.trim()) { + return whichResult.stdout.trim(); + } + + return null; +} + /** * Get the current installed build ID from Steam appmanifest */ @@ -114,7 +151,7 @@ async function getLatestSteamBuildId(ssh, appId, steamcmdPath = "steamcmd") { * Create a generic SteamCMD update handler */ function createSteamHandler(config) { - const { appId, installDir, steamcmdPath = "steamcmd", gameName, sudoUser = null } = config; + const { appId, installDir, steamcmdHints = [], gameName } = config; return { supportsUpdate: true, @@ -126,15 +163,21 @@ function createSteamHandler(config) { console.log(`[Update] Checking for ${gameName} updates...`); + // Find SteamCMD + const steamcmdPath = await findSteamCmd(ssh, steamcmdHints); + if (!steamcmdPath) { + return { hasUpdate: false, error: "SteamCMD nicht gefunden auf dem Server" }; + } + console.log(`[Update] Found SteamCMD at: ${steamcmdPath}`); + // Get current build ID const currentBuildId = await getSteamBuildId(ssh, actualInstallDir, appId); if (!currentBuildId) { - return { hasUpdate: false, error: "Konnte aktuelle Version nicht ermitteln" }; + return { hasUpdate: false, error: "Konnte aktuelle Version nicht ermitteln (appmanifest nicht gefunden)" }; } // Get latest build ID from Steam - const sudoPrefix = sudoUser ? `sudo -u ${sudoUser} ` : ""; - const latestBuildId = await getLatestSteamBuildId(ssh, appId, sudoPrefix + steamcmdPath); + const latestBuildId = await getLatestSteamBuildId(ssh, appId, steamcmdPath); if (!latestBuildId) { return { hasUpdate: false, error: "Konnte Steam-Version nicht abrufen" }; @@ -154,15 +197,20 @@ function createSteamHandler(config) { const ssh = await getConnection(server.host, server.sshUser); const actualInstallDir = installDir || server.workDir; + // Find SteamCMD + const steamcmdPath = await findSteamCmd(ssh, steamcmdHints); + if (!steamcmdPath) { + throw new Error("SteamCMD nicht gefunden auf dem Server"); + } + // Get old build ID const oldBuildId = await getSteamBuildId(ssh, actualInstallDir, appId); - console.log(`[Update] Starting ${gameName} update...`); + console.log(`[Update] Starting ${gameName} update with ${steamcmdPath}...`); // Run SteamCMD update - const sudoPrefix = sudoUser ? `sudo -u ${sudoUser} ` : ""; const updateResult = await ssh.execCommand( - `${sudoPrefix}${steamcmdPath} +login anonymous +force_install_dir "${actualInstallDir}" +app_update ${appId} validate +quit`, + `${steamcmdPath} +login anonymous +force_install_dir "${actualInstallDir}" +app_update ${appId} validate +quit`, { execOptions: { timeout: 600000 } } // 10 min timeout for large updates ); @@ -331,36 +379,35 @@ const updateHandlers = { } }, - // V Rising (SteamCMD) + // V Rising (SteamCMD) - runs as root, steam user has steamcmd vrising: createSteamHandler({ appId: STEAM_APP_IDS.vrising, installDir: "/home/steam/vrising", - steamcmdPath: "/home/steam/steamcmd/steamcmd.sh", + steamcmdHints: ["/home/steam/steamcmd/steamcmd.sh", "/home/steam/Steam/steamcmd.sh"], gameName: "V Rising" }), - // Palworld (SteamCMD) + // Palworld (SteamCMD) - runs as root palworld: createSteamHandler({ appId: STEAM_APP_IDS.palworld, installDir: "/opt/palworld", - steamcmdPath: "/usr/games/steamcmd", + steamcmdHints: ["/usr/games/steamcmd", "/home/steam/steamcmd/steamcmd.sh"], gameName: "Palworld" }), - // Project Zomboid (SteamCMD) + // Project Zomboid (SteamCMD) - runs as pzuser zomboid: createSteamHandler({ appId: STEAM_APP_IDS.zomboid, installDir: "/opt/pzserver", - steamcmdPath: "/home/pzuser/steamcmd/steamcmd.sh", - gameName: "Project Zomboid", - sudoUser: "pzuser" + steamcmdHints: ["/home/pzuser/steamcmd/steamcmd.sh", "/opt/steamcmd/steamcmd.sh"], + gameName: "Project Zomboid" }), - // Terraria / tModLoader (SteamCMD) + // Terraria / tModLoader (SteamCMD) - runs as terraria user terraria: createSteamHandler({ appId: STEAM_APP_IDS.terraria, installDir: "/home/terraria/tModLoader", - steamcmdPath: "/home/terraria/steamcmd/steamcmd.sh", + steamcmdHints: ["/home/terraria/steamcmd/steamcmd.sh", "/home/terraria/Steam/steamcmd.sh"], gameName: "Terraria (tModLoader)" }),