From 8fd183273df9d14fa805f7766e5cac3975cf88c7 Mon Sep 17 00:00:00 2001 From: akirilov <***REDACTED***> Date: Sun, 31 May 2026 09:04:51 +0000 Subject: [PATCH 1/5] Adding support for fedora --- .devcontainer/Dockerfile | 3 +- .devcontainer/devcontainer.json | 5 +- src/steamcmd/steamcmd-helper.go | 107 +++++++++++++++++++++++++++++--- 3 files changed, 103 insertions(+), 12 deletions(-) diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index 3c8d5272..f665842e 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -24,8 +24,7 @@ RUN mkdir -p /go/bin && chown -R vscode:vscode /go # Install Node.js 22.15.0 RUN curl -fsSL https://deb.nodesource.com/setup_22.x | bash - && \ - apt-get install -y nodejs && \ - npm install -g npm@latest + apt-get install -y nodejs # Set up non-root user and workspace USER vscode diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 44166e0b..74805d67 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -21,8 +21,7 @@ "vscode": { "extensions": [ "golang.go", - "svelte.svelte-vscode", - "eamodio.gitlens" + "svelte.svelte-vscode" ], "settings": { "go.toolsManagement.autoUpdate": true, @@ -30,5 +29,5 @@ } } }, - "postCreateCommand": "go mod tidy && cd frontend && npm install && npm install @sveltejs/vite-plugin-svelte" + "postCreateCommand": "go mod tidy && cd frontend && npm install && npm install @sveltejs/vite-plugin-svelte && npm audit fix" } \ No newline at end of file diff --git a/src/steamcmd/steamcmd-helper.go b/src/steamcmd/steamcmd-helper.go index 4caee4fe..e8330fc1 100644 --- a/src/steamcmd/steamcmd-helper.go +++ b/src/steamcmd/steamcmd-helper.go @@ -14,6 +14,7 @@ import ( "os/exec" "path/filepath" "runtime" + "slices" "strings" "time" @@ -293,9 +294,64 @@ func untarWrapper(r io.ReaderAt, _ int64, dest string) error { return untar(dest, io.NewSectionReader(r, 0, 1<<63-1)) // Use a large size for the section reader } +type distroFamily int + +const ( + distroUnknown distroFamily = iota + distroDebian + distroRHEL +) + +// parseOSRelease parses a /etc/os-release file into a key-value map. +func parseOSRelease(content string) map[string]string { + fields := make(map[string]string) + for _, line := range strings.Split(content, "\n") { + parts := strings.SplitN(line, "=", 2) + if len(parts) != 2 { + continue + } + fields[parts[0]] = strings.Trim(parts[1], `"`) + } + return fields +} + +// detectDistroFamily reads /etc/os-release and returns the distro family. +// ID is checked first (single value); ID_LIKE is the fallback (space-separated list). +func detectDistroFamily() distroFamily { + data, err := os.ReadFile("/etc/os-release") + if err != nil { + return distroUnknown + } + + debianIDs := []string{"ubuntu", "debian", "linuxmint", "pop", "elementary", "raspbian"} + rhelIDs := []string{"rhel", "centos", "fedora", "rocky", "almalinux", "ol"} + + fields := parseOSRelease(string(data)) + + // Check ID first — it's a single value identifying the primary distro. + id := strings.ToLower(fields["ID"]) + if slices.Contains(debianIDs, id) { + return distroDebian + } + if slices.Contains(rhelIDs, id) { + return distroRHEL + } + + // Fall back to ID_LIKE — a space-separated list of closely related distros. + for _, like := range strings.Fields(strings.ToLower(fields["ID_LIKE"])) { + if slices.Contains(debianIDs, like) { + return distroDebian + } + if slices.Contains(rhelIDs, like) { + return distroRHEL + } + } + + return distroUnknown +} + // installRequiredLibraries installs the required libraries for SteamCMD if they are not already installed. func installRequiredLibraries() error { - // Check if the system is Debian-based if runtime.GOOS != "linux" { return nil // Only Linux systems need this } @@ -306,8 +362,19 @@ func installRequiredLibraries() error { return nil } - // According to https://developer.valvesoftware.com/wiki/SteamCMD#Manually only lib32gcc-s1 is needed - // List of required libraries + switch detectDistroFamily() { + case distroDebian: + return installRequiredLibrariesDebian() + case distroRHEL: + return installRequiredLibrariesRHEL() + default: + return fmt.Errorf("unsupported Linux distribution: only Ubuntu/Debian and RHEL-based distros are supported") + } +} + +// installRequiredLibrariesDebian installs SteamCMD dependencies on Ubuntu/Debian using apt-get. +// According to https://developer.valvesoftware.com/wiki/SteamCMD#Manually only lib32gcc-s1 is needed. +func installRequiredLibrariesDebian() error { requiredLibs := []string{ "lib32gcc-s1", //"lib32stdc++6", @@ -316,10 +383,9 @@ func installRequiredLibraries() error { // Check and install each library for _, lib := range requiredLibs { // Check if the library is already installed - cmd := exec.Command("dpkg", "-s", lib) - if err := cmd.Run(); err == nil { + if err := exec.Command("dpkg", "-s", lib).Run(); err == nil { logger.Install.Debug("✅ Library already installed: " + lib + "\n") - continue // Library is already installed, skip to the next one + continue } // Library is not installed, attempt to install it @@ -327,12 +393,39 @@ func installRequiredLibraries() error { installCmd := exec.Command("sudo", "apt-get", "install", "-y", lib) installCmd.Stdout = os.Stdout installCmd.Stderr = os.Stderr - if err := installCmd.Run(); err != nil { return fmt.Errorf("failed to install library %s: %w", lib, err) } logger.Install.Debug("✅ Installed library: " + lib + "\n") } + return nil +} + +// installRequiredLibrariesRHEL installs SteamCMD dependencies on RHEL-based distros using dnf. +// libgcc.i686 is the RHEL equivalent of lib32gcc-s1 on Debian-based distros. +func installRequiredLibrariesRHEL() error { + requiredLibs := []string{ + "libgcc.i686", + "libstdc++.i686", + } + + // Check and install each library + for _, lib := range requiredLibs { + // Check if the library is already installed + if err := exec.Command("rpm", "-q", lib).Run(); err == nil { + logger.Install.Debug("✅ Library already installed: " + lib + "\n") + continue + } + // Library is not installed, attempt to install it + logger.Install.Debug("🔄 Installing library: " + lib + "\n") + installCmd := exec.Command("sudo", "dnf", "install", "-y", lib) + installCmd.Stdout = os.Stdout + installCmd.Stderr = os.Stderr + if err := installCmd.Run(); err != nil { + return fmt.Errorf("failed to install library %s: %w", lib, err) + } + logger.Install.Debug("✅ Installed library: " + lib + "\n") + } return nil } From da0af40cee3db2181ba39d12ec761659538e729b Mon Sep 17 00:00:00 2001 From: akirilov <4062569+akirilov@users.noreply.github.com> Date: Sun, 31 May 2026 19:11:19 +0900 Subject: [PATCH 2/5] Apply suggestions from code review Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- UIMod/onboard_bundled/assets/js/slp.js | 5 ++--- src/steamcmd/steamcmd-helper.go | 3 ++- src/web/slp-launchpad.go | 10 ++++++++++ 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/UIMod/onboard_bundled/assets/js/slp.js b/UIMod/onboard_bundled/assets/js/slp.js index c1a71936..dd2b703b 100644 --- a/UIMod/onboard_bundled/assets/js/slp.js +++ b/UIMod/onboard_bundled/assets/js/slp.js @@ -138,8 +138,7 @@ function reinstallSLP() { function updateSingleMod(workshopHandle, index) { const btnId = 'update-mod-btn-' + index; setButtonLoading(btnId, true); - showPopup('info', 'Updating workshop mod ' + workshopHandle + '...\n\nPlease wait.'); - + showPopup('info', 'Updating workshop mod ' + escapeHtml(String(workshopHandle)) + '...\n\nPlease wait.'); fetch('/api/v2/steamcmd/updatemod', { method: 'POST', headers: { 'Content-Type': 'application/json' }, @@ -452,7 +451,7 @@ function createModCard(mod, index) { let updateButtonHtml = ''; if (mod.WorkshopHandle) { - updateButtonHtml = ``; + updateButtonHtml = ``; } card.innerHTML = ` diff --git a/src/steamcmd/steamcmd-helper.go b/src/steamcmd/steamcmd-helper.go index e8330fc1..41ef276b 100644 --- a/src/steamcmd/steamcmd-helper.go +++ b/src/steamcmd/steamcmd-helper.go @@ -419,12 +419,13 @@ func installRequiredLibrariesRHEL() error { // Library is not installed, attempt to install it logger.Install.Debug("🔄 Installing library: " + lib + "\n") - installCmd := exec.Command("sudo", "dnf", "install", "-y", lib) + installCmd := exec.Command("sudo", "-n", "dnf", "install", "-y", lib) installCmd.Stdout = os.Stdout installCmd.Stderr = os.Stderr if err := installCmd.Run(); err != nil { return fmt.Errorf("failed to install library %s: %w", lib, err) } + } logger.Install.Debug("✅ Installed library: " + lib + "\n") } return nil diff --git a/src/web/slp-launchpad.go b/src/web/slp-launchpad.go index bc744604..15bee0af 100644 --- a/src/web/slp-launchpad.go +++ b/src/web/slp-launchpad.go @@ -144,6 +144,16 @@ func UpdateSingleWorkshopModHandler(w http.ResponseWriter, r *http.Request) { }) return } + for _, ch := range req.WorkshopHandle { + if ch < '0' || ch > '9' { + w.WriteHeader(http.StatusBadRequest) + json.NewEncoder(w).Encode(map[string]interface{}{ + "success": false, + "error": "workshopHandle must be a numeric Steam Workshop ID", + }) + return + } + } logs, err := steamcmd.DownloadWorkshopItems([]string{req.WorkshopHandle}) if err != nil { From 4559115e8a6363803794ef98cb09a4841b09f0ed Mon Sep 17 00:00:00 2001 From: akirilov Date: Sun, 31 May 2026 12:17:09 +0200 Subject: [PATCH 3/5] Fix AI slop --- src/steamcmd/steamcmd-helper.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/steamcmd/steamcmd-helper.go b/src/steamcmd/steamcmd-helper.go index 41ef276b..e8330fc1 100644 --- a/src/steamcmd/steamcmd-helper.go +++ b/src/steamcmd/steamcmd-helper.go @@ -419,13 +419,12 @@ func installRequiredLibrariesRHEL() error { // Library is not installed, attempt to install it logger.Install.Debug("🔄 Installing library: " + lib + "\n") - installCmd := exec.Command("sudo", "-n", "dnf", "install", "-y", lib) + installCmd := exec.Command("sudo", "dnf", "install", "-y", lib) installCmd.Stdout = os.Stdout installCmd.Stderr = os.Stderr if err := installCmd.Run(); err != nil { return fmt.Errorf("failed to install library %s: %w", lib, err) } - } logger.Install.Debug("✅ Installed library: " + lib + "\n") } return nil From 5089d41e32b463eddb31681b38166b7321ac996d Mon Sep 17 00:00:00 2001 From: akirilov Date: Sun, 31 May 2026 10:19:37 +0000 Subject: [PATCH 4/5] add devcontainer lock file --- .devcontainer/devcontainer-lock.json | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 .devcontainer/devcontainer-lock.json diff --git a/.devcontainer/devcontainer-lock.json b/.devcontainer/devcontainer-lock.json new file mode 100644 index 00000000..94b2b7fe --- /dev/null +++ b/.devcontainer/devcontainer-lock.json @@ -0,0 +1,9 @@ +{ + "features": { + "ghcr.io/devcontainers/features/go:1": { + "version": "1.3.4", + "resolved": "ghcr.io/devcontainers/features/go@sha256:d85e921f91b41340055bb12b325d9d551170ed04b3b832e33530bf42f167c032", + "integrity": "sha256:d85e921f91b41340055bb12b325d9d551170ed04b3b832e33530bf42f167c032" + } + } +} From 858609e6379dfc673ab7c84fc4b023efe440de72 Mon Sep 17 00:00:00 2001 From: akirilov <***REDACTED***> Date: Sun, 31 May 2026 15:38:36 +0000 Subject: [PATCH 5/5] Revert "Fix AI slop" This reverts commit 4559115e8a6363803794ef98cb09a4841b09f0ed. Revert "Apply suggestions from code review" This reverts commit da0af40cee3db2181ba39d12ec761659538e729b. --- UIMod/onboard_bundled/assets/js/slp.js | 5 +++-- src/web/slp-launchpad.go | 10 ---------- 2 files changed, 3 insertions(+), 12 deletions(-) diff --git a/UIMod/onboard_bundled/assets/js/slp.js b/UIMod/onboard_bundled/assets/js/slp.js index dd2b703b..c1a71936 100644 --- a/UIMod/onboard_bundled/assets/js/slp.js +++ b/UIMod/onboard_bundled/assets/js/slp.js @@ -138,7 +138,8 @@ function reinstallSLP() { function updateSingleMod(workshopHandle, index) { const btnId = 'update-mod-btn-' + index; setButtonLoading(btnId, true); - showPopup('info', 'Updating workshop mod ' + escapeHtml(String(workshopHandle)) + '...\n\nPlease wait.'); + showPopup('info', 'Updating workshop mod ' + workshopHandle + '...\n\nPlease wait.'); + fetch('/api/v2/steamcmd/updatemod', { method: 'POST', headers: { 'Content-Type': 'application/json' }, @@ -451,7 +452,7 @@ function createModCard(mod, index) { let updateButtonHtml = ''; if (mod.WorkshopHandle) { - updateButtonHtml = ``; + updateButtonHtml = ``; } card.innerHTML = ` diff --git a/src/web/slp-launchpad.go b/src/web/slp-launchpad.go index 15bee0af..bc744604 100644 --- a/src/web/slp-launchpad.go +++ b/src/web/slp-launchpad.go @@ -144,16 +144,6 @@ func UpdateSingleWorkshopModHandler(w http.ResponseWriter, r *http.Request) { }) return } - for _, ch := range req.WorkshopHandle { - if ch < '0' || ch > '9' { - w.WriteHeader(http.StatusBadRequest) - json.NewEncoder(w).Encode(map[string]interface{}{ - "success": false, - "error": "workshopHandle must be a numeric Steam Workshop ID", - }) - return - } - } logs, err := steamcmd.DownloadWorkshopItems([]string{req.WorkshopHandle}) if err != nil {