package main import ( "bufio" "bytes" "encoding/json" "fmt" "io" "log" "net/http" "os" "strings" socketio "github.com/googollee/go-socket.io" ) type UpdatePayload struct { Action string `json:"action"` Target string `json:"target"` Drive string `json:"drive"` } func registerUpdateChannel(server *socketio.Server) { server.OnEvent("/", "subscribe:update", func(s socketio.Conn) { s.Join("update") s.Emit("updateLogs", "👋 Subscribed to update channel") fmt.Println("📺", s.ID(), "joined update room") }) // copy files based on the target passed over server.OnEvent("/", "update", func(s socketio.Conn, payload UpdatePayload) { switch strings.ToLower(payload.Action) { case "copy": copyLatestBuild(server, payload.Target, payload.Drive) case "update": updateServer(server, payload.Target) default: server.BroadcastToRoom("/", "update", "updateLogs", fmt.Sprintf("❓ Unknown action: %s", payload.Action)) } }) server.OnEvent("/", "unsubscribe:update", func(s socketio.Conn) { s.Leave("update") s.Emit("updateLogs", "👋 Unsubscribed from update logs") }) } func updateServer(server *socketio.Server, target string) { host, err := os.Hostname() if err != nil { server.BroadcastToRoom("/", "update", "updateLogs", "Could not retrieve hostname") return } log.Printf("Host value: [%q]", host) if strings.Contains(host, "VMS") || strings.Contains(host, "vms") { server.BroadcastToRoom("/", "update", "updateLogs", "Your are about to check for a new build and then update the server.") //go UpdateApp(server) // Kick off the update go func() { updates := UpdateApp(server) // returns <-chan string for msg := range updates { fmt.Println(msg) //server.BroadcastToRoom("/", "update", "updateLogs", msg) } }() return } if target == "" { server.BroadcastToRoom("/", "update", "updateLogs", "You seem to be on a dev server or not an actual production server, you MUST pass a server over. I.E. USMCD1VMS036") return } else { server.BroadcastToRoom("/", "update", "updateLogs", fmt.Sprintf("Running remote update on: %v", target)) go triggerRemoteUpdate(server, target, UpdatePayload{Action: "update", Target: target}) } } func copyLatestBuild(server *socketio.Server, target string, drive string) { server.BroadcastToRoom("/", "update", "updateLogs", fmt.Sprintf("🚀 Copying latest build to %v", target)) copyBuild(server, target, drive) } func triggerRemoteUpdate(server *socketio.Server, remoteURL string, payload UpdatePayload) { fmt.Println("running the update process") basePath := "/api/controller" if os.Getenv("NODE_ENV") != "production" { basePath = "/lst/api/controller" } // send POST request with JSON, expect SSE / streaming text back body, _ := json.Marshal(payload) url := fmt.Sprintf("https://%v.alpla.net%v/update", remoteURL, basePath) fmt.Println(url) //url := fmt.Sprintf("http://%v:8080/api/controller/update", remoteURL) fmt.Println(url) resp, err := http.Post(url, "application/json", bytes.NewBuffer(body)) if err != nil { log.Println("❌ Cannot connect remote:", err) return } defer resp.Body.Close() decoder := bufio.NewReader(resp.Body) for { line, err := decoder.ReadString('\n') if err != nil { if err != io.EOF { log.Println("❌ Error reading stream:", err) } break } //fmt.Println(line) parsed := strings.TrimSpace(line) if parsed != "" { log.Println("📡 Remote log:", parsed) server.BroadcastToRoom("/", "update", "updateLogs", parsed) } } }