package helpers import ( "bytes" "encoding/json" "fmt" "io" "net/http" "net/http/cookiejar" "strings" "time" "github.com/QuantumNous/new-api/common" ) type APIClient struct { BaseURL string UserID int client *http.Client } func NewAPIClient(baseURL string) (*APIClient, error) { jar, err := cookiejar.New(nil) if err != nil { return nil, fmt.Errorf("create cookie jar: %w", err) } return &APIClient{ BaseURL: strings.TrimRight(baseURL, "/"), client: &http.Client{ Jar: jar, Timeout: 15 * time.Second, }, }, nil } func (c *APIClient) DoJSON(method, path string, requestBody any, expectedStatus int, responseBody any) error { return c.DoJSONWithHeaders(method, path, requestBody, expectedStatus, nil, responseBody) } func (c *APIClient) DoJSONWithHeaders(method, path string, requestBody any, expectedStatus int, headers map[string]string, responseBody any) error { var bodyReader io.Reader var requestDump string if requestBody != nil { data, err := common.Marshal(requestBody) if err != nil { return fmt.Errorf("marshal request body for %s %s: %w", method, path, err) } bodyReader = bytes.NewReader(data) requestDump = string(data) } req, err := http.NewRequest(method, c.BaseURL+path, bodyReader) if err != nil { return fmt.Errorf("create request %s %s: %w", method, path, err) } req.Header.Set("Accept", "application/json") if requestBody != nil { req.Header.Set("Content-Type", "application/json") } if c.UserID != 0 { req.Header.Set("New-Api-User", fmt.Sprintf("%d", c.UserID)) } for key, value := range headers { req.Header.Set(key, value) } resp, err := c.client.Do(req) if err != nil { return fmt.Errorf("do request %s %s: %w", method, path, err) } defer resp.Body.Close() respData, err := io.ReadAll(resp.Body) if err != nil { return fmt.Errorf("read response %s %s: %w", method, path, err) } if resp.StatusCode != expectedStatus { return fmt.Errorf( "%s %s: expected status %d, got %d, request=%s, response=%s", method, path, expectedStatus, resp.StatusCode, requestDump, string(respData), ) } if responseBody == nil || len(respData) == 0 { return nil } if err := common.Unmarshal(respData, responseBody); err != nil { return fmt.Errorf( "unmarshal response for %s %s: %w, raw=%s", method, path, err, string(respData), ) } return nil } func (c *APIClient) GetJSON(path string, expectedStatus int, responseBody any) error { return c.DoJSON(http.MethodGet, path, nil, expectedStatus, responseBody) } func (c *APIClient) PostJSON(path string, requestBody any, expectedStatus int, responseBody any) error { return c.DoJSON(http.MethodPost, path, requestBody, expectedStatus, responseBody) } func (c *APIClient) PutJSON(path string, requestBody any, expectedStatus int, responseBody any) error { return c.DoJSON(http.MethodPut, path, requestBody, expectedStatus, responseBody) } func (c *APIClient) DeleteJSON(path string, expectedStatus int, responseBody any) error { return c.DoJSON(http.MethodDelete, path, nil, expectedStatus, responseBody) } type Envelope struct { Success bool `json:"success"` Message string `json:"message,omitempty"` Error string `json:"error,omitempty"` Data json.RawMessage `json:"data,omitempty"` }