diff --git a/server/README.md b/server/README.md index 9eef65d7..4d921b2d 100644 --- a/server/README.md +++ b/server/README.md @@ -44,6 +44,28 @@ curl http://localhost:10001/recording/stop -d {} curl http://localhost:10001/recording/download --output recording.mp4 ``` +#### Additional routes + +```bash +# Clipboard operations +# | GET /clipboard - Get clipboard content +curl http://localhost:10001/clipboard + +# | POST /clipboard - Set clipboard content +curl -X POST -H "Content-Type: application/json" \ + --data '{"type":"text","text":"Hello from clipboard!"}' \ + http://localhost:10001/clipboard + +# | GET /clipboard/stream - Stream clipboard changes as SSE +# Keep this running in one terminal +curl -N http://localhost:10001/clipboard/stream + +# In another terminal, set clipboard content to see events +curl -X POST -H "Content-Type: application/json" \ + --data '{"type":"text","text":"Clipboard update"}' \ + http://localhost:10001/clipboard +``` + ### ⚙️ Configuration Configure the server using environment variables: diff --git a/server/cmd/api/api/api.go b/server/cmd/api/api/api.go index 21f5794c..4f8af9cb 100644 --- a/server/cmd/api/api/api.go +++ b/server/cmd/api/api/api.go @@ -22,6 +22,10 @@ type ApiService struct { // Filesystem watch management watchMu sync.RWMutex watches map[string]*fsWatch + // Server start time for health endpoint + startTime time.Time + // Clipboard management + clipboardManager *clipboardManager } var _ oapi.StrictServerInterface = (*ApiService)(nil) @@ -39,6 +43,7 @@ func New(recordManager recorder.RecordManager, factory recorder.FFmpegRecorderFa factory: factory, defaultRecorderID: "default", watches: make(map[string]*fsWatch), + startTime: time.Now(), }, nil } @@ -235,3 +240,12 @@ func (s *ApiService) ListRecorders(ctx context.Context, _ oapi.ListRecordersRequ func (s *ApiService) Shutdown(ctx context.Context) error { return s.recordManager.StopAll(ctx) } + +// GetHealth implements the health check endpoint +func (s *ApiService) GetHealth(ctx context.Context, _ oapi.GetHealthRequestObject) (oapi.GetHealthResponseObject, error) { + uptimeSec := int(time.Since(s.startTime).Seconds()) + return oapi.GetHealth200JSONResponse{ + Status: oapi.Ok, + UptimeSec: uptimeSec, + }, nil +} diff --git a/server/cmd/api/api/clipboard.go b/server/cmd/api/api/clipboard.go new file mode 100644 index 00000000..2b678a67 --- /dev/null +++ b/server/cmd/api/api/clipboard.go @@ -0,0 +1,275 @@ +package api + +import ( + "context" + "encoding/json" + "fmt" + "os" + "os/exec" + "strings" + "sync" + "time" + + "github.com/onkernel/kernel-images/server/lib/logger" + oapi "github.com/onkernel/kernel-images/server/lib/oapi" +) + +// clipboardManager handles clipboard operations +type clipboardManager struct { + mu sync.Mutex + lastContent string + watchers map[string]chan oapi.ClipboardEvent + watchersMu sync.RWMutex + lastEventTime time.Time +} + +// newClipboardManager creates a new clipboard manager +func newClipboardManager() *clipboardManager { + cm := &clipboardManager{ + watchers: make(map[string]chan oapi.ClipboardEvent), + lastEventTime: time.Now(), + } + return cm +} + +// getDisplay returns the DISPLAY environment variable or a default value +func getDisplay() string { + display := os.Getenv("DISPLAY") + if display == "" { + display = ":20" // Default display for testing + } + return display +} + +// getClipboardText retrieves text from the clipboard using xclip +func (cm *clipboardManager) getClipboardText(ctx context.Context) (string, error) { + log := logger.FromContext(ctx) + display := getDisplay() + + cmd := exec.CommandContext(ctx, "bash", "-lc", fmt.Sprintf("DISPLAY=%s xclip -selection clipboard -o 2>/dev/null || echo ''", display)) + out, err := cmd.Output() + if err != nil { + log.Error("failed to get clipboard content with xclip", "err", err) + return "", fmt.Errorf("failed to get clipboard: %w", err) + } + + return strings.TrimSpace(string(out)), nil +} + +// setClipboardText sets text to the clipboard using xclip +func (cm *clipboardManager) setClipboardText(ctx context.Context, text string) error { + log := logger.FromContext(ctx) + display := getDisplay() + + // Create a temporary file to store the content (more reliable than piping for large content) + cmd := exec.CommandContext(ctx, "bash", "-lc", fmt.Sprintf("printf %%s %s | DISPLAY=%s xclip -selection clipboard", + escapeShellString(text), display)) + err := cmd.Run() + if err != nil { + log.Error("failed to set clipboard content with xclip", "err", err) + return fmt.Errorf("failed to set clipboard: %w", err) + } + + return nil +} + +// escapeShellString escapes a string for use in shell commands +func escapeShellString(s string) string { + return fmt.Sprintf("'%s'", strings.Replace(s, "'", "'\\''", -1)) +} + +// GetClipboard retrieves clipboard content +func (s *ApiService) GetClipboard(ctx context.Context, _ oapi.GetClipboardRequestObject) (oapi.GetClipboardResponseObject, error) { + log := logger.FromContext(ctx) + log.Info("getting clipboard content") + + // Initialize clipboard manager if not already done + if s.clipboardManager == nil { + s.clipboardManager = newClipboardManager() + } + + text, err := s.clipboardManager.getClipboardText(ctx) + if err != nil { + log.Error("error getting clipboard content", "err", err) + // Return empty text content on error + return oapi.GetClipboard200JSONResponse{ + Type: oapi.Text, + Text: new(string), + }, nil + } + + return oapi.GetClipboard200JSONResponse{ + Type: oapi.Text, + Text: &text, + }, nil +} + +// SetClipboard sets clipboard content +func (s *ApiService) SetClipboard(ctx context.Context, req oapi.SetClipboardRequestObject) (oapi.SetClipboardResponseObject, error) { + log := logger.FromContext(ctx) + log.Info("setting clipboard content", "type", req.Body.Type) + + // Initialize clipboard manager if not already done + if s.clipboardManager == nil { + s.clipboardManager = newClipboardManager() + } + + if req.Body.Type != oapi.Text { + log.Error("unsupported clipboard content type", "type", req.Body.Type) + return oapi.SetClipboard400JSONResponse{ + BadRequestErrorJSONResponse: oapi.BadRequestErrorJSONResponse{ + Message: "only text clipboard content is supported", + }, + }, nil + } + + if req.Body.Text == nil { + log.Error("text content is required for text type") + return oapi.SetClipboard400JSONResponse{ + BadRequestErrorJSONResponse: oapi.BadRequestErrorJSONResponse{ + Message: "text content is required for text type", + }, + }, nil + } + + err := s.clipboardManager.setClipboardText(ctx, *req.Body.Text) + if err != nil { + log.Error("failed to set clipboard content", "err", err) + return oapi.SetClipboard500JSONResponse{ + InternalErrorJSONResponse: oapi.InternalErrorJSONResponse{ + Message: "failed to set clipboard content", + }, + }, nil + } + + // Update content for stream notifications + s.clipboardManager.mu.Lock() + oldContent := s.clipboardManager.lastContent + s.clipboardManager.lastContent = *req.Body.Text + s.clipboardManager.mu.Unlock() + + // If content changed, notify watchers + if oldContent != *req.Body.Text { + s.notifyClipboardChange(ctx, oapi.Text, *req.Body.Text) + } + + return oapi.SetClipboard200JSONResponse{ + Ok: true, + }, nil +} + +// StreamClipboard streams clipboard changes as SSE events +func (s *ApiService) StreamClipboard(ctx context.Context, _ oapi.StreamClipboardRequestObject) (oapi.StreamClipboardResponseObject, error) { + log := logger.FromContext(ctx) + log.Info("starting clipboard stream") + + // Initialize clipboard manager if not already done + if s.clipboardManager == nil { + s.clipboardManager = newClipboardManager() + } + + // Create a unique watcher ID + watcherID := fmt.Sprintf("clipboard-%d", time.Now().UnixNano()) + + // Create a channel for this watcher + events := make(chan oapi.ClipboardEvent, 10) + + // Register the watcher + s.clipboardManager.watchersMu.Lock() + s.clipboardManager.watchers[watcherID] = events + s.clipboardManager.watchersMu.Unlock() + + // Cleanup when the stream ends + cleanup := func() { + s.clipboardManager.watchersMu.Lock() + delete(s.clipboardManager.watchers, watcherID) + s.clipboardManager.watchersMu.Unlock() + close(events) + log.Info("clipboard stream ended", "watcher", watcherID) + } + + // Start a goroutine to poll clipboard content + go s.pollClipboard(ctx, watcherID) + + return &oapi.StreamClipboardResponseStream{ + Headers: oapi.StreamClipboard200ResponseHeaders{ + XSSEContentType: "application/json", + }, + Events: events, + Cleanup: cleanup, + }, nil +} + +// pollClipboard periodically polls clipboard content and notifies watchers of changes +func (s *ApiService) pollClipboard(ctx context.Context, watcherID string) { + log := logger.FromContext(ctx) + ticker := time.NewTicker(1 * time.Second) + defer ticker.Stop() + + lastText := "" + + for { + select { + case <-ctx.Done(): + log.Info("clipboard polling stopped due to context cancellation") + return + case <-ticker.C: + text, err := s.clipboardManager.getClipboardText(ctx) + if err != nil { + log.Error("error polling clipboard", "err", err) + continue + } + + if text != lastText { + log.Info("clipboard content changed") + lastText = text + s.notifyClipboardChange(ctx, oapi.Text, text) + } + } + } +} + +// notifyClipboardChange notifies all registered watchers of a clipboard change +func (s *ApiService) notifyClipboardChange(ctx context.Context, contentType oapi.ClipboardContentType, content string) { + log := logger.FromContext(ctx) + s.clipboardManager.mu.Lock() + s.clipboardManager.lastContent = content + s.clipboardManager.lastEventTime = time.Now() + s.clipboardManager.mu.Unlock() + + // Create a preview of the content + preview := content + if len(preview) > 100 { + preview = preview[:100] + } + + // Create the event + event := oapi.ClipboardEvent{ + Ts: time.Now().Format(time.RFC3339), + Type: contentType, + Preview: &preview, + } + + // Get a copy of the watchers to avoid holding the lock while sending + s.clipboardManager.watchersMu.RLock() + watchers := make([]chan oapi.ClipboardEvent, 0, len(s.clipboardManager.watchers)) + for _, ch := range s.clipboardManager.watchers { + watchers = append(watchers, ch) + } + s.clipboardManager.watchersMu.RUnlock() + + // Send event to all watchers + for _, ch := range watchers { + select { + case ch <- event: + // Sent successfully + default: + // Channel buffer is full, skip this event for this watcher + log.Warn("skipped clipboard event for watcher with full buffer") + } + } + + // Log the event + eventJSON, _ := json.Marshal(event) + log.Info("sent clipboard change event", "event", string(eventJSON)) +} diff --git a/server/cmd/api/api/clipboard_test.go b/server/cmd/api/api/clipboard_test.go new file mode 100644 index 00000000..8dd8ab59 --- /dev/null +++ b/server/cmd/api/api/clipboard_test.go @@ -0,0 +1,80 @@ +package api + +import ( + "context" + "testing" + "time" + + oapi "github.com/onkernel/kernel-images/server/lib/oapi" + "github.com/stretchr/testify/assert" +) + +func TestClipboardContentTypes(t *testing.T) { + // Simple test to verify the clipboard content types are defined correctly + assert.Equal(t, oapi.ClipboardContentType("text"), oapi.Text) + assert.Equal(t, oapi.ClipboardContentType("image"), oapi.Image) +} + +// Mock clipboard manager for testing +type mockClipboardManager struct { + getTextFunc func(ctx context.Context) (string, error) + setTextFunc func(ctx context.Context, text string) error +} + +func (m *mockClipboardManager) getClipboardText(ctx context.Context) (string, error) { + if m.getTextFunc != nil { + return m.getTextFunc(ctx) + } + return "", nil +} + +func (m *mockClipboardManager) setClipboardText(ctx context.Context, text string) error { + if m.setTextFunc != nil { + return m.setTextFunc(ctx, text) + } + return nil +} + +// Simple test for clipboard response creation +func TestClipboardResponseTypes(t *testing.T) { + // Test clipboard content response creation + text := "Test clipboard content" + clipboardContent := oapi.ClipboardContent{ + Type: oapi.Text, + Text: &text, + } + + // Test GetClipboard200JSONResponse + getResponse := oapi.GetClipboard200JSONResponse(clipboardContent) + assert.Equal(t, oapi.Text, getResponse.Type) + assert.Equal(t, &text, getResponse.Text) + + // Test SetClipboard200JSONResponse + setResponse := oapi.SetClipboard200JSONResponse{ + Ok: true, + } + assert.True(t, setResponse.Ok) + + // Test SetClipboard400JSONResponse + errorMsg := "error message" + badRequestResponse := oapi.SetClipboard400JSONResponse{ + BadRequestErrorJSONResponse: oapi.BadRequestErrorJSONResponse{ + Message: errorMsg, + }, + } + assert.Equal(t, errorMsg, badRequestResponse.Message) +} + +// Test ClipboardEvent struct +func TestClipboardEvent(t *testing.T) { + preview := "Test preview" + event := oapi.ClipboardEvent{ + Ts: time.Now().Format(time.RFC3339), + Type: oapi.Text, + Preview: &preview, + } + + assert.NotEmpty(t, event.Ts) + assert.Equal(t, oapi.Text, event.Type) + assert.Equal(t, &preview, event.Preview) +} diff --git a/server/cmd/api/api/server_handlers.go b/server/cmd/api/api/server_handlers.go new file mode 100644 index 00000000..58d6e6a9 --- /dev/null +++ b/server/cmd/api/api/server_handlers.go @@ -0,0 +1,142 @@ +package api + +import ( + "encoding/json" + "net/http" + + "github.com/go-chi/chi/v5" + oapi "github.com/onkernel/kernel-images/server/lib/oapi" +) + +// ClipboardHandler is a wrapper that implements http.Handler to handle clipboard requests +type ClipboardHandler struct { + ApiHandler *ApiService +} + +// ServeHTTP handles HTTP requests for clipboard endpoints +func (h *ClipboardHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { + path := r.URL.Path + + switch { + case path == "/clipboard" && r.Method == http.MethodGet: + h.GetClipboard(w, r) + case path == "/clipboard" && r.Method == http.MethodPost: + h.SetClipboard(w, r) + case path == "/clipboard/stream" && r.Method == http.MethodGet: + h.StreamClipboard(w, r) + default: + http.NotFound(w, r) + } +} + +// GetClipboard handles the GET /clipboard endpoint +func (h *ClipboardHandler) GetClipboard(w http.ResponseWriter, r *http.Request) { + res, err := h.ApiHandler.GetClipboard(r.Context(), oapi.GetClipboardRequestObject{}) + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + + if content, ok := res.(oapi.GetClipboard200JSONResponse); ok { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + json.NewEncoder(w).Encode(content) + } else { + http.Error(w, "Unexpected response type", http.StatusInternalServerError) + } +} + +// SetClipboard handles the POST /clipboard endpoint +func (h *ClipboardHandler) SetClipboard(w http.ResponseWriter, r *http.Request) { + var body oapi.ClipboardContent + if err := json.NewDecoder(r.Body).Decode(&body); err != nil { + http.Error(w, "Invalid request body", http.StatusBadRequest) + return + } + + res, err := h.ApiHandler.SetClipboard(r.Context(), oapi.SetClipboardRequestObject{Body: body}) + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + + if content, ok := res.(oapi.SetClipboard200JSONResponse); ok { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + json.NewEncoder(w).Encode(content) + } else if errResp, ok := res.(oapi.SetClipboard400JSONResponse); ok { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusBadRequest) + json.NewEncoder(w).Encode(errResp) + } else if serverErr, ok := res.(oapi.SetClipboard500JSONResponse); ok { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusInternalServerError) + json.NewEncoder(w).Encode(serverErr) + } else { + http.Error(w, "Unexpected response type", http.StatusInternalServerError) + } +} + +// StreamClipboard handles the GET /clipboard/stream endpoint +func (h *ClipboardHandler) StreamClipboard(w http.ResponseWriter, r *http.Request) { + res, err := h.ApiHandler.StreamClipboard(r.Context(), oapi.StreamClipboardRequestObject{}) + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + + if stream, ok := res.(*oapi.StreamClipboardResponseStream); ok { + w.Header().Set("Content-Type", "text/event-stream") + w.Header().Set("Cache-Control", "no-cache") + w.Header().Set("Connection", "keep-alive") + w.Header().Set("X-SSE-Content-Type", stream.Headers.XSSEContentType) + + flusher, ok := w.(http.Flusher) + if !ok { + http.Error(w, "Streaming not supported", http.StatusInternalServerError) + return + } + + // Send initial flush + flusher.Flush() + + // Use a defer to clean up when the stream ends + defer func() { + if stream.Cleanup != nil { + stream.Cleanup() + } + }() + + enc := json.NewEncoder(w) + for event := range stream.Events { + // Format as SSE + _, err := w.Write([]byte("event: data\ndata: ")) + if err != nil { + return + } + + err = enc.Encode(event) + if err != nil { + return + } + + _, err = w.Write([]byte("\n\n")) + if err != nil { + return + } + + flusher.Flush() + } + } else { + http.Error(w, "Unexpected response type", http.StatusInternalServerError) + } +} + +// RegisterClipboardHandlers registers the clipboard endpoints with the router +func RegisterClipboardHandlers(router chi.Router, apiService *ApiService) { + handler := &ClipboardHandler{ApiHandler: apiService} + + router.Get("/clipboard", handler.GetClipboard) + router.Post("/clipboard", handler.SetClipboard) + router.Get("/clipboard/stream", handler.StreamClipboard) +} diff --git a/server/cmd/api/main.go b/server/cmd/api/main.go index 50a56a14..5259a035 100644 --- a/server/cmd/api/main.go +++ b/server/cmd/api/main.go @@ -79,6 +79,9 @@ func main() { strictHandler := oapi.NewStrictHandler(apiService, nil) oapi.HandlerFromMux(strictHandler, r) + // Manually register our clipboard endpoints using the custom handler + api.RegisterClipboardHandlers(r, apiService) + // endpoints to expose the spec r.Get("/spec.yaml", func(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/vnd.oai.openapi") diff --git a/server/go.mod b/server/go.mod index fbbc9592..dd651284 100644 --- a/server/go.mod +++ b/server/go.mod @@ -3,32 +3,93 @@ module github.com/onkernel/kernel-images/server go 1.24.3 require ( + github.com/deepmap/oapi-codegen v1.16.3 github.com/fsnotify/fsnotify v1.9.0 github.com/getkin/kin-openapi v0.132.0 github.com/ghodss/yaml v1.0.0 github.com/go-chi/chi/v5 v5.2.1 github.com/kelseyhightower/envconfig v1.4.0 github.com/nrednav/cuid2 v1.1.0 - github.com/oapi-codegen/runtime v1.1.1 github.com/stretchr/testify v1.9.0 - golang.org/x/sync v0.15.0 + golang.org/x/sync v0.16.0 ) require ( + github.com/BurntSushi/toml v1.3.2 // indirect + github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53 // indirect + github.com/CloudyKit/jet/v6 v6.2.0 // indirect + github.com/Joker/jade v1.1.3 // indirect + github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06 // indirect + github.com/andybalholm/brotli v1.0.5 // indirect github.com/apapsch/go-jsonmerge/v2 v2.0.0 // indirect + github.com/aymerick/douceur v0.2.0 // indirect + github.com/bytedance/sonic v1.10.0-rc3 // indirect + github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d // indirect + github.com/chenzhuoyu/iasm v0.9.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect + github.com/fatih/structs v1.1.0 // indirect + github.com/flosch/pongo2/v4 v4.0.2 // indirect + github.com/gabriel-vasile/mimetype v1.4.2 // indirect + github.com/gin-contrib/sse v0.1.0 // indirect + github.com/gin-gonic/gin v1.9.1 // indirect github.com/go-openapi/jsonpointer v0.21.0 // indirect github.com/go-openapi/swag v0.23.0 // indirect + github.com/go-playground/locales v0.14.1 // indirect + github.com/go-playground/universal-translator v0.18.1 // indirect + github.com/go-playground/validator/v10 v10.14.1 // indirect + github.com/goccy/go-json v0.10.2 // indirect + github.com/golang/snappy v0.0.4 // indirect + github.com/gomarkdown/markdown v0.0.0-20230922112808-5421fefb8386 // indirect github.com/google/uuid v1.5.0 // indirect + github.com/gorilla/css v1.0.0 // indirect + github.com/iris-contrib/schema v0.0.6 // indirect github.com/josharian/intern v1.0.0 // indirect + github.com/json-iterator/go v1.1.12 // indirect + github.com/kataras/blocks v0.0.7 // indirect + github.com/kataras/golog v0.1.9 // indirect + github.com/kataras/iris/v12 v12.2.6-0.20230908161203-24ba4e8933b9 // indirect + github.com/kataras/pio v0.0.12 // indirect + github.com/kataras/sitemap v0.0.6 // indirect + github.com/kataras/tunnel v0.0.4 // indirect + github.com/klauspost/compress v1.16.7 // indirect + github.com/klauspost/cpuid/v2 v2.2.5 // indirect + github.com/labstack/echo/v4 v4.11.4 // indirect + github.com/labstack/gommon v0.4.2 // indirect + github.com/leodido/go-urn v1.2.4 // indirect + github.com/mailgun/raymond/v2 v2.0.48 // indirect github.com/mailru/easyjson v0.7.7 // indirect + github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect + github.com/microcosm-cc/bluemonday v1.0.25 // indirect + github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect + github.com/modern-go/reflect2 v1.0.2 // indirect github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect github.com/oasdiff/yaml v0.0.0-20250309154309-f31be36b4037 // indirect github.com/oasdiff/yaml3 v0.0.0-20250309153720-d2182401db90 // indirect + github.com/pelletier/go-toml/v2 v2.0.9 // indirect github.com/perimeterx/marshmallow v1.1.5 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/russross/blackfriday/v2 v2.1.0 // indirect + github.com/schollz/closestmatch v2.1.0+incompatible // indirect + github.com/sirupsen/logrus v1.8.1 // indirect + github.com/tdewolff/minify/v2 v2.12.9 // indirect + github.com/tdewolff/parse/v2 v2.6.8 // indirect + github.com/twitchyliquid64/golang-asm v0.15.1 // indirect + github.com/ugorji/go/codec v1.2.11 // indirect + github.com/valyala/bytebufferpool v1.0.0 // indirect + github.com/valyala/fasttemplate v1.2.2 // indirect + github.com/vmihailenco/msgpack/v5 v5.3.5 // indirect + github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect + github.com/yosssi/ace v0.0.5 // indirect + golang.org/x/arch v0.4.0 // indirect golang.org/x/crypto v0.40.0 // indirect + golang.org/x/net v0.41.0 // indirect golang.org/x/sys v0.34.0 // indirect + golang.org/x/text v0.27.0 // indirect + golang.org/x/time v0.5.0 // indirect + golang.org/x/xerrors v0.0.0-20220411194840-2f41105eb62f // indirect + google.golang.org/protobuf v1.31.0 // indirect + gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/server/go.sum b/server/go.sum index 40bb015b..3adea4c0 100644 --- a/server/go.sum +++ b/server/go.sum @@ -1,70 +1,268 @@ +github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8= +github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= +github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53 h1:sR+/8Yb4slttB4vD+b9btVEnWgL3Q00OBTzVT8B9C0c= +github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53/go.mod h1:+3IMCy2vIlbG1XG/0ggNQv0SvxCAIpPM5b1nCz56Xno= +github.com/CloudyKit/jet/v6 v6.2.0 h1:EpcZ6SR9n28BUGtNJSvlBqf90IpjeFr36Tizxhn/oME= +github.com/CloudyKit/jet/v6 v6.2.0/go.mod h1:d3ypHeIRNo2+XyqnGA8s+aphtcVpjP5hPwP/Lzo7Ro4= +github.com/Joker/hpp v1.0.0 h1:65+iuJYdRXv/XyN62C1uEmmOx3432rNG/rKlX6V7Kkc= +github.com/Joker/hpp v1.0.0/go.mod h1:8x5n+M1Hp5hC0g8okX3sR3vFQwynaX/UgSOM9MeBKzY= +github.com/Joker/jade v1.1.3 h1:Qbeh12Vq6BxURXT1qZBRHsDxeURB8ztcL6f3EXSGeHk= +github.com/Joker/jade v1.1.3/go.mod h1:T+2WLyt7VH6Lp0TRxQrUYEs64nRc83wkMQrfeIQKduM= github.com/RaveNoX/go-jsoncommentstrip v1.0.0/go.mod h1:78ihd09MekBnJnxpICcwzCMzGrKSKYe4AqU6PDYYpjk= +github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06 h1:KkH3I3sJuOLP3TjA/dfr4NAY8bghDwnXiU7cTKxQqo0= +github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06/go.mod h1:7erjKLwalezA0k99cWs5L11HWOAPNjdUZ6RxH1BXbbM= +github.com/ajg/form v1.5.1 h1:t9c7v8JUKu/XxOGBU0yjNpaMloxGEJhUkqFRq0ibGeU= +github.com/andybalholm/brotli v1.0.5 h1:8uQZIdzKmjc/iuPu7O2ioW48L81FgatrcpfFmiq/cCs= +github.com/andybalholm/brotli v1.0.5/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= github.com/apapsch/go-jsonmerge/v2 v2.0.0 h1:axGnT1gRIfimI7gJifB699GoE/oq+F2MU7Dml6nw9rQ= github.com/apapsch/go-jsonmerge/v2 v2.0.0/go.mod h1:lvDnEdqiQrp0O42VQGgmlKpxL1AP2+08jFMw88y4klk= +github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk= +github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4= github.com/bmatcuk/doublestar v1.1.1/go.mod h1:UD6OnuiIn0yFxxA2le/rnRU1G4RaI4UvFv1sNto9p6w= +github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM= +github.com/bytedance/sonic v1.10.0-rc/go.mod h1:ElCzW+ufi8qKqNW0FY314xriJhyJhuoJ3gFZdAHF7NM= +github.com/bytedance/sonic v1.10.0-rc3 h1:uNSnscRapXTwUgTyOF0GVljYD08p9X/Lbr9MweSV3V0= +github.com/bytedance/sonic v1.10.0-rc3/go.mod h1:iZcSUejdk5aukTND/Eu/ivjQuEL0Cu9/rf50Hi0u/g4= +github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY= +github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311/go.mod h1:b583jCggY9gE99b6G5LEC39OIiVsWj+R97kbl5odCEk= +github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d h1:77cEq6EriyTZ0g/qfRdp61a3Uu/AWrgIq2s0ClJV1g0= +github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d/go.mod h1:8EPpVsBuRksnlj1mLy4AWzRNQYxauNi62uWcE3to6eA= +github.com/chenzhuoyu/iasm v0.9.0 h1:9fhXjVzq5hUy2gkhhgHl95zG2cEAhw9OSGs8toWWAwo= +github.com/chenzhuoyu/iasm v0.9.0/go.mod h1:Xjy2NpN3h7aUqeqM+woSuuvxmIe6+DDsiNLIrkAmYog= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/deepmap/oapi-codegen v1.16.3 h1:GT9G86SbQtT1r8ZB+4Cybi9VGdu1P5ieNvNdEoCSbrA= +github.com/deepmap/oapi-codegen v1.16.3/go.mod h1:JD6ErqeX0nYnhdciLc61Konj3NBASREMlkHOgHn8WAM= +github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs= +github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo= +github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= +github.com/flosch/pongo2/v4 v4.0.2 h1:gv+5Pe3vaSVmiJvh/BZa82b7/00YUGm0PIyVVLop0Hw= +github.com/flosch/pongo2/v4 v4.0.2/go.mod h1:B5ObFANs/36VwxxlgKpdchIJHMvHB562PW+BWPhwZD8= github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k= github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= +github.com/gabriel-vasile/mimetype v1.4.2 h1:w5qFW6JKBz9Y393Y4q372O9A7cUSequkh1Q7OhCmWKU= +github.com/gabriel-vasile/mimetype v1.4.2/go.mod h1:zApsH/mKG4w07erKIaJPFiX0Tsq9BFQgN3qGY5GnNgA= github.com/getkin/kin-openapi v0.132.0 h1:3ISeLMsQzcb5v26yeJrBcdTCEQTag36ZjaGk7MIRUwk= github.com/getkin/kin-openapi v0.132.0/go.mod h1:3OlG51PCYNsPByuiMB0t4fjnNlIDnaEDsjiKUV8nL58= github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= +github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= +github.com/gin-gonic/gin v1.9.1 h1:4idEAncQnU5cB7BeOkPtxjfCSye0AAm1R0RVIqJ+Jmg= +github.com/gin-gonic/gin v1.9.1/go.mod h1:hPrL7YrpYKXt5YId3A/Tnip5kqbEAP+KLuI3SUcPTeU= github.com/go-chi/chi/v5 v5.2.1 h1:KOIHODQj58PmL80G2Eak4WdvUzjSJSm0vG72crDCqb8= github.com/go-chi/chi/v5 v5.2.1/go.mod h1:L2yAIGWB3H+phAw1NxKwWM+7eUH/lU8pOMm5hHcoops= github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ= github.com/go-openapi/jsonpointer v0.21.0/go.mod h1:IUyH9l/+uyhIYQ/PXVA41Rexl+kOkAPDdXEYns6fzUY= github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+GrE= github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ= +github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= +github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= +github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= +github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= +github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= +github.com/go-playground/validator/v10 v10.14.1 h1:9c50NUPC30zyuKprjL3vNZ0m5oG+jU0zvx4AqHGnv4k= +github.com/go-playground/validator/v10 v10.14.1/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU= github.com/go-test/deep v1.0.8 h1:TDsG77qcSprGbC6vTN8OuXp5g+J+b5Pcguhf7Zt61VM= -github.com/go-test/deep v1.0.8/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE= +github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= +github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU= +github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= +github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/gomarkdown/markdown v0.0.0-20230922112808-5421fefb8386 h1:EcQR3gusLHN46TAD+G+EbaaqJArt5vHhNpXAa12PQf4= +github.com/gomarkdown/markdown v0.0.0-20230922112808-5421fefb8386/go.mod h1:JDGcbDT52eL4fju3sZ4TeHGsQwhG9nbDV21aMyhwPoA= +github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/uuid v1.5.0 h1:1p67kYwdtXjb0gL0BPiP1Av9wiZPo5A8z2cWkTZ+eyU= github.com/google/uuid v1.5.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/gorilla/css v1.0.0 h1:BQqNyPTi50JCFMTw/b67hByjMVXZRwGha6wxVGkeihY= +github.com/gorilla/css v1.0.0/go.mod h1:Dn721qIggHpt4+EFCcTLTU/vk5ySda2ReITrtgBl60c= +github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= +github.com/imkira/go-interpol v1.1.0 h1:KIiKr0VSG2CUW1hl1jpiyuzuJeKUUpC8iM1AIE7N1Vk= +github.com/iris-contrib/httpexpect/v2 v2.15.2 h1:T9THsdP1woyAqKHwjkEsbCnMefsAFvk8iJJKokcJ3Go= +github.com/iris-contrib/schema v0.0.6 h1:CPSBLyx2e91H2yJzPuhGuifVRnZBBJ3pCOMbOvPZaTw= +github.com/iris-contrib/schema v0.0.6/go.mod h1:iYszG0IOsuIsfzjymw1kMzTL8YQcCWlm65f3wX8J5iA= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= +github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/juju/gnuflag v0.0.0-20171113085948-2ce1bb71843d/go.mod h1:2PavIy+JPciBPrBUjwbNvtwB6RQlve+hkpll6QSNmOE= +github.com/kataras/blocks v0.0.7 h1:cF3RDY/vxnSRezc7vLFlQFTYXG/yAr1o7WImJuZbzC4= +github.com/kataras/blocks v0.0.7/go.mod h1:UJIU97CluDo0f+zEjbnbkeMRlvYORtmc1304EeyXf4I= +github.com/kataras/golog v0.1.9 h1:vLvSDpP7kihFGKFAvBSofYo7qZNULYSHOH2D7rPTKJk= +github.com/kataras/golog v0.1.9/go.mod h1:jlpk/bOaYCyqDqH18pgDHdaJab72yBE6i0O3s30hpWY= +github.com/kataras/iris/v12 v12.2.6-0.20230908161203-24ba4e8933b9 h1:Vx8kDVhO2qepK8w44lBtp+RzN3ld743i+LYPzODJSpQ= +github.com/kataras/iris/v12 v12.2.6-0.20230908161203-24ba4e8933b9/go.mod h1:ldkoR3iXABBeqlTibQ3MYaviA1oSlPvim6f55biwBh4= +github.com/kataras/pio v0.0.12 h1:o52SfVYauS3J5X08fNjlGS5arXHjW/ItLkyLcKjoH6w= +github.com/kataras/pio v0.0.12/go.mod h1:ODK/8XBhhQ5WqrAhKy+9lTPS7sBf6O3KcLhc9klfRcY= +github.com/kataras/sitemap v0.0.6 h1:w71CRMMKYMJh6LR2wTgnk5hSgjVNB9KL60n5e2KHvLY= +github.com/kataras/sitemap v0.0.6/go.mod h1:dW4dOCNs896OR1HmG+dMLdT7JjDk7mYBzoIRwuj5jA4= +github.com/kataras/tunnel v0.0.4 h1:sCAqWuJV7nPzGrlb0os3j49lk2JhILT0rID38NHNLpA= +github.com/kataras/tunnel v0.0.4/go.mod h1:9FkU4LaeifdMWqZu7o20ojmW4B7hdhv2CMLwfnHGpYw= github.com/kelseyhightower/envconfig v1.4.0 h1:Im6hONhd3pLkfDFsbRgu68RDNkGF1r3dvMUtDTo2cv8= github.com/kelseyhightower/envconfig v1.4.0/go.mod h1:cccZRl6mQpaq41TPp5QxidR+Sa3axMbJDNb//FQX6Gg= +github.com/klauspost/compress v1.16.7 h1:2mk3MPGNzKyxErAw8YaohYh69+pa4sIQSC0fPGCFR9I= +github.com/klauspost/compress v1.16.7/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= +github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= +github.com/klauspost/cpuid/v2 v2.2.5 h1:0E5MSMDEoAulmXNFquVs//DdoomxaoTY1kUhbc/qbZg= +github.com/klauspost/cpuid/v2 v2.2.5/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= +github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= -github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= -github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/labstack/echo/v4 v4.11.4 h1:vDZmA+qNeh1pd/cCkEicDMrjtrnMGQ1QFI9gWN1zGq8= +github.com/labstack/echo/v4 v4.11.4/go.mod h1:noh7EvLwqDsmh/X/HWKPUl1AjzJrhyptRyEbQJfxen8= +github.com/labstack/gommon v0.4.2 h1:F8qTUNXgG1+6WQmqoUWnz8WiEU60mXVVw0P4ht1WRA0= +github.com/labstack/gommon v0.4.2/go.mod h1:QlUFxVM+SNXhDL/Z7YhocGIBYOiwB0mXm1+1bAPHPyU= +github.com/leodido/go-urn v1.2.4 h1:XlAE/cm/ms7TE/VMVoduSpNBoyc2dOxHs5MZSwAN63Q= +github.com/leodido/go-urn v1.2.4/go.mod h1:7ZrI8mTSeBSHl/UaRyKQW1qZeMgak41ANeCNaVckg+4= +github.com/mailgun/raymond/v2 v2.0.48 h1:5dmlB680ZkFG2RN/0lvTAghrSxIESeu9/2aeDqACtjw= +github.com/mailgun/raymond/v2 v2.0.48/go.mod h1:lsgvL50kgt1ylcFJYZiULi5fjPBkkhNfj4KA0W54Z18= github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/microcosm-cc/bluemonday v1.0.25 h1:4NEwSfiJ+Wva0VxN5B8OwMicaJvD8r9tlJWm9rtloEg= +github.com/microcosm-cc/bluemonday v1.0.25/go.mod h1:ZIOjCQp1OrzBBPIJmfX4qDYFuhU02nx4bn030ixfHLE= +github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 h1:RWengNIwukTxcDr9M+97sNutRR1RKhG96O6jWumTTnw= github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/nrednav/cuid2 v1.1.0 h1:Y2P9Fo1Iz7lKuwcn+fS0mbxkNvEqoNLUtm0+moHCnYc= github.com/nrednav/cuid2 v1.1.0/go.mod h1:jBjkJAI+QLM4EUGvtwGDHC1cP1QQrRNfLo/A7qJFDhA= -github.com/oapi-codegen/runtime v1.1.1 h1:EXLHh0DXIJnWhdRPN2w4MXAzFyE4CskzhNLUmtpMYro= -github.com/oapi-codegen/runtime v1.1.1/go.mod h1:SK9X900oXmPWilYR5/WKPzt3Kqxn/uS/+lbpREv+eCg= github.com/oasdiff/yaml v0.0.0-20250309154309-f31be36b4037 h1:G7ERwszslrBzRxj//JalHPu/3yz+De2J+4aLtSRlHiY= github.com/oasdiff/yaml v0.0.0-20250309154309-f31be36b4037/go.mod h1:2bpvgLBZEtENV5scfDFEtB/5+1M4hkQhDQrccEJ/qGw= github.com/oasdiff/yaml3 v0.0.0-20250309153720-d2182401db90 h1:bQx3WeLcUWy+RletIKwUIt4x3t8n2SxavmoclizMb8c= github.com/oasdiff/yaml3 v0.0.0-20250309153720-d2182401db90/go.mod h1:y5+oSEHCPT/DGrS++Wc/479ERge0zTFxaF8PbGKcg2o= +github.com/pelletier/go-toml/v2 v2.0.9 h1:uH2qQXheeefCCkuBBSLi7jCiSmj3VRh2+Goq2N7Xxu0= +github.com/pelletier/go-toml/v2 v2.0.9/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc= github.com/perimeterx/marshmallow v1.1.5 h1:a2LALqQ1BlHM8PZblsDdidgv1mWi1DgC2UmX50IvK2s= github.com/perimeterx/marshmallow v1.1.5/go.mod h1:dsXbUu8CRzfYP5a87xpp0xq9S3u0Vchtcl8we9tYaXw= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= -github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= +github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/sanity-io/litter v1.5.5 h1:iE+sBxPBzoK6uaEP5Lt3fHNgpKcHXc/A2HGETy0uJQo= +github.com/schollz/closestmatch v2.1.0+incompatible h1:Uel2GXEpJqOWBrlyI+oY9LTiyyjYS17cCYRqP13/SHk= +github.com/schollz/closestmatch v2.1.0+incompatible/go.mod h1:RtP1ddjLong6gTkbtmuhtR2uUrrJOpYzYRvbcPAid+g= +github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ= +github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= +github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/spkg/bom v0.0.0-20160624110644-59b7046e48ad/go.mod h1:qLr4V1qq6nMqFKkMo8ZTx3f+BZEkzsRUY10Xsm2mwU0= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/tdewolff/minify/v2 v2.12.9 h1:dvn5MtmuQ/DFMwqf5j8QhEVpPX6fi3WGImhv8RUB4zA= +github.com/tdewolff/minify/v2 v2.12.9/go.mod h1:qOqdlDfL+7v0/fyymB+OP497nIxJYSvX4MQWA8OoiXU= +github.com/tdewolff/parse/v2 v2.6.8 h1:mhNZXYCx//xG7Yq2e/kVLNZw4YfYmeHbhx+Zc0OvFMA= +github.com/tdewolff/parse/v2 v2.6.8/go.mod h1:XHDhaU6IBgsryfdnpzUXBlT6leW/l25yrFBTEb4eIyM= +github.com/tdewolff/test v1.0.9 h1:SswqJCmeN4B+9gEAi/5uqT0qpi1y2/2O47V/1hhGZT0= +github.com/tdewolff/test v1.0.9/go.mod h1:6DAvZliBAAnD7rhVgwaM7DE5/d9NMOAJ09SqYqeK4QE= +github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI= +github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU= github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= +github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= +github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= +github.com/valyala/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQD0Loo= +github.com/valyala/fasttemplate v1.2.2/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ= +github.com/vmihailenco/msgpack/v5 v5.3.5 h1:5gO0H1iULLWGhs2H5tbAHIZTV8/cYafcFOr9znI5mJU= +github.com/vmihailenco/msgpack/v5 v5.3.5/go.mod h1:7xyJ9e+0+9SaZT0Wt1RGleJXzli6Q/V5KbhBonMG9jc= +github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g= +github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds= +github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f h1:J9EGpcZtP0E/raorCMxlFGSTBrsSlaDGf3jU/qvAE2c= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0= +github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74= +github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0 h1:6fRhSjgLCkTD3JnJxvaJ4Sj+TYblw757bqYgZaOq5ZY= +github.com/yosssi/ace v0.0.5 h1:tUkIP/BLdKqrlrPwcmH0shwEEhTRHoGnc1wFIWmaBUA= +github.com/yosssi/ace v0.0.5/go.mod h1:ALfIzm2vT7t5ZE7uoIZqF3TQ7SAOyupFZnkrF5id+K0= +github.com/yudai/gojsondiff v1.0.0 h1:27cbfqXLVEJ1o8I6v3y9lg8Ydm53EKqHXAOMxEGlCOA= +github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82 h1:BHyfKlQyqbsFN5p3IfnEUduWvb9is428/nNb5L3U01M= +github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= +golang.org/x/arch v0.4.0 h1:A8WCeEWhLwPBKNbFi5Wv5UTCBx5zzubnXDlMOFAzFMc= +golang.org/x/arch v0.4.0/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.40.0 h1:r4x+VvoG5Fm+eJcxMaY8CQM7Lb0l1lsmjGBQ6s8BfKM= golang.org/x/crypto v0.40.0/go.mod h1:Qr1vMER5WyS2dfPHAlsOj01wgLbsyWtFn/aY+5+ZdxY= -golang.org/x/sync v0.15.0 h1:KWH3jNZsfyT6xfAfKiz6MRNmd46ByHDYaZ7KSkCtdW8= -golang.org/x/sync v0.15.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= +golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= +golang.org/x/net v0.0.0-20190327091125-710a502c58a2/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.41.0 h1:vBTly1HeNPEn3wtREYfy4GZ/NECgw2Cnl+nK6Nz3uvw= +golang.org/x/net v0.41.0/go.mod h1:B/K4NNqkfmg07DQYrbwvSluqCJOOXwUjeb/5lOisjbA= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw= +golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.34.0 h1:H5Y5sJ2L2JRdyv7ROF1he/lPdvFsd0mJHFw2ThKHxLA= golang.org/x/sys v0.34.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.27.0 h1:4fGWRpyh641NLlecmyl4LOe6yDdfaYNrGb2zdfo4JV4= +golang.org/x/text v0.27.0/go.mod h1:1D28KMCvyooCX9hBiosv5Tz/+YLxj0j7XhWjpSUF7CU= +golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= +golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.1.9/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20220411194840-2f41105eb62f h1:GGU+dLjvlC3qDwqYgL6UgRmHXhOOgns0bZu2Ty5mm6U= +golang.org/x/xerrors v0.0.0-20220411194840-2f41105eb62f/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= +google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= +gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +moul.io/http2curl/v2 v2.3.0 h1:9r3JfDzWPcbIklMOs2TnIFzDYvfAZvjeavG6EzP7jYs= +nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50= +rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= diff --git a/server/lib/oapi/clipboard_types.go b/server/lib/oapi/clipboard_types.go new file mode 100644 index 00000000..7b9d0fb0 --- /dev/null +++ b/server/lib/oapi/clipboard_types.go @@ -0,0 +1,168 @@ +package oapi + +import ( + "encoding/json" + "fmt" + "net/http" +) + +// ClipboardContentType Type of clipboard content +type ClipboardContentType string + +// Defines values for ClipboardContentType. +const ( + Text ClipboardContentType = "text" + Image ClipboardContentType = "image" +) + +// ClipboardContent defines model for ClipboardContent. +type ClipboardContent struct { + // Type Type of clipboard content + Type ClipboardContentType `json:"type"` + + // Text Text content when type is 'text' + Text *string `json:"text,omitempty"` + + // ImageB64 Base64-encoded image content when type is 'image' + ImageB64 *string `json:"image_b64,omitempty"` + + // ImageMime MIME type of the image when type is 'image' + ImageMime *string `json:"image_mime,omitempty"` +} + +// ClipboardSetResponse defines model for ClipboardSetResponse. +type ClipboardSetResponse struct { + // Ok Whether the clipboard was set successfully + Ok bool `json:"ok"` + + // Message Error message if clipboard couldn't be set + Message *string `json:"message,omitempty"` +} + +// ClipboardEvent defines model for ClipboardEvent. +type ClipboardEvent struct { + // Ts Timestamp of the clipboard change + Ts string `json:"ts"` + + // Type Type of clipboard content + Type ClipboardContentType `json:"type"` + + // Preview Preview of the clipboard content (truncated if text, or 'image...' if an image) + Preview *string `json:"preview,omitempty"` +} + +// GetClipboardRequestObject provides context for handlers +type GetClipboardRequestObject struct{} + +// SetClipboardRequestObject provides context for handlers +type SetClipboardRequestObject struct { + Body ClipboardContent +} + +// StreamClipboardRequestObject provides context for handlers +type StreamClipboardRequestObject struct{} + +// GetClipboard200JSONResponse is returned on successful get operation +type GetClipboard200JSONResponse = ClipboardContent + +// SetClipboard200JSONResponse is returned on successful set operation +type SetClipboard200JSONResponse = ClipboardSetResponse + +// SetClipboard400JSONResponse is returned on bad request +type SetClipboard400JSONResponse struct { + BadRequestErrorJSONResponse +} + +// SetClipboard500JSONResponse is returned on internal error +type SetClipboard500JSONResponse struct { + InternalErrorJSONResponse +} + +// StreamClipboard200ResponseHeaders defines headers for StreamClipboard200 response. +type StreamClipboard200ResponseHeaders struct { + XSSEContentType string `json:"X-SSE-Content-Type"` +} + +// StreamClipboardResponseStream is the streaming response for clipboard events +type StreamClipboardResponseStream struct { + Headers StreamClipboard200ResponseHeaders + Events chan ClipboardEvent + Cleanup func() +} + +// GetClipboardResponseObject defines the different possible responses for GetClipboard. +type GetClipboardResponseObject interface { + visitGetClipboardResponse(w http.ResponseWriter) error +} + +// SetClipboardResponseObject defines the different possible responses for SetClipboard. +type SetClipboardResponseObject interface { + visitSetClipboardResponse(w http.ResponseWriter) error +} + +// StreamClipboardResponseObject defines the different possible responses for StreamClipboard. +type StreamClipboardResponseObject interface { + visitStreamClipboardResponse(w http.ResponseWriter) error +} + +func (response GetClipboard200JSONResponse) visitGetClipboardResponse(w http.ResponseWriter) error { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(200) + + return json.NewEncoder(w).Encode(response) +} + +func (response SetClipboard200JSONResponse) visitSetClipboardResponse(w http.ResponseWriter) error { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(200) + + return json.NewEncoder(w).Encode(response) +} + +func (response SetClipboard400JSONResponse) visitSetClipboardResponse(w http.ResponseWriter) error { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(400) + + return json.NewEncoder(w).Encode(response) +} + +func (response SetClipboard500JSONResponse) visitSetClipboardResponse(w http.ResponseWriter) error { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(500) + + return json.NewEncoder(w).Encode(response) +} + +func (response *StreamClipboardResponseStream) visitStreamClipboardResponse(w http.ResponseWriter) error { + w.Header().Set("Content-Type", "text/event-stream") + w.Header().Set("Cache-Control", "no-cache") + w.Header().Set("Connection", "keep-alive") + w.Header().Set("X-SSE-Content-Type", response.Headers.XSSEContentType) + + flusher, ok := w.(http.Flusher) + if !ok { + return fmt.Errorf("streaming not supported") + } + + enc := json.NewEncoder(w) + + // Send initial flush + flusher.Flush() + + // Use a defer to clean up when the stream ends + defer func() { + if response.Cleanup != nil { + response.Cleanup() + } + }() + + for event := range response.Events { + // Format as SSE + fmt.Fprintf(w, "event: data\ndata: ") + enc.Encode(event) + fmt.Fprintf(w, "\n\n") + flusher.Flush() + } + + return nil +} diff --git a/server/lib/oapi/oapi.go b/server/lib/oapi/oapi.go index 14fa6ddf..afb62996 100644 --- a/server/lib/oapi/oapi.go +++ b/server/lib/oapi/oapi.go @@ -1,6 +1,6 @@ // Package oapi provides primitives to interact with the openapi HTTP API. // -// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.5.0 DO NOT EDIT. +// Code generated by github.com/deepmap/oapi-codegen version v1.12.4 DO NOT EDIT. package oapi import ( @@ -17,10 +17,9 @@ import ( "strings" "time" + "github.com/deepmap/oapi-codegen/pkg/runtime" "github.com/getkin/kin-openapi/openapi3" "github.com/go-chi/chi/v5" - "github.com/oapi-codegen/runtime" - strictnethttp "github.com/oapi-codegen/runtime/strictmiddleware/nethttp" ) // Defines values for ClickMouseRequestButton. @@ -47,6 +46,11 @@ const ( WRITE FileSystemEventType = "WRITE" ) +// Defines values for HealthResponseStatus. +const ( + Ok HealthResponseStatus = "ok" +) + // ClickMouseRequest defines model for ClickMouseRequest. type ClickMouseRequest struct { // Button Mouse button to interact with @@ -139,6 +143,18 @@ type FileSystemEvent struct { // FileSystemEventType Event type. type FileSystemEventType string +// HealthResponse defines model for HealthResponse. +type HealthResponse struct { + // Status Health status + Status HealthResponseStatus `json:"status"` + + // UptimeSec Uptime in seconds + UptimeSec int `json:"uptime_sec"` +} + +// HealthResponseStatus Health status +type HealthResponseStatus string + // ListFiles Array of file or directory information entries. type ListFiles = []FileInfo @@ -174,6 +190,21 @@ type RecorderInfo struct { StartedAt *time.Time `json:"started_at"` } +// ScreenshotRegionRequest defines model for ScreenshotRegionRequest. +type ScreenshotRegionRequest struct { + // Height Height of the region + Height int `json:"height"` + + // Width Width of the region + Width int `json:"width"` + + // X X coordinate of the top-left corner + X int `json:"x"` + + // Y Y coordinate of the top-left corner + Y int `json:"y"` +} + // SetFilePermissionsRequest defines model for SetFilePermissionsRequest. type SetFilePermissionsRequest struct { // Group New group name or GID. @@ -300,6 +331,9 @@ type StartRecordingJSONRequestBody = StartRecordingRequest // StopRecordingJSONRequestBody defines body for StopRecording for application/json ContentType. type StopRecordingJSONRequestBody = StopRecordingRequest +// CaptureScreenshotRegionJSONRequestBody defines body for CaptureScreenshotRegion for application/json ContentType. +type CaptureScreenshotRegionJSONRequestBody = ScreenshotRegionRequest + // RequestEditorFn is the function signature for the RequestEditor callback function type RequestEditorFn func(ctx context.Context, req *http.Request) error @@ -373,27 +407,27 @@ func WithRequestEditorFn(fn RequestEditorFn) ClientOption { // The interface specification for the client above. type ClientInterface interface { - // ClickMouseWithBody request with any body + // ClickMouse request with any body ClickMouseWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) ClickMouse(ctx context.Context, body ClickMouseJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) - // MoveMouseWithBody request with any body + // MoveMouse request with any body MoveMouseWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) MoveMouse(ctx context.Context, body MoveMouseJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) - // CreateDirectoryWithBody request with any body + // CreateDirectory request with any body CreateDirectoryWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) CreateDirectory(ctx context.Context, body CreateDirectoryJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) - // DeleteDirectoryWithBody request with any body + // DeleteDirectory request with any body DeleteDirectoryWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) DeleteDirectory(ctx context.Context, body DeleteDirectoryJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) - // DeleteFileWithBody request with any body + // DeleteFile request with any body DeleteFileWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) DeleteFile(ctx context.Context, body DeleteFileJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) @@ -404,7 +438,7 @@ type ClientInterface interface { // ListFiles request ListFiles(ctx context.Context, params *ListFilesParams, reqEditors ...RequestEditorFn) (*http.Response, error) - // MovePathWithBody request with any body + // MovePath request with any body MovePathWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) MovePath(ctx context.Context, body MovePathJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) @@ -412,12 +446,12 @@ type ClientInterface interface { // ReadFile request ReadFile(ctx context.Context, params *ReadFileParams, reqEditors ...RequestEditorFn) (*http.Response, error) - // SetFilePermissionsWithBody request with any body + // SetFilePermissions request with any body SetFilePermissionsWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) SetFilePermissions(ctx context.Context, body SetFilePermissionsJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) - // StartFsWatchWithBody request with any body + // StartFsWatch request with any body StartFsWatchWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) StartFsWatch(ctx context.Context, body StartFsWatchJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) @@ -428,10 +462,13 @@ type ClientInterface interface { // StreamFsEvents request StreamFsEvents(ctx context.Context, watchId string, reqEditors ...RequestEditorFn) (*http.Response, error) - // WriteFileWithBody request with any body + // WriteFile request with any body WriteFileWithBody(ctx context.Context, params *WriteFileParams, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) - // DeleteRecordingWithBody request with any body + // GetHealth request + GetHealth(ctx context.Context, reqEditors ...RequestEditorFn) (*http.Response, error) + + // DeleteRecording request with any body DeleteRecordingWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) DeleteRecording(ctx context.Context, body DeleteRecordingJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) @@ -442,15 +479,23 @@ type ClientInterface interface { // ListRecorders request ListRecorders(ctx context.Context, reqEditors ...RequestEditorFn) (*http.Response, error) - // StartRecordingWithBody request with any body + // StartRecording request with any body StartRecordingWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) StartRecording(ctx context.Context, body StartRecordingJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) - // StopRecordingWithBody request with any body + // StopRecording request with any body StopRecordingWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) StopRecording(ctx context.Context, body StopRecordingJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) + + // CaptureScreenshot request + CaptureScreenshot(ctx context.Context, reqEditors ...RequestEditorFn) (*http.Response, error) + + // CaptureScreenshotRegion request with any body + CaptureScreenshotRegionWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) + + CaptureScreenshotRegion(ctx context.Context, body CaptureScreenshotRegionJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) } func (c *Client) ClickMouseWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) { @@ -717,6 +762,18 @@ func (c *Client) WriteFileWithBody(ctx context.Context, params *WriteFileParams, return c.Client.Do(req) } +func (c *Client) GetHealth(ctx context.Context, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewGetHealthRequest(c.Server) + if err != nil { + return nil, err + } + req = req.WithContext(ctx) + if err := c.applyEditors(ctx, req, reqEditors); err != nil { + return nil, err + } + return c.Client.Do(req) +} + func (c *Client) DeleteRecordingWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) { req, err := NewDeleteRecordingRequestWithBody(c.Server, contentType, body) if err != nil { @@ -813,6 +870,42 @@ func (c *Client) StopRecording(ctx context.Context, body StopRecordingJSONReques return c.Client.Do(req) } +func (c *Client) CaptureScreenshot(ctx context.Context, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewCaptureScreenshotRequest(c.Server) + if err != nil { + return nil, err + } + req = req.WithContext(ctx) + if err := c.applyEditors(ctx, req, reqEditors); err != nil { + return nil, err + } + return c.Client.Do(req) +} + +func (c *Client) CaptureScreenshotRegionWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewCaptureScreenshotRegionRequestWithBody(c.Server, contentType, body) + if err != nil { + return nil, err + } + req = req.WithContext(ctx) + if err := c.applyEditors(ctx, req, reqEditors); err != nil { + return nil, err + } + return c.Client.Do(req) +} + +func (c *Client) CaptureScreenshotRegion(ctx context.Context, body CaptureScreenshotRegionJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewCaptureScreenshotRegionRequest(c.Server, body) + if err != nil { + return nil, err + } + req = req.WithContext(ctx) + if err := c.applyEditors(ctx, req, reqEditors); err != nil { + return nil, err + } + return c.Client.Do(req) +} + // NewClickMouseRequest calls the generic ClickMouse builder with application/json body func NewClickMouseRequest(server string, body ClickMouseJSONRequestBody) (*http.Request, error) { var bodyReader io.Reader @@ -1032,24 +1125,22 @@ func NewFileInfoRequest(server string, params *FileInfoParams) (*http.Request, e return nil, err } - if params != nil { - queryValues := queryURL.Query() + queryValues := queryURL.Query() - if queryFrag, err := runtime.StyleParamWithLocation("form", true, "path", runtime.ParamLocationQuery, params.Path); err != nil { - return nil, err - } else if parsed, err := url.ParseQuery(queryFrag); err != nil { - return nil, err - } else { - for k, v := range parsed { - for _, v2 := range v { - queryValues.Add(k, v2) - } + if queryFrag, err := runtime.StyleParamWithLocation("form", true, "path", runtime.ParamLocationQuery, params.Path); err != nil { + return nil, err + } else if parsed, err := url.ParseQuery(queryFrag); err != nil { + return nil, err + } else { + for k, v := range parsed { + for _, v2 := range v { + queryValues.Add(k, v2) } } - - queryURL.RawQuery = queryValues.Encode() } + queryURL.RawQuery = queryValues.Encode() + req, err := http.NewRequest("GET", queryURL.String(), nil) if err != nil { return nil, err @@ -1077,24 +1168,22 @@ func NewListFilesRequest(server string, params *ListFilesParams) (*http.Request, return nil, err } - if params != nil { - queryValues := queryURL.Query() + queryValues := queryURL.Query() - if queryFrag, err := runtime.StyleParamWithLocation("form", true, "path", runtime.ParamLocationQuery, params.Path); err != nil { - return nil, err - } else if parsed, err := url.ParseQuery(queryFrag); err != nil { - return nil, err - } else { - for k, v := range parsed { - for _, v2 := range v { - queryValues.Add(k, v2) - } + if queryFrag, err := runtime.StyleParamWithLocation("form", true, "path", runtime.ParamLocationQuery, params.Path); err != nil { + return nil, err + } else if parsed, err := url.ParseQuery(queryFrag); err != nil { + return nil, err + } else { + for k, v := range parsed { + for _, v2 := range v { + queryValues.Add(k, v2) } } - - queryURL.RawQuery = queryValues.Encode() } + queryURL.RawQuery = queryValues.Encode() + req, err := http.NewRequest("GET", queryURL.String(), nil) if err != nil { return nil, err @@ -1162,24 +1251,22 @@ func NewReadFileRequest(server string, params *ReadFileParams) (*http.Request, e return nil, err } - if params != nil { - queryValues := queryURL.Query() + queryValues := queryURL.Query() - if queryFrag, err := runtime.StyleParamWithLocation("form", true, "path", runtime.ParamLocationQuery, params.Path); err != nil { - return nil, err - } else if parsed, err := url.ParseQuery(queryFrag); err != nil { - return nil, err - } else { - for k, v := range parsed { - for _, v2 := range v { - queryValues.Add(k, v2) - } + if queryFrag, err := runtime.StyleParamWithLocation("form", true, "path", runtime.ParamLocationQuery, params.Path); err != nil { + return nil, err + } else if parsed, err := url.ParseQuery(queryFrag); err != nil { + return nil, err + } else { + for k, v := range parsed { + for _, v2 := range v { + queryValues.Add(k, v2) } } - - queryURL.RawQuery = queryValues.Encode() } + queryURL.RawQuery = queryValues.Encode() + req, err := http.NewRequest("GET", queryURL.String(), nil) if err != nil { return nil, err @@ -1355,10 +1442,23 @@ func NewWriteFileRequestWithBody(server string, params *WriteFileParams, content return nil, err } - if params != nil { - queryValues := queryURL.Query() + queryValues := queryURL.Query() - if queryFrag, err := runtime.StyleParamWithLocation("form", true, "path", runtime.ParamLocationQuery, params.Path); err != nil { + if queryFrag, err := runtime.StyleParamWithLocation("form", true, "path", runtime.ParamLocationQuery, params.Path); err != nil { + return nil, err + } else if parsed, err := url.ParseQuery(queryFrag); err != nil { + return nil, err + } else { + for k, v := range parsed { + for _, v2 := range v { + queryValues.Add(k, v2) + } + } + } + + if params.Mode != nil { + + if queryFrag, err := runtime.StyleParamWithLocation("form", true, "mode", runtime.ParamLocationQuery, *params.Mode); err != nil { return nil, err } else if parsed, err := url.ParseQuery(queryFrag); err != nil { return nil, err @@ -1370,25 +1470,10 @@ func NewWriteFileRequestWithBody(server string, params *WriteFileParams, content } } - if params.Mode != nil { - - if queryFrag, err := runtime.StyleParamWithLocation("form", true, "mode", runtime.ParamLocationQuery, *params.Mode); err != nil { - return nil, err - } else if parsed, err := url.ParseQuery(queryFrag); err != nil { - return nil, err - } else { - for k, v := range parsed { - for _, v2 := range v { - queryValues.Add(k, v2) - } - } - } - - } - - queryURL.RawQuery = queryValues.Encode() } + queryURL.RawQuery = queryValues.Encode() + req, err := http.NewRequest("PUT", queryURL.String(), body) if err != nil { return nil, err @@ -1399,6 +1484,33 @@ func NewWriteFileRequestWithBody(server string, params *WriteFileParams, content return req, nil } +// NewGetHealthRequest generates requests for GetHealth +func NewGetHealthRequest(server string) (*http.Request, error) { + var err error + + serverURL, err := url.Parse(server) + if err != nil { + return nil, err + } + + operationPath := fmt.Sprintf("/health") + if operationPath[0] == '/' { + operationPath = "." + operationPath + } + + queryURL, err := serverURL.Parse(operationPath) + if err != nil { + return nil, err + } + + req, err := http.NewRequest("GET", queryURL.String(), nil) + if err != nil { + return nil, err + } + + return req, nil +} + // NewDeleteRecordingRequest calls the generic DeleteRecording builder with application/json body func NewDeleteRecordingRequest(server string, body DeleteRecordingJSONRequestBody) (*http.Request, error) { var bodyReader io.Reader @@ -1458,28 +1570,26 @@ func NewDownloadRecordingRequest(server string, params *DownloadRecordingParams) return nil, err } - if params != nil { - queryValues := queryURL.Query() + queryValues := queryURL.Query() - if params.Id != nil { + if params.Id != nil { - if queryFrag, err := runtime.StyleParamWithLocation("form", true, "id", runtime.ParamLocationQuery, *params.Id); err != nil { - return nil, err - } else if parsed, err := url.ParseQuery(queryFrag); err != nil { - return nil, err - } else { - for k, v := range parsed { - for _, v2 := range v { - queryValues.Add(k, v2) - } + if queryFrag, err := runtime.StyleParamWithLocation("form", true, "id", runtime.ParamLocationQuery, *params.Id); err != nil { + return nil, err + } else if parsed, err := url.ParseQuery(queryFrag); err != nil { + return nil, err + } else { + for k, v := range parsed { + for _, v2 := range v { + queryValues.Add(k, v2) } } - } - queryURL.RawQuery = queryValues.Encode() } + queryURL.RawQuery = queryValues.Encode() + req, err := http.NewRequest("GET", queryURL.String(), nil) if err != nil { return nil, err @@ -1595,6 +1705,73 @@ func NewStopRecordingRequestWithBody(server string, contentType string, body io. return req, nil } +// NewCaptureScreenshotRequest generates requests for CaptureScreenshot +func NewCaptureScreenshotRequest(server string) (*http.Request, error) { + var err error + + serverURL, err := url.Parse(server) + if err != nil { + return nil, err + } + + operationPath := fmt.Sprintf("/screenshot") + if operationPath[0] == '/' { + operationPath = "." + operationPath + } + + queryURL, err := serverURL.Parse(operationPath) + if err != nil { + return nil, err + } + + req, err := http.NewRequest("GET", queryURL.String(), nil) + if err != nil { + return nil, err + } + + return req, nil +} + +// NewCaptureScreenshotRegionRequest calls the generic CaptureScreenshotRegion builder with application/json body +func NewCaptureScreenshotRegionRequest(server string, body CaptureScreenshotRegionJSONRequestBody) (*http.Request, error) { + var bodyReader io.Reader + buf, err := json.Marshal(body) + if err != nil { + return nil, err + } + bodyReader = bytes.NewReader(buf) + return NewCaptureScreenshotRegionRequestWithBody(server, "application/json", bodyReader) +} + +// NewCaptureScreenshotRegionRequestWithBody generates requests for CaptureScreenshotRegion with any type of body +func NewCaptureScreenshotRegionRequestWithBody(server string, contentType string, body io.Reader) (*http.Request, error) { + var err error + + serverURL, err := url.Parse(server) + if err != nil { + return nil, err + } + + operationPath := fmt.Sprintf("/screenshot") + if operationPath[0] == '/' { + operationPath = "." + operationPath + } + + queryURL, err := serverURL.Parse(operationPath) + if err != nil { + return nil, err + } + + req, err := http.NewRequest("POST", queryURL.String(), body) + if err != nil { + return nil, err + } + + req.Header.Add("Content-Type", contentType) + + return req, nil +} + func (c *Client) applyEditors(ctx context.Context, req *http.Request, additionalEditors []RequestEditorFn) error { for _, r := range c.RequestEditors { if err := r(ctx, req); err != nil { @@ -1638,91 +1815,102 @@ func WithBaseURL(baseURL string) ClientOption { // ClientWithResponsesInterface is the interface specification for the client with responses above. type ClientWithResponsesInterface interface { - // ClickMouseWithBodyWithResponse request with any body + // ClickMouse request with any body ClickMouseWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*ClickMouseResponse, error) ClickMouseWithResponse(ctx context.Context, body ClickMouseJSONRequestBody, reqEditors ...RequestEditorFn) (*ClickMouseResponse, error) - // MoveMouseWithBodyWithResponse request with any body + // MoveMouse request with any body MoveMouseWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*MoveMouseResponse, error) MoveMouseWithResponse(ctx context.Context, body MoveMouseJSONRequestBody, reqEditors ...RequestEditorFn) (*MoveMouseResponse, error) - // CreateDirectoryWithBodyWithResponse request with any body + // CreateDirectory request with any body CreateDirectoryWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*CreateDirectoryResponse, error) CreateDirectoryWithResponse(ctx context.Context, body CreateDirectoryJSONRequestBody, reqEditors ...RequestEditorFn) (*CreateDirectoryResponse, error) - // DeleteDirectoryWithBodyWithResponse request with any body + // DeleteDirectory request with any body DeleteDirectoryWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*DeleteDirectoryResponse, error) DeleteDirectoryWithResponse(ctx context.Context, body DeleteDirectoryJSONRequestBody, reqEditors ...RequestEditorFn) (*DeleteDirectoryResponse, error) - // DeleteFileWithBodyWithResponse request with any body + // DeleteFile request with any body DeleteFileWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*DeleteFileResponse, error) DeleteFileWithResponse(ctx context.Context, body DeleteFileJSONRequestBody, reqEditors ...RequestEditorFn) (*DeleteFileResponse, error) - // FileInfoWithResponse request + // FileInfo request FileInfoWithResponse(ctx context.Context, params *FileInfoParams, reqEditors ...RequestEditorFn) (*FileInfoResponse, error) - // ListFilesWithResponse request + // ListFiles request ListFilesWithResponse(ctx context.Context, params *ListFilesParams, reqEditors ...RequestEditorFn) (*ListFilesResponse, error) - // MovePathWithBodyWithResponse request with any body + // MovePath request with any body MovePathWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*MovePathResponse, error) MovePathWithResponse(ctx context.Context, body MovePathJSONRequestBody, reqEditors ...RequestEditorFn) (*MovePathResponse, error) - // ReadFileWithResponse request + // ReadFile request ReadFileWithResponse(ctx context.Context, params *ReadFileParams, reqEditors ...RequestEditorFn) (*ReadFileResponse, error) - // SetFilePermissionsWithBodyWithResponse request with any body + // SetFilePermissions request with any body SetFilePermissionsWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*SetFilePermissionsResponse, error) SetFilePermissionsWithResponse(ctx context.Context, body SetFilePermissionsJSONRequestBody, reqEditors ...RequestEditorFn) (*SetFilePermissionsResponse, error) - // StartFsWatchWithBodyWithResponse request with any body + // StartFsWatch request with any body StartFsWatchWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*StartFsWatchResponse, error) StartFsWatchWithResponse(ctx context.Context, body StartFsWatchJSONRequestBody, reqEditors ...RequestEditorFn) (*StartFsWatchResponse, error) - // StopFsWatchWithResponse request + // StopFsWatch request StopFsWatchWithResponse(ctx context.Context, watchId string, reqEditors ...RequestEditorFn) (*StopFsWatchResponse, error) - // StreamFsEventsWithResponse request + // StreamFsEvents request StreamFsEventsWithResponse(ctx context.Context, watchId string, reqEditors ...RequestEditorFn) (*StreamFsEventsResponse, error) - // WriteFileWithBodyWithResponse request with any body + // WriteFile request with any body WriteFileWithBodyWithResponse(ctx context.Context, params *WriteFileParams, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*WriteFileResponse, error) - // DeleteRecordingWithBodyWithResponse request with any body + // GetHealth request + GetHealthWithResponse(ctx context.Context, reqEditors ...RequestEditorFn) (*GetHealthResponse, error) + + // DeleteRecording request with any body DeleteRecordingWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*DeleteRecordingResponse, error) DeleteRecordingWithResponse(ctx context.Context, body DeleteRecordingJSONRequestBody, reqEditors ...RequestEditorFn) (*DeleteRecordingResponse, error) - // DownloadRecordingWithResponse request + // DownloadRecording request DownloadRecordingWithResponse(ctx context.Context, params *DownloadRecordingParams, reqEditors ...RequestEditorFn) (*DownloadRecordingResponse, error) - // ListRecordersWithResponse request + // ListRecorders request ListRecordersWithResponse(ctx context.Context, reqEditors ...RequestEditorFn) (*ListRecordersResponse, error) - // StartRecordingWithBodyWithResponse request with any body + // StartRecording request with any body StartRecordingWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*StartRecordingResponse, error) StartRecordingWithResponse(ctx context.Context, body StartRecordingJSONRequestBody, reqEditors ...RequestEditorFn) (*StartRecordingResponse, error) - // StopRecordingWithBodyWithResponse request with any body + // StopRecording request with any body StopRecordingWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*StopRecordingResponse, error) StopRecordingWithResponse(ctx context.Context, body StopRecordingJSONRequestBody, reqEditors ...RequestEditorFn) (*StopRecordingResponse, error) + + // CaptureScreenshot request + CaptureScreenshotWithResponse(ctx context.Context, reqEditors ...RequestEditorFn) (*CaptureScreenshotResponse, error) + + // CaptureScreenshotRegion request with any body + CaptureScreenshotRegionWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*CaptureScreenshotRegionResponse, error) + + CaptureScreenshotRegionWithResponse(ctx context.Context, body CaptureScreenshotRegionJSONRequestBody, reqEditors ...RequestEditorFn) (*CaptureScreenshotRegionResponse, error) } type ClickMouseResponse struct { Body []byte HTTPResponse *http.Response - JSON400 *BadRequestError - JSON500 *InternalError + JSON400 *Error + JSON500 *Error } // Status returns HTTPResponse.Status @@ -1744,8 +1932,8 @@ func (r ClickMouseResponse) StatusCode() int { type MoveMouseResponse struct { Body []byte HTTPResponse *http.Response - JSON400 *BadRequestError - JSON500 *InternalError + JSON400 *Error + JSON500 *Error } // Status returns HTTPResponse.Status @@ -1767,8 +1955,8 @@ func (r MoveMouseResponse) StatusCode() int { type CreateDirectoryResponse struct { Body []byte HTTPResponse *http.Response - JSON400 *BadRequestError - JSON500 *InternalError + JSON400 *Error + JSON500 *Error } // Status returns HTTPResponse.Status @@ -1790,9 +1978,9 @@ func (r CreateDirectoryResponse) StatusCode() int { type DeleteDirectoryResponse struct { Body []byte HTTPResponse *http.Response - JSON400 *BadRequestError - JSON404 *NotFoundError - JSON500 *InternalError + JSON400 *Error + JSON404 *Error + JSON500 *Error } // Status returns HTTPResponse.Status @@ -1814,9 +2002,9 @@ func (r DeleteDirectoryResponse) StatusCode() int { type DeleteFileResponse struct { Body []byte HTTPResponse *http.Response - JSON400 *BadRequestError - JSON404 *NotFoundError - JSON500 *InternalError + JSON400 *Error + JSON404 *Error + JSON500 *Error } // Status returns HTTPResponse.Status @@ -1839,9 +2027,9 @@ type FileInfoResponse struct { Body []byte HTTPResponse *http.Response JSON200 *FileInfo - JSON400 *BadRequestError - JSON404 *NotFoundError - JSON500 *InternalError + JSON400 *Error + JSON404 *Error + JSON500 *Error } // Status returns HTTPResponse.Status @@ -1864,9 +2052,9 @@ type ListFilesResponse struct { Body []byte HTTPResponse *http.Response JSON200 *ListFiles - JSON400 *BadRequestError - JSON404 *NotFoundError - JSON500 *InternalError + JSON400 *Error + JSON404 *Error + JSON500 *Error } // Status returns HTTPResponse.Status @@ -1888,9 +2076,9 @@ func (r ListFilesResponse) StatusCode() int { type MovePathResponse struct { Body []byte HTTPResponse *http.Response - JSON400 *BadRequestError - JSON404 *NotFoundError - JSON500 *InternalError + JSON400 *Error + JSON404 *Error + JSON500 *Error } // Status returns HTTPResponse.Status @@ -1912,9 +2100,9 @@ func (r MovePathResponse) StatusCode() int { type ReadFileResponse struct { Body []byte HTTPResponse *http.Response - JSON400 *BadRequestError - JSON404 *NotFoundError - JSON500 *InternalError + JSON400 *Error + JSON404 *Error + JSON500 *Error } // Status returns HTTPResponse.Status @@ -1936,9 +2124,9 @@ func (r ReadFileResponse) StatusCode() int { type SetFilePermissionsResponse struct { Body []byte HTTPResponse *http.Response - JSON400 *BadRequestError - JSON404 *NotFoundError - JSON500 *InternalError + JSON400 *Error + JSON404 *Error + JSON500 *Error } // Status returns HTTPResponse.Status @@ -1964,9 +2152,9 @@ type StartFsWatchResponse struct { // WatchId Unique identifier for the directory watch WatchId *string `json:"watch_id,omitempty"` } - JSON400 *BadRequestError - JSON404 *NotFoundError - JSON500 *InternalError + JSON400 *Error + JSON404 *Error + JSON500 *Error } // Status returns HTTPResponse.Status @@ -1988,9 +2176,9 @@ func (r StartFsWatchResponse) StatusCode() int { type StopFsWatchResponse struct { Body []byte HTTPResponse *http.Response - JSON400 *BadRequestError - JSON404 *NotFoundError - JSON500 *InternalError + JSON400 *Error + JSON404 *Error + JSON500 *Error } // Status returns HTTPResponse.Status @@ -2012,9 +2200,9 @@ func (r StopFsWatchResponse) StatusCode() int { type StreamFsEventsResponse struct { Body []byte HTTPResponse *http.Response - JSON400 *BadRequestError - JSON404 *NotFoundError - JSON500 *InternalError + JSON400 *Error + JSON404 *Error + JSON500 *Error } // Status returns HTTPResponse.Status @@ -2036,9 +2224,9 @@ func (r StreamFsEventsResponse) StatusCode() int { type WriteFileResponse struct { Body []byte HTTPResponse *http.Response - JSON400 *BadRequestError - JSON404 *NotFoundError - JSON500 *InternalError + JSON400 *Error + JSON404 *Error + JSON500 *Error } // Status returns HTTPResponse.Status @@ -2057,12 +2245,35 @@ func (r WriteFileResponse) StatusCode() int { return 0 } +type GetHealthResponse struct { + Body []byte + HTTPResponse *http.Response + JSON200 *HealthResponse + JSON500 *Error +} + +// Status returns HTTPResponse.Status +func (r GetHealthResponse) Status() string { + if r.HTTPResponse != nil { + return r.HTTPResponse.Status + } + return http.StatusText(0) +} + +// StatusCode returns HTTPResponse.StatusCode +func (r GetHealthResponse) StatusCode() int { + if r.HTTPResponse != nil { + return r.HTTPResponse.StatusCode + } + return 0 +} + type DeleteRecordingResponse struct { Body []byte HTTPResponse *http.Response - JSON400 *BadRequestError - JSON404 *NotFoundError - JSON500 *InternalError + JSON400 *Error + JSON404 *Error + JSON500 *Error } // Status returns HTTPResponse.Status @@ -2084,9 +2295,9 @@ func (r DeleteRecordingResponse) StatusCode() int { type DownloadRecordingResponse struct { Body []byte HTTPResponse *http.Response - JSON400 *BadRequestError - JSON404 *NotFoundError - JSON500 *InternalError + JSON400 *Error + JSON404 *Error + JSON500 *Error } // Status returns HTTPResponse.Status @@ -2109,7 +2320,7 @@ type ListRecordersResponse struct { Body []byte HTTPResponse *http.Response JSON200 *[]RecorderInfo - JSON500 *InternalError + JSON500 *Error } // Status returns HTTPResponse.Status @@ -2131,9 +2342,9 @@ func (r ListRecordersResponse) StatusCode() int { type StartRecordingResponse struct { Body []byte HTTPResponse *http.Response - JSON400 *BadRequestError - JSON409 *ConflictError - JSON500 *InternalError + JSON400 *Error + JSON409 *Error + JSON500 *Error } // Status returns HTTPResponse.Status @@ -2155,8 +2366,8 @@ func (r StartRecordingResponse) StatusCode() int { type StopRecordingResponse struct { Body []byte HTTPResponse *http.Response - JSON400 *BadRequestError - JSON500 *InternalError + JSON400 *Error + JSON500 *Error } // Status returns HTTPResponse.Status @@ -2175,6 +2386,51 @@ func (r StopRecordingResponse) StatusCode() int { return 0 } +type CaptureScreenshotResponse struct { + Body []byte + HTTPResponse *http.Response + JSON500 *Error +} + +// Status returns HTTPResponse.Status +func (r CaptureScreenshotResponse) Status() string { + if r.HTTPResponse != nil { + return r.HTTPResponse.Status + } + return http.StatusText(0) +} + +// StatusCode returns HTTPResponse.StatusCode +func (r CaptureScreenshotResponse) StatusCode() int { + if r.HTTPResponse != nil { + return r.HTTPResponse.StatusCode + } + return 0 +} + +type CaptureScreenshotRegionResponse struct { + Body []byte + HTTPResponse *http.Response + JSON400 *Error + JSON500 *Error +} + +// Status returns HTTPResponse.Status +func (r CaptureScreenshotRegionResponse) Status() string { + if r.HTTPResponse != nil { + return r.HTTPResponse.Status + } + return http.StatusText(0) +} + +// StatusCode returns HTTPResponse.StatusCode +func (r CaptureScreenshotRegionResponse) StatusCode() int { + if r.HTTPResponse != nil { + return r.HTTPResponse.StatusCode + } + return 0 +} + // ClickMouseWithBodyWithResponse request with arbitrary body returning *ClickMouseResponse func (c *ClientWithResponses) ClickMouseWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*ClickMouseResponse, error) { rsp, err := c.ClickMouseWithBody(ctx, contentType, body, reqEditors...) @@ -2365,6 +2621,15 @@ func (c *ClientWithResponses) WriteFileWithBodyWithResponse(ctx context.Context, return ParseWriteFileResponse(rsp) } +// GetHealthWithResponse request returning *GetHealthResponse +func (c *ClientWithResponses) GetHealthWithResponse(ctx context.Context, reqEditors ...RequestEditorFn) (*GetHealthResponse, error) { + rsp, err := c.GetHealth(ctx, reqEditors...) + if err != nil { + return nil, err + } + return ParseGetHealthResponse(rsp) +} + // DeleteRecordingWithBodyWithResponse request with arbitrary body returning *DeleteRecordingResponse func (c *ClientWithResponses) DeleteRecordingWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*DeleteRecordingResponse, error) { rsp, err := c.DeleteRecordingWithBody(ctx, contentType, body, reqEditors...) @@ -2434,6 +2699,32 @@ func (c *ClientWithResponses) StopRecordingWithResponse(ctx context.Context, bod return ParseStopRecordingResponse(rsp) } +// CaptureScreenshotWithResponse request returning *CaptureScreenshotResponse +func (c *ClientWithResponses) CaptureScreenshotWithResponse(ctx context.Context, reqEditors ...RequestEditorFn) (*CaptureScreenshotResponse, error) { + rsp, err := c.CaptureScreenshot(ctx, reqEditors...) + if err != nil { + return nil, err + } + return ParseCaptureScreenshotResponse(rsp) +} + +// CaptureScreenshotRegionWithBodyWithResponse request with arbitrary body returning *CaptureScreenshotRegionResponse +func (c *ClientWithResponses) CaptureScreenshotRegionWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*CaptureScreenshotRegionResponse, error) { + rsp, err := c.CaptureScreenshotRegionWithBody(ctx, contentType, body, reqEditors...) + if err != nil { + return nil, err + } + return ParseCaptureScreenshotRegionResponse(rsp) +} + +func (c *ClientWithResponses) CaptureScreenshotRegionWithResponse(ctx context.Context, body CaptureScreenshotRegionJSONRequestBody, reqEditors ...RequestEditorFn) (*CaptureScreenshotRegionResponse, error) { + rsp, err := c.CaptureScreenshotRegion(ctx, body, reqEditors...) + if err != nil { + return nil, err + } + return ParseCaptureScreenshotRegionResponse(rsp) +} + // ParseClickMouseResponse parses an HTTP response from a ClickMouseWithResponse call func ParseClickMouseResponse(rsp *http.Response) (*ClickMouseResponse, error) { bodyBytes, err := io.ReadAll(rsp.Body) @@ -2449,14 +2740,14 @@ func ParseClickMouseResponse(rsp *http.Response) (*ClickMouseResponse, error) { switch { case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 400: - var dest BadRequestError + var dest Error if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } response.JSON400 = &dest case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 500: - var dest InternalError + var dest Error if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } @@ -2482,14 +2773,14 @@ func ParseMoveMouseResponse(rsp *http.Response) (*MoveMouseResponse, error) { switch { case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 400: - var dest BadRequestError + var dest Error if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } response.JSON400 = &dest case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 500: - var dest InternalError + var dest Error if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } @@ -2515,14 +2806,14 @@ func ParseCreateDirectoryResponse(rsp *http.Response) (*CreateDirectoryResponse, switch { case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 400: - var dest BadRequestError + var dest Error if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } response.JSON400 = &dest case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 500: - var dest InternalError + var dest Error if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } @@ -2548,21 +2839,21 @@ func ParseDeleteDirectoryResponse(rsp *http.Response) (*DeleteDirectoryResponse, switch { case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 400: - var dest BadRequestError + var dest Error if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } response.JSON400 = &dest case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 404: - var dest NotFoundError + var dest Error if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } response.JSON404 = &dest case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 500: - var dest InternalError + var dest Error if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } @@ -2588,21 +2879,21 @@ func ParseDeleteFileResponse(rsp *http.Response) (*DeleteFileResponse, error) { switch { case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 400: - var dest BadRequestError + var dest Error if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } response.JSON400 = &dest case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 404: - var dest NotFoundError + var dest Error if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } response.JSON404 = &dest case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 500: - var dest InternalError + var dest Error if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } @@ -2635,21 +2926,21 @@ func ParseFileInfoResponse(rsp *http.Response) (*FileInfoResponse, error) { response.JSON200 = &dest case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 400: - var dest BadRequestError + var dest Error if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } response.JSON400 = &dest case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 404: - var dest NotFoundError + var dest Error if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } response.JSON404 = &dest case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 500: - var dest InternalError + var dest Error if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } @@ -2682,21 +2973,21 @@ func ParseListFilesResponse(rsp *http.Response) (*ListFilesResponse, error) { response.JSON200 = &dest case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 400: - var dest BadRequestError + var dest Error if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } response.JSON400 = &dest case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 404: - var dest NotFoundError + var dest Error if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } response.JSON404 = &dest case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 500: - var dest InternalError + var dest Error if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } @@ -2722,21 +3013,21 @@ func ParseMovePathResponse(rsp *http.Response) (*MovePathResponse, error) { switch { case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 400: - var dest BadRequestError + var dest Error if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } response.JSON400 = &dest case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 404: - var dest NotFoundError + var dest Error if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } response.JSON404 = &dest case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 500: - var dest InternalError + var dest Error if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } @@ -2762,21 +3053,21 @@ func ParseReadFileResponse(rsp *http.Response) (*ReadFileResponse, error) { switch { case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 400: - var dest BadRequestError + var dest Error if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } response.JSON400 = &dest case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 404: - var dest NotFoundError + var dest Error if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } response.JSON404 = &dest case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 500: - var dest InternalError + var dest Error if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } @@ -2802,21 +3093,21 @@ func ParseSetFilePermissionsResponse(rsp *http.Response) (*SetFilePermissionsRes switch { case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 400: - var dest BadRequestError + var dest Error if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } response.JSON400 = &dest case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 404: - var dest NotFoundError + var dest Error if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } response.JSON404 = &dest case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 500: - var dest InternalError + var dest Error if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } @@ -2852,21 +3143,21 @@ func ParseStartFsWatchResponse(rsp *http.Response) (*StartFsWatchResponse, error response.JSON201 = &dest case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 400: - var dest BadRequestError + var dest Error if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } response.JSON400 = &dest case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 404: - var dest NotFoundError + var dest Error if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } response.JSON404 = &dest case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 500: - var dest InternalError + var dest Error if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } @@ -2885,28 +3176,68 @@ func ParseStopFsWatchResponse(rsp *http.Response) (*StopFsWatchResponse, error) return nil, err } - response := &StopFsWatchResponse{ + response := &StopFsWatchResponse{ + Body: bodyBytes, + HTTPResponse: rsp, + } + + switch { + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 400: + var dest Error + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON400 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 404: + var dest Error + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON404 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 500: + var dest Error + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON500 = &dest + + } + + return response, nil +} + +// ParseStreamFsEventsResponse parses an HTTP response from a StreamFsEventsWithResponse call +func ParseStreamFsEventsResponse(rsp *http.Response) (*StreamFsEventsResponse, error) { + bodyBytes, err := io.ReadAll(rsp.Body) + defer func() { _ = rsp.Body.Close() }() + if err != nil { + return nil, err + } + + response := &StreamFsEventsResponse{ Body: bodyBytes, HTTPResponse: rsp, } switch { case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 400: - var dest BadRequestError + var dest Error if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } response.JSON400 = &dest case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 404: - var dest NotFoundError + var dest Error if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } response.JSON404 = &dest case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 500: - var dest InternalError + var dest Error if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } @@ -2917,36 +3248,36 @@ func ParseStopFsWatchResponse(rsp *http.Response) (*StopFsWatchResponse, error) return response, nil } -// ParseStreamFsEventsResponse parses an HTTP response from a StreamFsEventsWithResponse call -func ParseStreamFsEventsResponse(rsp *http.Response) (*StreamFsEventsResponse, error) { +// ParseWriteFileResponse parses an HTTP response from a WriteFileWithResponse call +func ParseWriteFileResponse(rsp *http.Response) (*WriteFileResponse, error) { bodyBytes, err := io.ReadAll(rsp.Body) defer func() { _ = rsp.Body.Close() }() if err != nil { return nil, err } - response := &StreamFsEventsResponse{ + response := &WriteFileResponse{ Body: bodyBytes, HTTPResponse: rsp, } switch { case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 400: - var dest BadRequestError + var dest Error if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } response.JSON400 = &dest case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 404: - var dest NotFoundError + var dest Error if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } response.JSON404 = &dest case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 500: - var dest InternalError + var dest Error if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } @@ -2957,36 +3288,29 @@ func ParseStreamFsEventsResponse(rsp *http.Response) (*StreamFsEventsResponse, e return response, nil } -// ParseWriteFileResponse parses an HTTP response from a WriteFileWithResponse call -func ParseWriteFileResponse(rsp *http.Response) (*WriteFileResponse, error) { +// ParseGetHealthResponse parses an HTTP response from a GetHealthWithResponse call +func ParseGetHealthResponse(rsp *http.Response) (*GetHealthResponse, error) { bodyBytes, err := io.ReadAll(rsp.Body) defer func() { _ = rsp.Body.Close() }() if err != nil { return nil, err } - response := &WriteFileResponse{ + response := &GetHealthResponse{ Body: bodyBytes, HTTPResponse: rsp, } switch { - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 400: - var dest BadRequestError - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON400 = &dest - - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 404: - var dest NotFoundError + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: + var dest HealthResponse if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } - response.JSON404 = &dest + response.JSON200 = &dest case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 500: - var dest InternalError + var dest Error if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } @@ -3012,21 +3336,21 @@ func ParseDeleteRecordingResponse(rsp *http.Response) (*DeleteRecordingResponse, switch { case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 400: - var dest BadRequestError + var dest Error if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } response.JSON400 = &dest case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 404: - var dest NotFoundError + var dest Error if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } response.JSON404 = &dest case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 500: - var dest InternalError + var dest Error if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } @@ -3052,21 +3376,21 @@ func ParseDownloadRecordingResponse(rsp *http.Response) (*DownloadRecordingRespo switch { case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 400: - var dest BadRequestError + var dest Error if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } response.JSON400 = &dest case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 404: - var dest NotFoundError + var dest Error if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } response.JSON404 = &dest case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 500: - var dest InternalError + var dest Error if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } @@ -3099,7 +3423,7 @@ func ParseListRecordersResponse(rsp *http.Response) (*ListRecordersResponse, err response.JSON200 = &dest case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 500: - var dest InternalError + var dest Error if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } @@ -3125,21 +3449,21 @@ func ParseStartRecordingResponse(rsp *http.Response) (*StartRecordingResponse, e switch { case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 400: - var dest BadRequestError + var dest Error if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } response.JSON400 = &dest case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 409: - var dest ConflictError + var dest Error if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } response.JSON409 = &dest case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 500: - var dest InternalError + var dest Error if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } @@ -3165,14 +3489,73 @@ func ParseStopRecordingResponse(rsp *http.Response) (*StopRecordingResponse, err switch { case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 400: - var dest BadRequestError + var dest Error + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON400 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 500: + var dest Error + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON500 = &dest + + } + + return response, nil +} + +// ParseCaptureScreenshotResponse parses an HTTP response from a CaptureScreenshotWithResponse call +func ParseCaptureScreenshotResponse(rsp *http.Response) (*CaptureScreenshotResponse, error) { + bodyBytes, err := io.ReadAll(rsp.Body) + defer func() { _ = rsp.Body.Close() }() + if err != nil { + return nil, err + } + + response := &CaptureScreenshotResponse{ + Body: bodyBytes, + HTTPResponse: rsp, + } + + switch { + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 500: + var dest Error + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON500 = &dest + + } + + return response, nil +} + +// ParseCaptureScreenshotRegionResponse parses an HTTP response from a CaptureScreenshotRegionWithResponse call +func ParseCaptureScreenshotRegionResponse(rsp *http.Response) (*CaptureScreenshotRegionResponse, error) { + bodyBytes, err := io.ReadAll(rsp.Body) + defer func() { _ = rsp.Body.Close() }() + if err != nil { + return nil, err + } + + response := &CaptureScreenshotRegionResponse{ + Body: bodyBytes, + HTTPResponse: rsp, + } + + switch { + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 400: + var dest Error if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } response.JSON400 = &dest case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 500: - var dest InternalError + var dest Error if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } @@ -3227,6 +3610,9 @@ type ServerInterface interface { // Write or create a file // (PUT /fs/write_file) WriteFile(w http.ResponseWriter, r *http.Request, params WriteFileParams) + // Check API health status + // (GET /health) + GetHealth(w http.ResponseWriter, r *http.Request) // Delete a previously recorded video file // (POST /recording/delete) DeleteRecording(w http.ResponseWriter, r *http.Request) @@ -3244,124 +3630,6 @@ type ServerInterface interface { StopRecording(w http.ResponseWriter, r *http.Request) } -// Unimplemented server implementation that returns http.StatusNotImplemented for each endpoint. - -type Unimplemented struct{} - -// Simulate a mouse click action on the host computer -// (POST /computer/click_mouse) -func (_ Unimplemented) ClickMouse(w http.ResponseWriter, r *http.Request) { - w.WriteHeader(http.StatusNotImplemented) -} - -// Move the mouse cursor to the specified coordinates on the host computer -// (POST /computer/move_mouse) -func (_ Unimplemented) MoveMouse(w http.ResponseWriter, r *http.Request) { - w.WriteHeader(http.StatusNotImplemented) -} - -// Create a new directory -// (PUT /fs/create_directory) -func (_ Unimplemented) CreateDirectory(w http.ResponseWriter, r *http.Request) { - w.WriteHeader(http.StatusNotImplemented) -} - -// Delete a directory -// (PUT /fs/delete_directory) -func (_ Unimplemented) DeleteDirectory(w http.ResponseWriter, r *http.Request) { - w.WriteHeader(http.StatusNotImplemented) -} - -// Delete a file -// (PUT /fs/delete_file) -func (_ Unimplemented) DeleteFile(w http.ResponseWriter, r *http.Request) { - w.WriteHeader(http.StatusNotImplemented) -} - -// Get information about a file or directory -// (GET /fs/file_info) -func (_ Unimplemented) FileInfo(w http.ResponseWriter, r *http.Request, params FileInfoParams) { - w.WriteHeader(http.StatusNotImplemented) -} - -// List files in a directory -// (GET /fs/list_files) -func (_ Unimplemented) ListFiles(w http.ResponseWriter, r *http.Request, params ListFilesParams) { - w.WriteHeader(http.StatusNotImplemented) -} - -// Move or rename a file or directory -// (PUT /fs/move) -func (_ Unimplemented) MovePath(w http.ResponseWriter, r *http.Request) { - w.WriteHeader(http.StatusNotImplemented) -} - -// Read file contents -// (GET /fs/read_file) -func (_ Unimplemented) ReadFile(w http.ResponseWriter, r *http.Request, params ReadFileParams) { - w.WriteHeader(http.StatusNotImplemented) -} - -// Set file or directory permissions/ownership -// (PUT /fs/set_file_permissions) -func (_ Unimplemented) SetFilePermissions(w http.ResponseWriter, r *http.Request) { - w.WriteHeader(http.StatusNotImplemented) -} - -// Watch a directory for changes -// (POST /fs/watch) -func (_ Unimplemented) StartFsWatch(w http.ResponseWriter, r *http.Request) { - w.WriteHeader(http.StatusNotImplemented) -} - -// Stop watching a directory -// (DELETE /fs/watch/{watch_id}) -func (_ Unimplemented) StopFsWatch(w http.ResponseWriter, r *http.Request, watchId string) { - w.WriteHeader(http.StatusNotImplemented) -} - -// Stream filesystem events for a watch -// (GET /fs/watch/{watch_id}/events) -func (_ Unimplemented) StreamFsEvents(w http.ResponseWriter, r *http.Request, watchId string) { - w.WriteHeader(http.StatusNotImplemented) -} - -// Write or create a file -// (PUT /fs/write_file) -func (_ Unimplemented) WriteFile(w http.ResponseWriter, r *http.Request, params WriteFileParams) { - w.WriteHeader(http.StatusNotImplemented) -} - -// Delete a previously recorded video file -// (POST /recording/delete) -func (_ Unimplemented) DeleteRecording(w http.ResponseWriter, r *http.Request) { - w.WriteHeader(http.StatusNotImplemented) -} - -// Download the most recently recorded video file -// (GET /recording/download) -func (_ Unimplemented) DownloadRecording(w http.ResponseWriter, r *http.Request, params DownloadRecordingParams) { - w.WriteHeader(http.StatusNotImplemented) -} - -// List all recorders -// (GET /recording/list) -func (_ Unimplemented) ListRecorders(w http.ResponseWriter, r *http.Request) { - w.WriteHeader(http.StatusNotImplemented) -} - -// Start a screen recording. Only one recording per ID can be registered at a time. -// (POST /recording/start) -func (_ Unimplemented) StartRecording(w http.ResponseWriter, r *http.Request) { - w.WriteHeader(http.StatusNotImplemented) -} - -// Stop the recording -// (POST /recording/stop) -func (_ Unimplemented) StopRecording(w http.ResponseWriter, r *http.Request) { - w.WriteHeader(http.StatusNotImplemented) -} - // ServerInterfaceWrapper converts contexts to parameters. type ServerInterfaceWrapper struct { Handler ServerInterface @@ -3373,76 +3641,82 @@ type MiddlewareFunc func(http.Handler) http.Handler // ClickMouse operation middleware func (siw *ServerInterfaceWrapper) ClickMouse(w http.ResponseWriter, r *http.Request) { + ctx := r.Context() - handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { siw.Handler.ClickMouse(w, r) - })) + }) for _, middleware := range siw.HandlerMiddlewares { handler = middleware(handler) } - handler.ServeHTTP(w, r) + handler.ServeHTTP(w, r.WithContext(ctx)) } // MoveMouse operation middleware func (siw *ServerInterfaceWrapper) MoveMouse(w http.ResponseWriter, r *http.Request) { + ctx := r.Context() - handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { siw.Handler.MoveMouse(w, r) - })) + }) for _, middleware := range siw.HandlerMiddlewares { handler = middleware(handler) } - handler.ServeHTTP(w, r) + handler.ServeHTTP(w, r.WithContext(ctx)) } // CreateDirectory operation middleware func (siw *ServerInterfaceWrapper) CreateDirectory(w http.ResponseWriter, r *http.Request) { + ctx := r.Context() - handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { siw.Handler.CreateDirectory(w, r) - })) + }) for _, middleware := range siw.HandlerMiddlewares { handler = middleware(handler) } - handler.ServeHTTP(w, r) + handler.ServeHTTP(w, r.WithContext(ctx)) } // DeleteDirectory operation middleware func (siw *ServerInterfaceWrapper) DeleteDirectory(w http.ResponseWriter, r *http.Request) { + ctx := r.Context() - handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { siw.Handler.DeleteDirectory(w, r) - })) + }) for _, middleware := range siw.HandlerMiddlewares { handler = middleware(handler) } - handler.ServeHTTP(w, r) + handler.ServeHTTP(w, r.WithContext(ctx)) } // DeleteFile operation middleware func (siw *ServerInterfaceWrapper) DeleteFile(w http.ResponseWriter, r *http.Request) { + ctx := r.Context() - handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { siw.Handler.DeleteFile(w, r) - })) + }) for _, middleware := range siw.HandlerMiddlewares { handler = middleware(handler) } - handler.ServeHTTP(w, r) + handler.ServeHTTP(w, r.WithContext(ctx)) } // FileInfo operation middleware func (siw *ServerInterfaceWrapper) FileInfo(w http.ResponseWriter, r *http.Request) { + ctx := r.Context() var err error @@ -3464,19 +3738,20 @@ func (siw *ServerInterfaceWrapper) FileInfo(w http.ResponseWriter, r *http.Reque return } - handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { siw.Handler.FileInfo(w, r, params) - })) + }) for _, middleware := range siw.HandlerMiddlewares { handler = middleware(handler) } - handler.ServeHTTP(w, r) + handler.ServeHTTP(w, r.WithContext(ctx)) } // ListFiles operation middleware func (siw *ServerInterfaceWrapper) ListFiles(w http.ResponseWriter, r *http.Request) { + ctx := r.Context() var err error @@ -3498,33 +3773,35 @@ func (siw *ServerInterfaceWrapper) ListFiles(w http.ResponseWriter, r *http.Requ return } - handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { siw.Handler.ListFiles(w, r, params) - })) + }) for _, middleware := range siw.HandlerMiddlewares { handler = middleware(handler) } - handler.ServeHTTP(w, r) + handler.ServeHTTP(w, r.WithContext(ctx)) } // MovePath operation middleware func (siw *ServerInterfaceWrapper) MovePath(w http.ResponseWriter, r *http.Request) { + ctx := r.Context() - handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { siw.Handler.MovePath(w, r) - })) + }) for _, middleware := range siw.HandlerMiddlewares { handler = middleware(handler) } - handler.ServeHTTP(w, r) + handler.ServeHTTP(w, r.WithContext(ctx)) } // ReadFile operation middleware func (siw *ServerInterfaceWrapper) ReadFile(w http.ResponseWriter, r *http.Request) { + ctx := r.Context() var err error @@ -3546,97 +3823,102 @@ func (siw *ServerInterfaceWrapper) ReadFile(w http.ResponseWriter, r *http.Reque return } - handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { siw.Handler.ReadFile(w, r, params) - })) + }) for _, middleware := range siw.HandlerMiddlewares { handler = middleware(handler) } - handler.ServeHTTP(w, r) + handler.ServeHTTP(w, r.WithContext(ctx)) } // SetFilePermissions operation middleware func (siw *ServerInterfaceWrapper) SetFilePermissions(w http.ResponseWriter, r *http.Request) { + ctx := r.Context() - handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { siw.Handler.SetFilePermissions(w, r) - })) + }) for _, middleware := range siw.HandlerMiddlewares { handler = middleware(handler) } - handler.ServeHTTP(w, r) + handler.ServeHTTP(w, r.WithContext(ctx)) } // StartFsWatch operation middleware func (siw *ServerInterfaceWrapper) StartFsWatch(w http.ResponseWriter, r *http.Request) { + ctx := r.Context() - handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { siw.Handler.StartFsWatch(w, r) - })) + }) for _, middleware := range siw.HandlerMiddlewares { handler = middleware(handler) } - handler.ServeHTTP(w, r) + handler.ServeHTTP(w, r.WithContext(ctx)) } // StopFsWatch operation middleware func (siw *ServerInterfaceWrapper) StopFsWatch(w http.ResponseWriter, r *http.Request) { + ctx := r.Context() var err error // ------------- Path parameter "watch_id" ------------- var watchId string - err = runtime.BindStyledParameterWithOptions("simple", "watch_id", chi.URLParam(r, "watch_id"), &watchId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithLocation("simple", false, "watch_id", runtime.ParamLocationPath, chi.URLParam(r, "watch_id"), &watchId) if err != nil { siw.ErrorHandlerFunc(w, r, &InvalidParamFormatError{ParamName: "watch_id", Err: err}) return } - handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { siw.Handler.StopFsWatch(w, r, watchId) - })) + }) for _, middleware := range siw.HandlerMiddlewares { handler = middleware(handler) } - handler.ServeHTTP(w, r) + handler.ServeHTTP(w, r.WithContext(ctx)) } // StreamFsEvents operation middleware func (siw *ServerInterfaceWrapper) StreamFsEvents(w http.ResponseWriter, r *http.Request) { + ctx := r.Context() var err error // ------------- Path parameter "watch_id" ------------- var watchId string - err = runtime.BindStyledParameterWithOptions("simple", "watch_id", chi.URLParam(r, "watch_id"), &watchId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithLocation("simple", false, "watch_id", runtime.ParamLocationPath, chi.URLParam(r, "watch_id"), &watchId) if err != nil { siw.ErrorHandlerFunc(w, r, &InvalidParamFormatError{ParamName: "watch_id", Err: err}) return } - handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { siw.Handler.StreamFsEvents(w, r, watchId) - })) + }) for _, middleware := range siw.HandlerMiddlewares { handler = middleware(handler) } - handler.ServeHTTP(w, r) + handler.ServeHTTP(w, r.WithContext(ctx)) } // WriteFile operation middleware func (siw *ServerInterfaceWrapper) WriteFile(w http.ResponseWriter, r *http.Request) { + ctx := r.Context() var err error @@ -3666,33 +3948,50 @@ func (siw *ServerInterfaceWrapper) WriteFile(w http.ResponseWriter, r *http.Requ return } - handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { siw.Handler.WriteFile(w, r, params) - })) + }) + + for _, middleware := range siw.HandlerMiddlewares { + handler = middleware(handler) + } + + handler.ServeHTTP(w, r.WithContext(ctx)) +} + +// GetHealth operation middleware +func (siw *ServerInterfaceWrapper) GetHealth(w http.ResponseWriter, r *http.Request) { + ctx := r.Context() + + var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + siw.Handler.GetHealth(w, r) + }) for _, middleware := range siw.HandlerMiddlewares { handler = middleware(handler) } - handler.ServeHTTP(w, r) + handler.ServeHTTP(w, r.WithContext(ctx)) } // DeleteRecording operation middleware func (siw *ServerInterfaceWrapper) DeleteRecording(w http.ResponseWriter, r *http.Request) { + ctx := r.Context() - handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { siw.Handler.DeleteRecording(w, r) - })) + }) for _, middleware := range siw.HandlerMiddlewares { handler = middleware(handler) } - handler.ServeHTTP(w, r) + handler.ServeHTTP(w, r.WithContext(ctx)) } // DownloadRecording operation middleware func (siw *ServerInterfaceWrapper) DownloadRecording(w http.ResponseWriter, r *http.Request) { + ctx := r.Context() var err error @@ -3707,57 +4006,60 @@ func (siw *ServerInterfaceWrapper) DownloadRecording(w http.ResponseWriter, r *h return } - handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { siw.Handler.DownloadRecording(w, r, params) - })) + }) for _, middleware := range siw.HandlerMiddlewares { handler = middleware(handler) } - handler.ServeHTTP(w, r) + handler.ServeHTTP(w, r.WithContext(ctx)) } // ListRecorders operation middleware func (siw *ServerInterfaceWrapper) ListRecorders(w http.ResponseWriter, r *http.Request) { + ctx := r.Context() - handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { siw.Handler.ListRecorders(w, r) - })) + }) for _, middleware := range siw.HandlerMiddlewares { handler = middleware(handler) } - handler.ServeHTTP(w, r) + handler.ServeHTTP(w, r.WithContext(ctx)) } // StartRecording operation middleware func (siw *ServerInterfaceWrapper) StartRecording(w http.ResponseWriter, r *http.Request) { + ctx := r.Context() - handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { siw.Handler.StartRecording(w, r) - })) + }) for _, middleware := range siw.HandlerMiddlewares { handler = middleware(handler) } - handler.ServeHTTP(w, r) + handler.ServeHTTP(w, r.WithContext(ctx)) } // StopRecording operation middleware func (siw *ServerInterfaceWrapper) StopRecording(w http.ResponseWriter, r *http.Request) { + ctx := r.Context() - handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { siw.Handler.StopRecording(w, r) - })) + }) for _, middleware := range siw.HandlerMiddlewares { handler = middleware(handler) } - handler.ServeHTTP(w, r) + handler.ServeHTTP(w, r.WithContext(ctx)) } type UnescapedCookieParamError struct { @@ -3773,16 +4075,16 @@ func (e *UnescapedCookieParamError) Unwrap() error { return e.Err } -type UnmarshalingParamError struct { +type UnmarshallingParamError struct { ParamName string Err error } -func (e *UnmarshalingParamError) Error() string { - return fmt.Sprintf("Error unmarshaling parameter %s as JSON: %s", e.ParamName, e.Err.Error()) +func (e *UnmarshallingParamError) Error() string { + return fmt.Sprintf("Error unmarshalling parameter %s as JSON: %s", e.ParamName, e.Err.Error()) } -func (e *UnmarshalingParamError) Unwrap() error { +func (e *UnmarshallingParamError) Unwrap() error { return e.Err } @@ -3915,6 +4217,9 @@ func HandlerWithOptions(si ServerInterface, options ChiServerOptions) http.Handl r.Group(func(r chi.Router) { r.Put(options.BaseURL+"/fs/write_file", wrapper.WriteFile) }) + r.Group(func(r chi.Router) { + r.Get(options.BaseURL+"/health", wrapper.GetHealth) + }) r.Group(func(r chi.Router) { r.Post(options.BaseURL+"/recording/delete", wrapper.DeleteRecording) }) @@ -4467,40 +4772,18 @@ type StreamFsEvents200TexteventStreamResponse struct { } func (response StreamFsEvents200TexteventStreamResponse) VisitStreamFsEventsResponse(w http.ResponseWriter) error { + w.Header().Set("X-SSE-Content-Type", fmt.Sprint(response.Headers.XSSEContentType)) w.Header().Set("Content-Type", "text/event-stream") if response.ContentLength != 0 { w.Header().Set("Content-Length", fmt.Sprint(response.ContentLength)) } - w.Header().Set("X-SSE-Content-Type", fmt.Sprint(response.Headers.XSSEContentType)) w.WriteHeader(200) if closer, ok := response.Body.(io.ReadCloser); ok { defer closer.Close() } - flusher, ok := w.(http.Flusher) - if !ok { - // If w doesn't support flushing, might as well use io.Copy - _, err := io.Copy(w, response.Body) - return err - } - - // Use a buffer for efficient copying and flushing - buf := make([]byte, 4096) // text/event-stream are usually very small messages - for { - n, err := response.Body.Read(buf) - if n > 0 { - if _, werr := w.Write(buf[:n]); werr != nil { - return werr - } - flusher.Flush() // Flush after each write - } - if err != nil { - if err == io.EOF { - return nil // End of file, no error - } - return err - } - } + _, err := io.Copy(w, response.Body) + return err } type StreamFsEvents400JSONResponse struct{ BadRequestErrorJSONResponse } @@ -4574,6 +4857,31 @@ func (response WriteFile500JSONResponse) VisitWriteFileResponse(w http.ResponseW return json.NewEncoder(w).Encode(response) } +type GetHealthRequestObject struct { +} + +type GetHealthResponseObject interface { + VisitGetHealthResponse(w http.ResponseWriter) error +} + +type GetHealth200JSONResponse HealthResponse + +func (response GetHealth200JSONResponse) VisitGetHealthResponse(w http.ResponseWriter) error { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(200) + + return json.NewEncoder(w).Encode(response) +} + +type GetHealth500JSONResponse struct{ InternalErrorJSONResponse } + +func (response GetHealth500JSONResponse) VisitGetHealthResponse(w http.ResponseWriter) error { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(500) + + return json.NewEncoder(w).Encode(response) +} + type DeleteRecordingRequestObject struct { Body *DeleteRecordingJSONRequestBody } @@ -4637,12 +4945,12 @@ type DownloadRecording200Videomp4Response struct { } func (response DownloadRecording200Videomp4Response) VisitDownloadRecordingResponse(w http.ResponseWriter) error { + w.Header().Set("X-Recording-Finished-At", fmt.Sprint(response.Headers.XRecordingFinishedAt)) + w.Header().Set("X-Recording-Started-At", fmt.Sprint(response.Headers.XRecordingStartedAt)) w.Header().Set("Content-Type", "video/mp4") if response.ContentLength != 0 { w.Header().Set("Content-Length", fmt.Sprint(response.ContentLength)) } - w.Header().Set("X-Recording-Finished-At", fmt.Sprint(response.Headers.XRecordingFinishedAt)) - w.Header().Set("X-Recording-Started-At", fmt.Sprint(response.Headers.XRecordingStartedAt)) w.WriteHeader(200) if closer, ok := response.Body.(io.ReadCloser); ok { @@ -4795,6 +5103,86 @@ func (response StopRecording500JSONResponse) VisitStopRecordingResponse(w http.R return json.NewEncoder(w).Encode(response) } +type CaptureScreenshotRequestObject struct { +} + +type CaptureScreenshotResponseObject interface { + VisitCaptureScreenshotResponse(w http.ResponseWriter) error +} + +type CaptureScreenshot200ImagepngResponse struct { + Body io.Reader + ContentLength int64 +} + +func (response CaptureScreenshot200ImagepngResponse) VisitCaptureScreenshotResponse(w http.ResponseWriter) error { + w.Header().Set("Content-Type", "image/png") + if response.ContentLength != 0 { + w.Header().Set("Content-Length", fmt.Sprint(response.ContentLength)) + } + w.WriteHeader(200) + + if closer, ok := response.Body.(io.ReadCloser); ok { + defer closer.Close() + } + _, err := io.Copy(w, response.Body) + return err +} + +type CaptureScreenshot500JSONResponse struct{ InternalErrorJSONResponse } + +func (response CaptureScreenshot500JSONResponse) VisitCaptureScreenshotResponse(w http.ResponseWriter) error { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(500) + + return json.NewEncoder(w).Encode(response) +} + +type CaptureScreenshotRegionRequestObject struct { + Body *CaptureScreenshotRegionJSONRequestBody +} + +type CaptureScreenshotRegionResponseObject interface { + VisitCaptureScreenshotRegionResponse(w http.ResponseWriter) error +} + +type CaptureScreenshotRegion200ImagepngResponse struct { + Body io.Reader + ContentLength int64 +} + +func (response CaptureScreenshotRegion200ImagepngResponse) VisitCaptureScreenshotRegionResponse(w http.ResponseWriter) error { + w.Header().Set("Content-Type", "image/png") + if response.ContentLength != 0 { + w.Header().Set("Content-Length", fmt.Sprint(response.ContentLength)) + } + w.WriteHeader(200) + + if closer, ok := response.Body.(io.ReadCloser); ok { + defer closer.Close() + } + _, err := io.Copy(w, response.Body) + return err +} + +type CaptureScreenshotRegion400JSONResponse struct{ BadRequestErrorJSONResponse } + +func (response CaptureScreenshotRegion400JSONResponse) VisitCaptureScreenshotRegionResponse(w http.ResponseWriter) error { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(400) + + return json.NewEncoder(w).Encode(response) +} + +type CaptureScreenshotRegion500JSONResponse struct{ InternalErrorJSONResponse } + +func (response CaptureScreenshotRegion500JSONResponse) VisitCaptureScreenshotRegionResponse(w http.ResponseWriter) error { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(500) + + return json.NewEncoder(w).Encode(response) +} + // StrictServerInterface represents all server handlers. type StrictServerInterface interface { // Simulate a mouse click action on the host computer @@ -4839,6 +5227,9 @@ type StrictServerInterface interface { // Write or create a file // (PUT /fs/write_file) WriteFile(ctx context.Context, request WriteFileRequestObject) (WriteFileResponseObject, error) + // Check API health status + // (GET /health) + GetHealth(ctx context.Context, request GetHealthRequestObject) (GetHealthResponseObject, error) // Delete a previously recorded video file // (POST /recording/delete) DeleteRecording(ctx context.Context, request DeleteRecordingRequestObject) (DeleteRecordingResponseObject, error) @@ -4856,8 +5247,9 @@ type StrictServerInterface interface { StopRecording(ctx context.Context, request StopRecordingRequestObject) (StopRecordingResponseObject, error) } -type StrictHandlerFunc = strictnethttp.StrictHTTPHandlerFunc -type StrictMiddlewareFunc = strictnethttp.StrictHTTPMiddlewareFunc +type StrictHandlerFunc func(ctx context.Context, w http.ResponseWriter, r *http.Request, args interface{}) (interface{}, error) + +type StrictMiddlewareFunc func(f StrictHandlerFunc, operationID string) StrictHandlerFunc type StrictHTTPServerOptions struct { RequestErrorHandlerFunc func(w http.ResponseWriter, r *http.Request, err error) @@ -4912,7 +5304,7 @@ func (sh *strictHandler) ClickMouse(w http.ResponseWriter, r *http.Request) { sh.options.ResponseErrorHandlerFunc(w, r, err) } } else if response != nil { - sh.options.ResponseErrorHandlerFunc(w, r, fmt.Errorf("unexpected response type: %T", response)) + sh.options.ResponseErrorHandlerFunc(w, r, fmt.Errorf("Unexpected response type: %T", response)) } } @@ -4943,7 +5335,7 @@ func (sh *strictHandler) MoveMouse(w http.ResponseWriter, r *http.Request) { sh.options.ResponseErrorHandlerFunc(w, r, err) } } else if response != nil { - sh.options.ResponseErrorHandlerFunc(w, r, fmt.Errorf("unexpected response type: %T", response)) + sh.options.ResponseErrorHandlerFunc(w, r, fmt.Errorf("Unexpected response type: %T", response)) } } @@ -4974,7 +5366,7 @@ func (sh *strictHandler) CreateDirectory(w http.ResponseWriter, r *http.Request) sh.options.ResponseErrorHandlerFunc(w, r, err) } } else if response != nil { - sh.options.ResponseErrorHandlerFunc(w, r, fmt.Errorf("unexpected response type: %T", response)) + sh.options.ResponseErrorHandlerFunc(w, r, fmt.Errorf("Unexpected response type: %T", response)) } } @@ -5005,7 +5397,7 @@ func (sh *strictHandler) DeleteDirectory(w http.ResponseWriter, r *http.Request) sh.options.ResponseErrorHandlerFunc(w, r, err) } } else if response != nil { - sh.options.ResponseErrorHandlerFunc(w, r, fmt.Errorf("unexpected response type: %T", response)) + sh.options.ResponseErrorHandlerFunc(w, r, fmt.Errorf("Unexpected response type: %T", response)) } } @@ -5036,7 +5428,7 @@ func (sh *strictHandler) DeleteFile(w http.ResponseWriter, r *http.Request) { sh.options.ResponseErrorHandlerFunc(w, r, err) } } else if response != nil { - sh.options.ResponseErrorHandlerFunc(w, r, fmt.Errorf("unexpected response type: %T", response)) + sh.options.ResponseErrorHandlerFunc(w, r, fmt.Errorf("Unexpected response type: %T", response)) } } @@ -5062,7 +5454,7 @@ func (sh *strictHandler) FileInfo(w http.ResponseWriter, r *http.Request, params sh.options.ResponseErrorHandlerFunc(w, r, err) } } else if response != nil { - sh.options.ResponseErrorHandlerFunc(w, r, fmt.Errorf("unexpected response type: %T", response)) + sh.options.ResponseErrorHandlerFunc(w, r, fmt.Errorf("Unexpected response type: %T", response)) } } @@ -5088,7 +5480,7 @@ func (sh *strictHandler) ListFiles(w http.ResponseWriter, r *http.Request, param sh.options.ResponseErrorHandlerFunc(w, r, err) } } else if response != nil { - sh.options.ResponseErrorHandlerFunc(w, r, fmt.Errorf("unexpected response type: %T", response)) + sh.options.ResponseErrorHandlerFunc(w, r, fmt.Errorf("Unexpected response type: %T", response)) } } @@ -5119,7 +5511,7 @@ func (sh *strictHandler) MovePath(w http.ResponseWriter, r *http.Request) { sh.options.ResponseErrorHandlerFunc(w, r, err) } } else if response != nil { - sh.options.ResponseErrorHandlerFunc(w, r, fmt.Errorf("unexpected response type: %T", response)) + sh.options.ResponseErrorHandlerFunc(w, r, fmt.Errorf("Unexpected response type: %T", response)) } } @@ -5145,7 +5537,7 @@ func (sh *strictHandler) ReadFile(w http.ResponseWriter, r *http.Request, params sh.options.ResponseErrorHandlerFunc(w, r, err) } } else if response != nil { - sh.options.ResponseErrorHandlerFunc(w, r, fmt.Errorf("unexpected response type: %T", response)) + sh.options.ResponseErrorHandlerFunc(w, r, fmt.Errorf("Unexpected response type: %T", response)) } } @@ -5176,7 +5568,7 @@ func (sh *strictHandler) SetFilePermissions(w http.ResponseWriter, r *http.Reque sh.options.ResponseErrorHandlerFunc(w, r, err) } } else if response != nil { - sh.options.ResponseErrorHandlerFunc(w, r, fmt.Errorf("unexpected response type: %T", response)) + sh.options.ResponseErrorHandlerFunc(w, r, fmt.Errorf("Unexpected response type: %T", response)) } } @@ -5207,7 +5599,7 @@ func (sh *strictHandler) StartFsWatch(w http.ResponseWriter, r *http.Request) { sh.options.ResponseErrorHandlerFunc(w, r, err) } } else if response != nil { - sh.options.ResponseErrorHandlerFunc(w, r, fmt.Errorf("unexpected response type: %T", response)) + sh.options.ResponseErrorHandlerFunc(w, r, fmt.Errorf("Unexpected response type: %T", response)) } } @@ -5233,7 +5625,7 @@ func (sh *strictHandler) StopFsWatch(w http.ResponseWriter, r *http.Request, wat sh.options.ResponseErrorHandlerFunc(w, r, err) } } else if response != nil { - sh.options.ResponseErrorHandlerFunc(w, r, fmt.Errorf("unexpected response type: %T", response)) + sh.options.ResponseErrorHandlerFunc(w, r, fmt.Errorf("Unexpected response type: %T", response)) } } @@ -5259,7 +5651,7 @@ func (sh *strictHandler) StreamFsEvents(w http.ResponseWriter, r *http.Request, sh.options.ResponseErrorHandlerFunc(w, r, err) } } else if response != nil { - sh.options.ResponseErrorHandlerFunc(w, r, fmt.Errorf("unexpected response type: %T", response)) + sh.options.ResponseErrorHandlerFunc(w, r, fmt.Errorf("Unexpected response type: %T", response)) } } @@ -5287,7 +5679,31 @@ func (sh *strictHandler) WriteFile(w http.ResponseWriter, r *http.Request, param sh.options.ResponseErrorHandlerFunc(w, r, err) } } else if response != nil { - sh.options.ResponseErrorHandlerFunc(w, r, fmt.Errorf("unexpected response type: %T", response)) + sh.options.ResponseErrorHandlerFunc(w, r, fmt.Errorf("Unexpected response type: %T", response)) + } +} + +// GetHealth operation middleware +func (sh *strictHandler) GetHealth(w http.ResponseWriter, r *http.Request) { + var request GetHealthRequestObject + + handler := func(ctx context.Context, w http.ResponseWriter, r *http.Request, request interface{}) (interface{}, error) { + return sh.ssi.GetHealth(ctx, request.(GetHealthRequestObject)) + } + for _, middleware := range sh.middlewares { + handler = middleware(handler, "GetHealth") + } + + response, err := handler(r.Context(), w, r, request) + + if err != nil { + sh.options.ResponseErrorHandlerFunc(w, r, err) + } else if validResponse, ok := response.(GetHealthResponseObject); ok { + if err := validResponse.VisitGetHealthResponse(w); err != nil { + sh.options.ResponseErrorHandlerFunc(w, r, err) + } + } else if response != nil { + sh.options.ResponseErrorHandlerFunc(w, r, fmt.Errorf("Unexpected response type: %T", response)) } } @@ -5318,7 +5734,7 @@ func (sh *strictHandler) DeleteRecording(w http.ResponseWriter, r *http.Request) sh.options.ResponseErrorHandlerFunc(w, r, err) } } else if response != nil { - sh.options.ResponseErrorHandlerFunc(w, r, fmt.Errorf("unexpected response type: %T", response)) + sh.options.ResponseErrorHandlerFunc(w, r, fmt.Errorf("Unexpected response type: %T", response)) } } @@ -5344,7 +5760,7 @@ func (sh *strictHandler) DownloadRecording(w http.ResponseWriter, r *http.Reques sh.options.ResponseErrorHandlerFunc(w, r, err) } } else if response != nil { - sh.options.ResponseErrorHandlerFunc(w, r, fmt.Errorf("unexpected response type: %T", response)) + sh.options.ResponseErrorHandlerFunc(w, r, fmt.Errorf("Unexpected response type: %T", response)) } } @@ -5368,7 +5784,7 @@ func (sh *strictHandler) ListRecorders(w http.ResponseWriter, r *http.Request) { sh.options.ResponseErrorHandlerFunc(w, r, err) } } else if response != nil { - sh.options.ResponseErrorHandlerFunc(w, r, fmt.Errorf("unexpected response type: %T", response)) + sh.options.ResponseErrorHandlerFunc(w, r, fmt.Errorf("Unexpected response type: %T", response)) } } @@ -5399,7 +5815,7 @@ func (sh *strictHandler) StartRecording(w http.ResponseWriter, r *http.Request) sh.options.ResponseErrorHandlerFunc(w, r, err) } } else if response != nil { - sh.options.ResponseErrorHandlerFunc(w, r, fmt.Errorf("unexpected response type: %T", response)) + sh.options.ResponseErrorHandlerFunc(w, r, fmt.Errorf("Unexpected response type: %T", response)) } } @@ -5430,61 +5846,65 @@ func (sh *strictHandler) StopRecording(w http.ResponseWriter, r *http.Request) { sh.options.ResponseErrorHandlerFunc(w, r, err) } } else if response != nil { - sh.options.ResponseErrorHandlerFunc(w, r, fmt.Errorf("unexpected response type: %T", response)) + sh.options.ResponseErrorHandlerFunc(w, r, fmt.Errorf("Unexpected response type: %T", response)) } } // Base64 encoded, gzipped, json marshaled Swagger object var swaggerSpec = []string{ - "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", - "//+ThhMPQj4AAA==", + "H4sIAAAAAAAC/9xba3PUONb+Kyq982F4130BwkxNvoUksKmdMFSaKWYX2C61fdzWYEtGktM0VP771pF8", + "basv6aRhMlVUkfbl6Ojc9JyLv9JQZrkUIIymx1+pAp1LocH+eM6iK/hUgDbnSkmFl0IpDAiDf7I8T3nI", + "DJdi9KeWAq/pMIGM4V8/KIjpMf2/UUN/5O7qkaN2c3MT0Ah0qHiOROgxLkjKFelNQE+liFMefqvVq+Vw", + "6QthQAmWfqOlq+XIBNQ1KFI+GNBX0ryQhYi+ER+vpCF2PYr3yseR2mnKw4+XstBQ6QcZiCKOL7L0tZI5", + "KMPRbmKWagho3rr0lc4KYxyH3QUtSeLuEiMJR0Gw0JAFNwkNKIgio8fvaAqxoQFVfJ7g/xmPohRoQGcs", + "/EgDGku1YCqiHwJqljnQY6qN4mKOIgyR9am7vLr8m2UORMbEPkNYaC83q0ZygT+LnJZkvAskMo2mH2Gp", + "fduLeMxBEbyN+8NnSVTgq8Qk4BamAeUGMvt+j3p5gSnFlvhbFNnUvlUuF7MiNfT4cU+VRTYDhZszPAO7", + "uIIcmOmsW1JHsc/BWtzn/i7+IKGUKuKCGSutmgDJpealzPqUln1K/96H0k1AFXwquIIIlfKZIulGEXL2", + "JzinPVXADJxxBaGRarmfpWYy8hjKb7l7nUQVdYIPkh9laFhKnLoCAsP5kPz87NmjITlzmrGC//nZsyEN", + "aM4Mujk9pv99Nx78/OHr0+Do5gfqMamcmaTPxMlMy7Qw0GICH8QVQrv1lUVGw//vE1+Rpl3JJ8wzSMHA", + "a2aS/eS4ZQsV45Fd5v4Zv4LQGtp8P+551Of9IgJhnDuXpquqRVo7ISdpnjBRZKB4SKQiyTJPQKzqnw2+", + "nAz+Mx78Mvjwjx+8m+1trD4DVgwWtGZz8ASPFYlVD/qE9oKncCFi2SfP9TTiqi+NtwmYBJSVg1Um14Q1", + "ljls9jSTMgUmcJlMRlMMR31yvzJt0KV4XB5pNmwNXWzPmKHHNGIGBvZtj8f43Ra35Rx1xo0mP6J/BuQ9", + "jdTisxrgv/cUdfSeDtRioAb47z19NPStIJiP7+dMA8FblU3EuKRUXkns7OB42/ue5l9gOlsa8Bw2E/4F", + "CBfE3h6SMYlbbHDQw+2x1e6x5K6zWFDZQUuHpdDXmdNkqQ1k59clWukrRtsHSJgwMQcC+KD1klubH4tj", + "CA1Eu9vhvrqsl9pXqbezEj9osSIleG/YwiqnV+cnb85pQN9eXdj/z85/Pbd/XJ2/Ork890CXFeXbu8H6", + "wPpPYCmeBi5D6EcKbZgpPHbp3iPl7YZj6YdTRY7WNdUQ9kn9bu+hkWsIpYi0xYKCZ0hxvNW8axZaa/h2", + "+ivXxlqoR5uIw1CLfdvgwoUqDF4gTOVyNbTbhMjr+OtBfJfyGu4Ave8CTzN5DbdCp9vQo5GWpgN+hdJS", + "ESP3Qo+7UtoZPaKY94c7EWgz3QbbQBtkHg2kivDbUE9AtQq3EdayUCHsTHPVK6oFgtYufBJymAqUHyjE", + "XHCdQDRlnnj/BnMQw7KcLBIQLeBUvbXuoBdFmrJZCvTYqAI84nFIrX9Z1wiwdb91BGjDlLktt+VLezK7", + "Ince0S6fPplPQgUgdCLNFcy5FHvGALCJsyc04/UGzs5dBlaH1Mc+z1zwyGeNb/HyLUntmGwamQ9SiA0J", + "pRKgtgT9nTPP25H1BpJKGkElYq8OwZ4mr0FlXGsuhd5Pi3Mli7y/tVewIPZWiV0UeXlxNtwfJHtS2p+O", + "jh7dLoOVC5Sol1d7ixQaVMXv72v43QVQLRKpgeSNbAlT9nSYQQkto32zyw0Ad4KB4IV+y0x4r/lxXbzA", + "HSyQulcwCvDI49fQqQGV66wByiU9Ur+besHxrmm2lcAds+xYsQwUMx6jvGpOiOohhH1xjgZ6DUrxCDTR", + "rlxaSuARaox9dh78ZLwt+Phy/LrOw5tkH9OobravwZraPeX6lumzQllgcCEmJbLtozW3tRYfUflSCxBv", + "kc5GgWTss03c+Be4EJfP13Ngsa8u083L5ztq5PF4PO4oxR9kPZYm87samlQhIJ3t/nKRZRBxZiBdEm1k", + "bivRsjBkrlgIcZESnRQmkgsxJG8SrknGlkSBLlKD0mB4mKgix3T0mkcgrbD8WehtikzOg5Ghg1WY8BIv", + "oZ3hBmEM/RcoASm5yNgcNDl5fUEDeg1KO2bHw8fDsY32OQiWc3pMnw7Hw6dlFmlFb7OdwoAauUJ8hpmM", + "DYDSqRH15Ew/osetRgN1gQi0eS6j5b31PvqdjJtuzEPoZi+0OmFPxuN1vQvXNMADCCEhRCiOI/e4j42a", + "7Gi1u3YT0Ge7vNdtTdk+TZFlTC1tCSgrUgyVjFg5dxobRAprUInUCHmcViyBRkeYUm1TUZ2PHkhDvXz3", + "bgoqk0Pc2fdVzmWVrmZtvoy013QOIbp91MKpeoPGYj1yNf9pXYCwGit8PtXtixzKsfzdl52U93gTEnL7", + "jIguwhC0jos0XX5XRbqdEkYELJr6T60X1wjYQS+uU3FovfQbOfv6U6MSt8U7udPR+Gj7e932933ozkmj", + "XSFe1Rue11tUhijpL68tm9b9DRRl9VHpCH9MK5AyB4+G6koqYhBMHQwoTY/f7V+W5/j4pwKsh7rOQZUf", + "dtUStHS8Nd/84NfhvRhRU03uj3hYs2iVqh+gabwE0ym2sxnic9bXXm02KdfGOrZeazdNzX9Xw+l24R+m", + "pTS79phKE+9RfmWu+sBsBTdoDUO77KxvG7bHsS7eV02BA0Ld+4j1Flo2+OgB6snuQCqiwBYFNzmzAhbV", + "p7TXl6+AReUZvZsr28WqkRSk/1fxZhkaMANtFLCsa1Z1A2LGBbMsrq7kD/24u3uD0t/JWFC/Tmel2HRt", + "HBpcoJ+2KsJrvbtfmD+Qn6/vAOzr8S1SpMgj9jBB3gSMp5HeUt3INgt0wvNaw7aKvb460a7MH0qbnuL/", + "7mnuzix0S5h221NfyfB3wT8V4KtYNyJdlOLYqQi40kCwXYOy8/nQI4fbTAsGWFm5PpHumtjoayXyGydz", + "zEd89ibzxtxWjht7hJRnRnmC1HrcdIpsPzSOPA3YUlEyzx++oia29I474mLuxW2rShrZCbL1AH9iD9EX", + "+tw99g11tXrAG/hsHLfek31bZtcerPP462RyThzZakypHLSDauMJsMju+iv9YzCZnA9OHW+DN955s0uI", + "OLPzZkgQyUfMsJIc+XE1iD2ibelUw169UOcZR7t5iGZqBd2Tsg0rrAy7tcUqvq2+9BYf2QW6nrVmiVgP", + "xh4OvgZrO6ZxPUawdoKgMxT/09HROjZt230NWxvnDpzz7XLi3xFY71HQtugbTcCAePDHKJopgrawKoU3", + "VbrEjnuuDcMvwbiBUHrAssbKqKonSp68viBcE8fs8n7aAgmEHwkSTjoTr1YqddN+1AAJP4Bd+X7hoHXm", + "Xlv9prTubelHM57xN6gw5wquuSx0uqya7e3efU9/ciFSyaK1Fn5WPtBW4cZYXofQutXfYPkheZuAIDLD", + "uBEFrlfoZiwKDdrBfBdV69fXhVULZPxBdduwwHZQYwU2yvKjO5cpWqM/7iDs4JX67uBFOTo6ONk4wilj", + "N8XZHeGp5k6H5GXBFBMGICqnxq5enD59+vSXId2E8oIOKxOXHe3FSZlZ7csIsvJk/GSTi3JNtOFpSrgg", + "uZJzBVoHJE+BaSBGLQmbMy5IyowdgmyJ+wqMWg5OYuOb5ZsU8zloTAoXjBuyMplPZhBLhRs1aumcoNnE", + "pjmkhwgDK5cv2/va+iIIs1tESbk7B9b2JarBa33XM3OnbxE6Y969Gf++v9oSu4zr8KPvr3DP0rRNtis2", + "6zhbCkGHPkb9U5DeU/TxJhetBsvvZPq/bH+v+0n9/WRATBnCiLaD6k1cG5LfRLokUrRjXQ6KXJyRkAmM", + "bwrmXBtQEBGGJNwXfz0tu6m9dUpuzQYeTMee+cPbA6WyMPN958OMzLvHjxO3rr8yWBuHTlluCgXN9wjb", + "YxHP2BxGufsC406QoFmVhI6PfoHr7vjdUa5t2S5XDgYgHFNQ3rCj6f7pxVUhXVXfQRzEMNd8G7J7T+G7", + "Kev7zW6tUTKrJvDC6tsV9PD/BQAA//+501KJH0UAAA==", } // GetSwagger returns the content of the embedded swagger specification file @@ -5492,16 +5912,16 @@ var swaggerSpec = []string{ func decodeSpec() ([]byte, error) { zipped, err := base64.StdEncoding.DecodeString(strings.Join(swaggerSpec, "")) if err != nil { - return nil, fmt.Errorf("error base64 decoding spec: %w", err) + return nil, fmt.Errorf("error base64 decoding spec: %s", err) } zr, err := gzip.NewReader(bytes.NewReader(zipped)) if err != nil { - return nil, fmt.Errorf("error decompressing spec: %w", err) + return nil, fmt.Errorf("error decompressing spec: %s", err) } var buf bytes.Buffer _, err = buf.ReadFrom(zr) if err != nil { - return nil, fmt.Errorf("error decompressing spec: %w", err) + return nil, fmt.Errorf("error decompressing spec: %s", err) } return buf.Bytes(), nil @@ -5519,7 +5939,7 @@ func decodeSpecCached() func() ([]byte, error) { // Constructs a synthetic filesystem for resolving external references when loading openapi specifications. func PathToRawSpec(pathToFile string) map[string]func() ([]byte, error) { - res := make(map[string]func() ([]byte, error)) + var res = make(map[string]func() ([]byte, error)) if len(pathToFile) > 0 { res[pathToFile] = rawSpec } @@ -5533,12 +5953,12 @@ func PathToRawSpec(pathToFile string) map[string]func() ([]byte, error) { // Externally referenced files must be embedded in the corresponding golang packages. // Urls can be supported but this task was out of the scope. func GetSwagger() (swagger *openapi3.T, err error) { - resolvePath := PathToRawSpec("") + var resolvePath = PathToRawSpec("") loader := openapi3.NewLoader() loader.IsExternalRefsAllowed = true loader.ReadFromURIFunc = func(loader *openapi3.Loader, url *url.URL) ([]byte, error) { - pathToFile := url.String() + var pathToFile = url.String() pathToFile = path.Clean(pathToFile) getSpec, ok := resolvePath[pathToFile] if !ok { diff --git a/server/openapi.yaml b/server/openapi.yaml index d56dbaa5..4cc67bb2 100644 --- a/server/openapi.yaml +++ b/server/openapi.yaml @@ -3,6 +3,74 @@ info: title: Kernel Images API version: 0.1.0 paths: + /health: + get: + summary: Check API health status + operationId: getHealth + responses: + "200": + description: API is healthy + content: + application/json: + schema: + $ref: "#/components/schemas/HealthResponse" + "500": + $ref: "#/components/responses/InternalError" + + /clipboard: + get: + summary: Get clipboard content + operationId: getClipboard + responses: + "200": + description: Current clipboard content + content: + application/json: + schema: + $ref: "#/components/schemas/ClipboardContent" + "500": + $ref: "#/components/responses/InternalError" + post: + summary: Set clipboard content + operationId: setClipboard + requestBody: + required: true + content: + application/json: + schema: + $ref: "#/components/schemas/ClipboardContent" + responses: + "200": + description: Clipboard content set successfully + content: + application/json: + schema: + $ref: "#/components/schemas/ClipboardSetResponse" + "400": + $ref: "#/components/responses/BadRequestError" + "500": + $ref: "#/components/responses/InternalError" + + /clipboard/stream: + get: + summary: Stream clipboard events + operationId: streamClipboard + responses: + "200": + description: SSE stream of clipboard change events + headers: + X-SSE-Content-Type: + description: Media type of SSE data events (application/json) + schema: + type: string + const: application/json + content: + text/event-stream: + schema: + $ref: "#/components/schemas/ClipboardEvent" + "500": + $ref: "#/components/responses/InternalError" + /recording/start: post: summary: Start a screen recording. Only one recording per ID can be registered at a time. @@ -447,6 +515,67 @@ paths: $ref: "#/components/responses/InternalError" components: schemas: + HealthResponse: + type: object + required: [status, uptime_sec] + properties: + status: + type: string + description: Health status + enum: [ok] + uptime_sec: + type: integer + description: Uptime in seconds + minimum: 0 + + ClipboardContent: + type: object + required: [type] + properties: + type: + type: string + description: Type of clipboard content + enum: [text, image] + text: + type: string + description: Text content when type is 'text' + image_b64: + type: string + description: Base64-encoded image content when type is 'image' + image_mime: + type: string + description: MIME type of the image when type is 'image' + default: image/png + additionalProperties: false + + ClipboardSetResponse: + type: object + required: [ok] + properties: + ok: + type: boolean + description: Whether the clipboard was set successfully + message: + type: string + description: Error message if clipboard couldn't be set + additionalProperties: false + + ClipboardEvent: + type: object + required: [ts, type] + properties: + ts: + type: string + format: date-time + description: Timestamp of the clipboard change + type: + type: string + description: Type of clipboard content + enum: [text, image] + preview: + type: string + description: Preview of the clipboard content (truncated if text, or 'image...' if an image) + StartRecordingRequest: type: object properties: