package router import ( "ARKItems/configs" "archive/zip" "encoding/json" "fmt" "github.com/gin-gonic/gin" "io" "io/ioutil" "os" "path/filepath" "strings" "time" ) var ( BackupFileList = make([]string, 0) // ServerConfigUrls 实际服务器目录,商店插件配置文件位置 ServerConfigUrls = make([]string, 0) ) func init() { ReadBackupFileList() } func ARKFileRouter(api *gin.RouterGroup) { //安装插件 api.GET("/installPlugin", InstallArkApiZip) //保存配置到配置文件 api.GET("/saveConfig", WriteFileConfig) //更新实际配置文件内容 api.GET("/updateServerShopApiConfig", UpdateServerShopApiConfig) } func UpdateServerShopApiConfig(c *gin.Context) { marshal, err := json.Marshal(ARKConfig) if err != nil { fmt.Println(err) c.JSON(200, CreateResultError(500, "配置文件读取失败")) } for i := range ServerConfigUrls { os.Remove(ServerConfigUrls[i]) ioutil.WriteFile(ServerConfigUrls[i], marshal, 0644) } //TODO 可能需要调用rcon功能,更新配置 c.JSON(200, CreateResult()) } //F:/arkserver/Servers/Server1/ShooterGame/Binaries/Win64/Plugins/ArkShop/config.json // InstallArkApiZip 安装ArkApi func InstallArkApiZip(c *gin.Context) { value := c.Query("compulsion") //TODO 是否将最新的商店文件写入配置中 //writeNow := c.Query("writeNow") //是否强制安装 compulsion := value == "true" urls := ReadArkBackupUrl(configs.ArkApiInstallUrl) for _, url := range urls { ServerConfigUrls = append(ServerConfigUrls, url+"/ArkApi/Plugins/ArkShop/config.json") go InstallZip(compulsion, url) } c.JSON(200, CreateResult()) } // WriteFileConfig 备份实体的配置文件 func WriteFileConfig(c *gin.Context) { err := BackupFile() if err != nil { fmt.Println(err) c.JSON(200, CreateResultError(500, "备份失败")) } //修改目标文件 marshal, err := json.Marshal(ARKConfig) if err != nil { fmt.Println(err) c.JSON(200, CreateResultError(500, "写入失败")) } err = os.WriteFile(configs.ARKJsonFilePath, marshal, 0644) } // ReadBackupFileList 读取备份文件列表 func ReadBackupFileList() { entities, err := os.ReadDir(configs.ARKBackupDir) if err != nil { fmt.Println(err) } //获取备份文件位置 for i := range entities { BackupFileList = append(BackupFileList, configs.ARKBackupDir+"/"+entities[i].Name()) } //获取实际的插件配置位置 urls := ReadArkBackupUrl(configs.ArkApiInstallUrl) for _, url := range urls { ServerConfigUrls = append(ServerConfigUrls, url+"/ArkApi/Plugins/ArkShop/config.json") } } func BackupFile() error { //穿件备份文件夹 os.MkdirAll(configs.ARKBackupDir, 0755) name := "" //创建备份文件 split := strings.Split(configs.ARKJsonFilePath, "/") split = strings.Split(split[len(split)-1], ".") name = split[0] + "-" + time.Now().Format("20060102150405") for i := 1; i < len(split); i++ { name += "." + split[i] } return CopyFile(configs.ARKJsonFilePath, configs.ARKBackupDir+"/"+name) } // CopyFile 复制文件 func CopyFile(src, dest string) error { // 打开源文件 sourceFile, err := os.Open(src) if err != nil { return err } defer sourceFile.Close() // 创建目标文件 split := strings.Split(dest, "/") str := "" for i := 0; i < len(split)-1; i++ { str += split[i] + "/" err := os.MkdirAll(str, 0755) if err != nil { fmt.Println(err) } } destinationFile, err := os.Create(dest) if err != nil { return err } defer destinationFile.Close() // 复制文件内容 _, err = io.Copy(destinationFile, sourceFile) if err != nil { return err } // 确保数据写入目标文件 err = destinationFile.Sync() if err != nil { return err } return nil } // InstallZip 安装服务器插件 func InstallZip(compulsion bool, url string) { entries, err := os.ReadDir(url) if err != nil { fmt.Println(err) } if !compulsion { for i := range entries { if entries[i].IsDir() && entries[i].Name() == "ArkApi" { return } } } else { for i := range entries { if entries[i].IsDir() && entries[i].Name() == "ArkApi" { //删除 os.RemoveAll(url + "/ArkApi") break } } } err = Unzip(configs.ARKAPiZipPath, url) } // ReadArkBackupUrl 读取服务器路径的实际位置 func ReadArkBackupUrl(dir string) []string { resourcesDir := make([]string, 0) // 读取目录内容 entries, err := os.ReadDir(dir) if err != nil { fmt.Println(err) return resourcesDir } // 遍历目录内容 for _, entry := range entries { if entry.IsDir() { readDir, err := os.ReadDir(dir + "/" + entry.Name()) if err != nil { fmt.Println(err) return resourcesDir } existEngineDir := false existShooterGameDir := false existSteamapps := false for _, subentry := range readDir { if subentry.IsDir() && subentry.Name() == "Engine" { existEngineDir = true } if subentry.IsDir() && subentry.Name() == "ShooterGame" { existShooterGameDir = true } if subentry.IsDir() && subentry.Name() == "steamapps" { existSteamapps = true } } if existEngineDir && existShooterGameDir && existSteamapps { resourcesDir = append(resourcesDir, dir+"/"+entry.Name()+"/ShooterGame/Binaries/Win64") } } } return resourcesDir } // Unzip 解压缩ZIP文件到目标路径 func Unzip(src, dest string) error { // 打开ZIP文件 reader, err := zip.OpenReader(src) if err != nil { return err } defer reader.Close() // 创建目标路径 if err := os.MkdirAll(dest, 0755); err != nil { return err } // 解压每个文件 for _, file := range reader.File { filePath := filepath.Join(dest, file.Name) // 检查文件的目录结构 if !strings.HasPrefix(filePath, filepath.Clean(dest)+string(os.PathSeparator)) { return fmt.Errorf("非法文件路径: %s", filePath) } if file.FileInfo().IsDir() { // 创建目录 if err := os.MkdirAll(filePath, file.Mode()); err != nil { return err } } else { // 创建文件所在的目录 if err := os.MkdirAll(filepath.Dir(filePath), file.Mode()); err != nil { return err } // 打开ZIP中的文件 zipFile, err := file.Open() if err != nil { return err } defer zipFile.Close() // 创建输出文件 outputFile, err := os.OpenFile(filePath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, file.Mode()) if err != nil { return err } defer outputFile.Close() // 将内容拷贝到输出文件 _, err = io.Copy(outputFile, zipFile) if err != nil { return err } } } return nil }