import { NodeSSH } from "node-ssh"; const SSH_TIMEOUT = 15000; const sshConnections = new Map(); async function getConnection(host, username = "root") { const key = username + "@" + host; if (sshConnections.has(key)) { const conn = sshConnections.get(key); if (conn.isConnected()) return conn; sshConnections.delete(key); } const ssh = new NodeSSH(); await ssh.connect({ host, username, privateKeyPath: "/root/.ssh/id_ed25519", readyTimeout: SSH_TIMEOUT }); sshConnections.set(key, ssh); return ssh; } const SE_APPMANIFEST = "/opt/spaceengineers/appdata/space-engineers/bins/SpaceEngineersDedicated/steamapps/appmanifest_298740.acf"; async function getSpaceEngineersVersion(server) { const ssh = await getConnection(server.host, server.sshUser); const result = await ssh.execCommand(`cat ${SE_APPMANIFEST} 2>/dev/null`); const text = result.stdout || ""; if (!text) return null; const buildidMatch = text.match(/"buildid"\s*"([^"]+)"/); const lastUpdatedMatch = text.match(/"LastUpdated"\s*"([^"]+)"/); const targetBuildMatch = text.match(/"TargetBuildID"\s*"([^"]+)"/); const buildid = buildidMatch ? buildidMatch[1] : null; const lastUpdatedUnix = lastUpdatedMatch ? parseInt(lastUpdatedMatch[1], 10) : null; const targetBuild = targetBuildMatch ? targetBuildMatch[1] : null; if (!buildid) return null; return { version: buildid, lastUpdated: lastUpdatedUnix ? new Date(lastUpdatedUnix * 1000).toISOString() : null, updatePending: targetBuild && targetBuild !== "0" && targetBuild !== buildid ? targetBuild : null, source: "steam-appmanifest" }; } const versionHandlers = { spaceengineers: getSpaceEngineersVersion }; const versionCache = new Map(); const CACHE_TTL_MS = 60_000; export function supportsVersionInfo(serverType) { return !!versionHandlers[serverType]; } export function invalidateVersionCache(serverId) { versionCache.delete(serverId); } export async function getVersionInfo(server) { const handler = versionHandlers[server.type]; if (!handler) return null; const cached = versionCache.get(server.id); if (cached && Date.now() - cached.fetchedAt < CACHE_TTL_MS) { return cached.data; } const data = await handler(server); if (data) { versionCache.set(server.id, { data, fetchedAt: Date.now() }); } return data; }