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 {