package main import ( "fmt" "os" "strings" "path/filepath" c "github.com/TwiN/go-color" "github.com/gin-gonic/gin" ) func main() { if len(os.Args) < 2 { fmt.Println(c.InRed("No target directory specified!")) fmt.Println(c.InBlue("Run 'mercury-sync help' for more information.")) os.Exit(1) } target := os.Args[1] fi, err := os.Stat(target) if err != nil { fmt.Println(c.InRed("Target directory ") + c.InUnderline(c.InPurple(target)) + c.InRed(" does not exist!")) os.Exit(1) } if !fi.IsDir() { fmt.Println(c.InUnderline(c.InPurple(target)) + c.InRed(" is a file, please choose a directory to sync with!")) os.Exit(1) } gin.SetMode(gin.ReleaseMode) r := gin.New() r.Use(gin.Recovery()) r.SetTrustedProxies([]string{"127.0.0.1"}) r.GET("/", func(cx *gin.Context) { cx.String(200, "Mercury Sync") }) r.GET("/sync", func(cx *gin.Context) { fmt.Println(c.InYellow("Syncing...")) // Create struct for JSON response type File struct { Path []string `json:"path"` Content string `json:"content"` Type string `json:"type"` } var Response struct { Files []File `json:"files"` // Message string `json:"message"` } usedScripts := make(map[string]bool) // Read files recursively and send them to the client filepath.Walk(target, func(path string, info os.FileInfo, err error) error { if err != nil { fmt.Println(c.InRed("Error while reading file:"), err.Error()) return nil } if info.IsDir() { return nil } var filetype string var scripttype string switch strings.ToLower(filepath.Ext(path)) { case ".lua": filetype = "lua" case ".luau": filetype = "luau" case ".moon": filetype = "moon" case ".yue": filetype = "yue" default: return nil } // Trim target directory and extension from path, and remove suffix if it's a server/client script formatPath := strings.TrimPrefix(path, target+string(os.PathSeparator)) formatPath = strings.TrimSuffix(formatPath, "."+filetype) if strings.Contains(formatPath, ".") { scripttype = strings.Split(formatPath, ".")[1] if scripttype == "server" || scripttype == "client" { formatPath = strings.Split(formatPath, ".")[0] } } if scripttype == "" { // scripttype = "module" fmt.Println(c.InRed("Unknown script type: ") + c.InUnderline(c.InPurple(formatPath)) + c.InRed("!")) fmt.Println(c.InYellow("If you were trying to sync a ModuleScript, these are not supported by Mercury Sync. Please transpose them manually.")) return nil } formatPath = strings.ReplaceAll(formatPath, string(os.PathSeparator), "$dot$") filename := strings.Split(formatPath, "$dot$")[len(strings.Split(formatPath, "$dot$"))-1] if filename == "init" { formatPath = strings.TrimSuffix(formatPath, "$dot$init") } dottedPath := strings.ReplaceAll(formatPath, "$dot$", ".") if usedScripts[formatPath] { fmt.Println(c.InRed("Duplicate filename: ") + c.InUnderline(c.InPurple(dottedPath)) + c.InRed("! Skipping...")) return nil } usedScripts[formatPath] = true var content string switch filetype { case "luau": fmt.Println(c.InBlue("Compiling ") + c.InUnderline(c.InPurple(dottedPath)) + c.InBlue("...")) content, err = CompileLuau(path) if content == "" { fmt.Println(c.InYellow("After compilation, file ") + c.InUnderline(c.InPurple(dottedPath)) + c.InYellow(" was empty!")) content = "-- Mercury Sync: Empty file" } if err != nil { fmt.Println(c.InRed("Error while compiling Luau file:"), err) if strings.Contains(err.Error(), "file does not exist") || strings.Contains(err.Error(), "no such file or directory") { fmt.Println(c.InYellow("Please place a copy of darklua (name \"darklua\" or \"darklua.exe\") in the tools folder.")) } return nil } default: file, err := os.ReadFile(path) if err != nil { fmt.Println(c.InRed("Error while reading file:"), err) return nil } content = string(file) if content == "" { fmt.Println(c.InYellow("File ") + c.InUnderline(c.InPurple(dottedPath)) + c.InYellow(" is empty!")) content = "-- Mercury Sync: Empty file" } } fmt.Println(c.InGreen("Sending ") + c.InUnderline(c.InPurple(dottedPath)) + c.InGreen("...")) scriptFile := File{ Path: strings.Split(formatPath, "$dot$"), Content: strings.ReplaceAll(content, "\r\n", "\n"), Type: scripttype, } if filename == "init" { Response.Files = append([]File{scriptFile}, Response.Files...) } else { Response.Files = append(Response.Files, scriptFile) } return nil }) // os.Remove("./temp.lua") cx.JSON(200, Response) }) fmt.Println(c.InBold(c.InGreen("~ Mercury Sync ~"))) r.Run("0.0.0.0:2013") }