Files
G-Launcher/internal/git-service/server.go
T

208 lines
5.4 KiB
Go

package gitService
import (
"encoding/json"
"fmt"
"g-launcher/pkg/constant"
"g-launcher/pkg/models"
"io"
"net/http"
"os"
"path/filepath"
"strings"
"time"
"github.com/wailsapp/wails/v3/pkg/application"
)
func (g *GitService) GetLatestServerVersion() (bool, string, string) {
client := &http.Client{Timeout: 15 * time.Second}
resp, err := client.Get(constant.ServerGitUrl)
if err != nil {
return false, "", err.Error()
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
return false, "", err.Error()
}
var releases []models.ReleaseType
err = json.Unmarshal(body, &releases)
if err != nil {
return false, "", err.Error()
}
if len(releases) == 0 {
return false, "", "no releases found"
}
return true, releases[0].TagName, ""
}
func (g *GitService) DownloadServerProgress(version string) (bool, string) {
client := &http.Client{Timeout: 15 * time.Second}
resp, err := client.Get(constant.ServerGitUrl)
if err != nil {
return false, fmt.Sprintf("fetch server releases: %v", err)
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
return false, fmt.Sprintf("read server releases: %v", err)
}
var releases []*models.ReleaseType
if err := json.Unmarshal(body, &releases); err != nil || len(releases) == 0 {
return false, "no releases found on server repository"
}
var targetRelease *models.ReleaseType
for _, rel := range releases {
if rel.TagName == version {
targetRelease = rel
break
}
}
if targetRelease == nil && len(releases) > 0 {
targetRelease = releases[0]
}
if targetRelease == nil {
return false, "could not find server release matching version " + version
}
if err := os.MkdirAll(constant.ServerStorageUrl, 0755); err != nil {
return false, err.Error()
}
// 1. Search for .zip asset
var zipAsset *models.AssetType
for _, asset := range targetRelease.Assets {
if strings.HasSuffix(strings.ToLower(asset.Name), ".zip") {
aCopy := asset
zipAsset = &aCopy
break
}
}
if zipAsset != nil {
// Case A: ZIP archive found
saveZipPath := filepath.Join(constant.ServerStorageUrl, zipAsset.Name)
tmpPath, err := g.downloadFileParallel(saveZipPath, zipAsset.BrowserDownloadURL, 4, func(percent float64, speed string) {
application.Get().Event.Emit("download:server", map[string]interface{}{
"percent": fmt.Sprintf("%.2f", percent),
"speed": speed,
})
})
if err != nil {
return false, fmt.Sprintf("download server zip: %v", err)
}
renamed := false
for i := 0; i < 3; i++ {
if err := os.Rename(tmpPath, saveZipPath); err == nil {
renamed = true
break
}
time.Sleep(300 * time.Millisecond)
}
if !renamed {
os.Remove(tmpPath)
return false, "failed to rename downloaded server zip"
}
// Unzip immediately
if err := g.unzipParallel(saveZipPath, constant.ServerStorageUrl); err != nil {
return false, fmt.Sprintf("unzip server: %v", err)
}
os.Remove(saveZipPath)
return true, ""
}
// Case B: No ZIP archive, download sdkserver and server executables
var sdkAsset, serverAsset *models.AssetType
for _, asset := range targetRelease.Assets {
nameLower := strings.ToLower(asset.Name)
if strings.Contains(nameLower, "sdkserver") {
aCopy := asset
sdkAsset = &aCopy
} else if strings.Contains(nameLower, "server") {
aCopy := asset
serverAsset = &aCopy
}
}
if sdkAsset == nil && serverAsset == nil {
return false, "no zip or server executable assets found in release"
}
if sdkAsset != nil {
saveSdk := filepath.Join(constant.ServerStorageUrl, sdkAsset.Name)
tmpPath, err := g.downloadFileParallel(saveSdk, sdkAsset.BrowserDownloadURL, 4, func(percent float64, speed string) {
application.Get().Event.Emit("download:server", map[string]interface{}{
"percent": fmt.Sprintf("%.2f", percent*0.5),
"speed": speed,
})
})
if err == nil {
_ = os.Rename(tmpPath, saveSdk)
}
}
if serverAsset != nil {
saveServer := filepath.Join(constant.ServerStorageUrl, serverAsset.Name)
tmpPath, err := g.downloadFileParallel(saveServer, serverAsset.BrowserDownloadURL, 4, func(percent float64, speed string) {
application.Get().Event.Emit("download:server", map[string]interface{}{
"percent": fmt.Sprintf("%.2f", 50.0+percent*0.5),
"speed": speed,
})
})
if err == nil {
_ = os.Rename(tmpPath, saveServer)
}
}
return true, ""
}
func (g *GitService) UnzipServer() {
entries, err := os.ReadDir(constant.ServerStorageUrl)
if err != nil {
return
}
for _, entry := range entries {
if !entry.IsDir() && strings.HasSuffix(strings.ToLower(entry.Name()), ".zip") {
zipPath := filepath.Join(constant.ServerStorageUrl, entry.Name())
_ = g.unzipParallel(zipPath, constant.ServerStorageUrl)
_ = os.Remove(zipPath)
}
}
}
func (g *GitService) FindServerExecutables() (string, string) {
serverDir := constant.ServerStorageUrl
var gameServer, sdkServer string
// Candidate filenames for game server
for _, name := range []string{"gameserver-go.exe", "server.exe", "gameserver.exe", "firefly-go_win.exe"} {
p := filepath.Join(serverDir, name)
if info, err := os.Stat(p); err == nil && !info.IsDir() {
gameServer = p
break
}
}
// Candidate filenames for sdk server
for _, name := range []string{"sdkserver-go.exe", "sdkserver.exe"} {
p := filepath.Join(serverDir, name)
if info, err := os.Stat(p); err == nil && !info.IsDir() {
sdkServer = p
break
}
}
return gameServer, sdkServer
}