diff --git a/main.go b/main.go index d94768d..a1262cf 100644 --- a/main.go +++ b/main.go @@ -10,9 +10,11 @@ import ( "log" "net/http" "os" + "os/exec" "path/filepath" "sort" "strings" + "time" ) const ( @@ -56,21 +58,7 @@ func findLatestScreenshot(desktop string) (string, error) { return filepath.Join(desktop, screenshots[0].Name()), nil } -func screenshotHandler(w http.ResponseWriter, r *http.Request) { - if r.Method != http.MethodGet { - http.Error(w, "GET only", http.StatusMethodNotAllowed) - return - } - - desktop := getDesktopPath() - path, err := findLatestScreenshot(desktop) - if err != nil { - http.Error(w, err.Error(), http.StatusNotFound) - log.Println("No screenshot:", err) - return - } - - // Open and serve +func serveAndDelete(w http.ResponseWriter, path string) { f, err := os.Open(path) if err != nil { http.Error(w, "Cannot open file", http.StatusInternalServerError) @@ -88,7 +76,6 @@ func screenshotHandler(w http.ResponseWriter, r *http.Request) { return } - // Delete after successful send f.Close() if err := os.Remove(path); err != nil { log.Println("Warning: could not delete:", err) @@ -97,19 +84,63 @@ func screenshotHandler(w http.ResponseWriter, r *http.Request) { } } +func screenshotHandler(w http.ResponseWriter, r *http.Request) { + if r.Method != http.MethodGet { + http.Error(w, "GET only", http.StatusMethodNotAllowed) + return + } + + desktop := getDesktopPath() + path, err := findLatestScreenshot(desktop) + if err != nil { + http.Error(w, err.Error(), http.StatusNotFound) + log.Println("No screenshot:", err) + return + } + + serveAndDelete(w, path) +} + +func captureHandler(w http.ResponseWriter, r *http.Request) { + if r.Method != http.MethodPost { + http.Error(w, "POST only", http.StatusMethodNotAllowed) + return + } + + display := r.URL.Query().Get("display") + if display == "" { + display = "1" + } + + tmpFile := filepath.Join(os.TempDir(), fmt.Sprintf("capture-%d.png", time.Now().UnixNano())) + + cmd := exec.Command("screencapture", "-x", "-D", display, tmpFile) + if out, err := cmd.CombinedOutput(); err != nil { + http.Error(w, fmt.Sprintf("capture failed: %v: %s", err, out), http.StatusInternalServerError) + log.Printf("Capture failed (display %s): %v: %s", display, err, out) + os.Remove(tmpFile) + return + } + + log.Printf("Captured display %s", display) + serveAndDelete(w, tmpFile) +} + func healthHandler(w http.ResponseWriter, r *http.Request) { w.Write([]byte("ok")) } func main() { http.HandleFunc("/screenshot", screenshotHandler) + http.HandleFunc("/capture", captureHandler) http.HandleFunc("/health", healthHandler) log.Printf("Screenshot server starting on %s", port) log.Printf("Desktop: %s", getDesktopPath()) log.Printf("Endpoints:") - log.Printf(" GET /screenshot - fetch & delete latest screenshot") - log.Printf(" GET /health - health check") + log.Printf(" GET /screenshot - fetch & delete latest screenshot") + log.Printf(" POST /capture?display=N - take screenshot of display N") + log.Printf(" GET /health - health check") if err := http.ListenAndServe(port, nil); err != nil { log.Fatal(err)