Initial commit
This commit is contained in:
142
backend/internal/services/steamcmd.go
Normal file
142
backend/internal/services/steamcmd.go
Normal file
@@ -0,0 +1,142 @@
|
||||
package services
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
func CheckWorkshopMod(serverfileDir, modID string) bool {
|
||||
if modID == "" {
|
||||
return false
|
||||
}
|
||||
p := filepath.Join(serverfileDir, "steamapps", "workshop", "content", "107410", modID)
|
||||
fi, err := os.Stat(p)
|
||||
return err == nil && fi.IsDir()
|
||||
}
|
||||
|
||||
const arma3AppID = "233780"
|
||||
|
||||
type SteamCmdManager struct {
|
||||
serverfileDir string
|
||||
streamer *LogStreamer
|
||||
mu sync.Mutex
|
||||
cancel context.CancelFunc
|
||||
running bool
|
||||
}
|
||||
|
||||
func NewSteamCmdManager(serverfileDir string, streamer *LogStreamer) *SteamCmdManager {
|
||||
return &SteamCmdManager{
|
||||
serverfileDir: serverfileDir,
|
||||
streamer: streamer,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *SteamCmdManager) IsRunning() bool {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
return s.running
|
||||
}
|
||||
|
||||
func (s *SteamCmdManager) UpdateGame(branch, user string) error {
|
||||
s.mu.Lock()
|
||||
if s.running {
|
||||
s.mu.Unlock()
|
||||
return fmt.Errorf("steamcmd already running")
|
||||
}
|
||||
s.mu.Unlock()
|
||||
|
||||
args := []string{
|
||||
"+force_install_dir", s.serverfileDir,
|
||||
"+login", user,
|
||||
"+app_update", arma3AppID,
|
||||
}
|
||||
if branch != "" && branch != "stable" {
|
||||
args = append(args, "-beta", branch)
|
||||
}
|
||||
args = append(args, "validate", "+quit")
|
||||
|
||||
return s.run("Game update", args)
|
||||
}
|
||||
|
||||
func (s *SteamCmdManager) DownloadMod(modID string) error {
|
||||
return s.DownloadMods([]string{modID})
|
||||
}
|
||||
|
||||
func (s *SteamCmdManager) DownloadMods(modIDs []string) error {
|
||||
s.mu.Lock()
|
||||
if s.running {
|
||||
s.mu.Unlock()
|
||||
return fmt.Errorf("steamcmd already running")
|
||||
}
|
||||
s.mu.Unlock()
|
||||
|
||||
if len(modIDs) == 0 {
|
||||
return fmt.Errorf("no mod ids provided")
|
||||
}
|
||||
|
||||
args := []string{
|
||||
"+force_install_dir", s.serverfileDir,
|
||||
"+login", "anonymous",
|
||||
}
|
||||
for _, id := range modIDs {
|
||||
args = append(args, "+workshop_download_item", "107410", id)
|
||||
}
|
||||
args = append(args, "+quit")
|
||||
|
||||
label := fmt.Sprintf("Download %d mod(s)", len(modIDs))
|
||||
return s.run(label, args)
|
||||
}
|
||||
|
||||
const steamcmdTimeout = 10 * time.Minute
|
||||
|
||||
func (s *SteamCmdManager) run(label string, args []string) error {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), steamcmdTimeout)
|
||||
|
||||
s.streamer.Broadcast("steamcmd", "[STEAMCMD] "+label+" starting...")
|
||||
|
||||
cmd := exec.CommandContext(ctx, "steamcmd", args...)
|
||||
|
||||
stdout, err := cmd.StdoutPipe()
|
||||
if err != nil {
|
||||
cancel()
|
||||
return fmt.Errorf("stdout pipe: %w", err)
|
||||
}
|
||||
stderr, err := cmd.StderrPipe()
|
||||
if err != nil {
|
||||
cancel()
|
||||
return fmt.Errorf("stderr pipe: %w", err)
|
||||
}
|
||||
|
||||
if err := cmd.Start(); err != nil {
|
||||
cancel()
|
||||
return fmt.Errorf("start steamcmd: %w", err)
|
||||
}
|
||||
|
||||
s.mu.Lock()
|
||||
s.running = true
|
||||
s.cancel = cancel
|
||||
s.mu.Unlock()
|
||||
|
||||
go s.streamer.Stream("steamcmd", stdout, "")
|
||||
go s.streamer.Stream("steamcmd", stderr, "")
|
||||
|
||||
go func() {
|
||||
err := cmd.Wait()
|
||||
s.mu.Lock()
|
||||
s.running = false
|
||||
s.cancel = nil
|
||||
s.mu.Unlock()
|
||||
if err == nil {
|
||||
s.streamer.Broadcast("steamcmd", "[STEAMCMD] SUCCESS: "+label+" finished")
|
||||
} else {
|
||||
s.streamer.Broadcast("steamcmd", "[STEAMCMD] ERROR: "+label+" failed: "+err.Error())
|
||||
}
|
||||
}()
|
||||
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user