From 2ca9ac7a1b55d75a89393e59f892c9ae3e27a98d Mon Sep 17 00:00:00 2001 From: Falko Habel Date: Wed, 19 Jun 2024 10:58:32 +0200 Subject: [PATCH] multi response capabilitys added --- main.go | 65 ++++++++++++++++++++++----------------------------------- 1 file changed, 25 insertions(+), 40 deletions(-) diff --git a/main.go b/main.go index 4581e26..97936c2 100644 --- a/main.go +++ b/main.go @@ -10,6 +10,7 @@ import ( "os" "os/exec" "path/filepath" + "sync" "time" ) @@ -19,7 +20,6 @@ type Message struct { To string `json:"to"` } -// Note: The StreamResponse structure simplified for demonstration. Adjust according to actual requirements. type StreamResponse struct { From string `json:"from"` To string `json:"to"` @@ -44,7 +44,6 @@ func createStreamResponse(fromLanguage, toLanguage, message string) string { } func streamResponse(w http.ResponseWriter, fromLanguage, toLanguage string, messages <-chan string) { - // Set headers for SSE w.Header().Set("Content-Type", "text/event-stream") w.Header().Set("Cache-Control", "no-cache") w.Header().Set("Connection", "keep-alive") @@ -58,20 +57,16 @@ func streamResponse(w http.ResponseWriter, fromLanguage, toLanguage string, mess for msg := range messages { formattedMessage := createStreamResponse(fromLanguage, toLanguage, msg) fmt.Fprintf(w, " %s\n\n", formattedMessage) - flusher.Flush() // Ensure client receives the update immediately + flusher.Flush() } } func downloadPackages(w http.ResponseWriter, fromLanguage, toLanguage string) { - - // Create a channel to send messages from the download process messages := make(chan string) defer close(messages) - // Use a goroutine for streaming responses so we can proceed with the download go streamResponse(w, fromLanguage, toLanguage, messages) - // Start the python command in the background cmd := exec.Command(linux, "translator/download.py", fromLanguage, toLanguage) output, err := cmd.StdoutPipe() if err != nil { @@ -85,10 +80,8 @@ func downloadPackages(w http.ResponseWriter, fromLanguage, toLanguage string) { return } - // Initial message sent to the channel for streaming messages <- "Download started..." - // Start a ticker to send "..." every few seconds until we get real output ticker := time.NewTicker(2 * time.Second) go func() { for range ticker.C { @@ -96,19 +89,16 @@ func downloadPackages(w http.ResponseWriter, fromLanguage, toLanguage string) { } }() - // Read the output of the python command and send it to the channel scanner := bufio.NewScanner(output) firstOutputReceived := false for scanner.Scan() { if !firstOutputReceived { - // Stop the ticker after receiving the first real output ticker.Stop() firstOutputReceived = true } messages <- scanner.Text() } - // Wait for the command to complete err = cmd.Wait() if err != nil { messages <- fmt.Sprintf("Error waiting for Download: %s", err.Error()) @@ -117,14 +107,10 @@ func downloadPackages(w http.ResponseWriter, fromLanguage, toLanguage string) { } func executeTranslator(w http.ResponseWriter, message, fromLanguage, toLanguage string) { - // Create a message channel for streaming translation results messages := make(chan string) defer close(messages) - // A goroutine will manage sending streamed responses go streamResponse(w, fromLanguage, toLanguage, messages) - - // Start the python command in the background cmd := exec.Command(linux, "translator/translate.py", message, fromLanguage, toLanguage) output, err := cmd.StdoutPipe() if err != nil { @@ -138,13 +124,11 @@ func executeTranslator(w http.ResponseWriter, message, fromLanguage, toLanguage return } - // Read the output of the python command and send it through the channel scanner := bufio.NewScanner(output) for scanner.Scan() { - messages <- scanner.Text() // Sends each line of the output to the stream + messages <- scanner.Text() } - // Wait for the command to complete err = cmd.Wait() if err != nil { messages <- fmt.Sprintf("Error waiting for Translation: %s", err.Error()) @@ -153,27 +137,24 @@ func executeTranslator(w http.ResponseWriter, message, fromLanguage, toLanguage } func CheckLanguagesInstalled(fromCode, toCode string) (bool, error) { - // Construct the target directory path homeDir, err := os.UserHomeDir() if err != nil { return false, fmt.Errorf("unable to determine the user home directory: %w", err) } targetDir := filepath.Join(homeDir, ".local", "share", "argos-translate", "packages", fromCode+"_"+toCode) - // Check if the directory exists _, err = os.Stat(targetDir) if err != nil { if os.IsNotExist(err) { - return false, nil // Directory does not exist, indicating the language pair is not installed + return false, nil } return false, fmt.Errorf("error checking for language directory: %w", err) } - // The directory exists, indicating the language pair is installed return true, nil } + func handleRequest(w http.ResponseWriter, r *http.Request) { - // Read the request body if r.Header.Get("Content-Type") != "application/json" { http.Error(w, "Request content type must be application/json", http.StatusBadRequest) return @@ -185,7 +166,6 @@ func handleRequest(w http.ResponseWriter, r *http.Request) { } defer r.Body.Close() - // Unmarshal the JSON data var msg Message err = json.Unmarshal(body, &msg) if err != nil { @@ -193,37 +173,42 @@ func handleRequest(w http.ResponseWriter, r *http.Request) { return } - // Check if From and To fields are not longer than 2 letters if len(msg.From) > 2 || len(msg.To) > 2 { http.Error(w, "From and To fields should not be longer than 2 letters.", http.StatusBadRequest) return - } else { - installed, err := CheckLanguagesInstalled(msg.From, msg.To) - if err != nil { - if err.Error() == "file not found" { - http.Error(w, "file not found "+err.Error(), http.StatusInternalServerError) - } else { - fmt.Println("An error occurred:", err) - } - return + } + + installed, err := CheckLanguagesInstalled(msg.From, msg.To) + if err != nil { + if err.Error() == "file not found" { + http.Error(w, "file not found "+err.Error(), http.StatusInternalServerError) + } else { + fmt.Println("An error occurred:", err) } + return + } + + var wg sync.WaitGroup + wg.Add(1) + + go func() { + defer wg.Done() if installed { executeTranslator(w, msg.Message, msg.From, msg.To) } else { downloadPackages(w, msg.From, msg.To) } - } + }() + + wg.Wait() } func main() { - // Define the HTTP handler function - http.HandleFunc("/", handleRequest) // This ensures all requests are routed to handleRequest + http.HandleFunc("/", handleRequest) - // Define the port port := "53184" address := fmt.Sprintf("0.0.0.0:%s", port) - // Start the HTTP server fmt.Printf("Listening on %s...\n", address) err := http.ListenAndServe(address, nil) if err != nil {