package bkosmi import ( "bytes" "encoding/json" "fmt" "io" "mime/multipart" "net/http" "github.com/sirupsen/logrus" ) const ( kosmiImageUploadURL = "https://img.kosmi.io/" ) // ImageUploadResponse represents the response from Kosmi image upload endpoint type ImageUploadResponse struct { Filename string `json:"filename"` } // UploadImage uploads an image to Kosmi's CDN and returns the URL func UploadImage(imageData []byte, filename string) (string, error) { logrus.WithFields(logrus.Fields{ "filename": filename, "size": len(imageData), }).Debug("Uploading image to Kosmi CDN") // Create multipart form body body := &bytes.Buffer{} writer := multipart.NewWriter(body) // Add file field part, err := writer.CreateFormFile("file", filename) if err != nil { return "", fmt.Errorf("failed to create form file: %w", err) } if _, err := part.Write(imageData); err != nil { return "", fmt.Errorf("failed to write image data: %w", err) } // Close the multipart writer to finalize the body if err := writer.Close(); err != nil { return "", fmt.Errorf("failed to close multipart writer: %w", err) } // Create HTTP request req, err := http.NewRequest("POST", kosmiImageUploadURL, body) if err != nil { return "", fmt.Errorf("failed to create request: %w", err) } // Set required headers req.Header.Set("Content-Type", writer.FormDataContentType()) req.Header.Set("Origin", "https://app.kosmi.io") req.Header.Set("Referer", "https://app.kosmi.io/") req.Header.Set("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36") // Send request client := &http.Client{} resp, err := client.Do(req) if err != nil { return "", fmt.Errorf("failed to send request: %w", err) } defer resp.Body.Close() // Check status code if resp.StatusCode != http.StatusOK { bodyBytes, _ := io.ReadAll(resp.Body) return "", fmt.Errorf("upload failed with status %d: %s", resp.StatusCode, string(bodyBytes)) } // Read response body for debugging bodyBytes, err := io.ReadAll(resp.Body) if err != nil { return "", fmt.Errorf("failed to read response body: %w", err) } logrus.WithField("response", string(bodyBytes)).Debug("Upload response body") // Parse response var result ImageUploadResponse if err := json.Unmarshal(bodyBytes, &result); err != nil { return "", fmt.Errorf("failed to parse response: %w (body: %s)", err, string(bodyBytes)) } if result.Filename == "" { return "", fmt.Errorf("no filename in response (body: %s)", string(bodyBytes)) } // Construct the full URL from the filename imageURL := fmt.Sprintf("https://img.kosmi.io/%s", result.Filename) logrus.WithField("url", imageURL).Info("Successfully uploaded image to Kosmi CDN") return imageURL, nil }