package playtogo import ( "bytes" "context" "encoding/json" "fmt" "io" "log/slog" "net/http" "strings" "time" ) type Client struct { baseURL string token string httpClient *http.Client } func New(baseURL, token string) *Client { return &Client{ baseURL: strings.TrimRight(baseURL, "/"), token: token, httpClient: &http.Client{ Timeout: 10 * time.Second, }, } } func (c *Client) do(ctx context.Context, method, path string, body, result any) error { var reader io.Reader if body != nil { data, err := json.Marshal(body) if err != nil { return fmt.Errorf("encode request: %s", err) } reader = bytes.NewReader(data) } req, err := http.NewRequestWithContext(ctx, method, c.baseURL+path, reader) if err != nil { return fmt.Errorf("create reqest: %s", err) } headers := map[string]string{ "Accept": "application/json", "Authorization": "Bearer " + c.token, } for k, v := range headers { req.Header.Set(k, v) } if body != nil { req.Header.Set("Content-Type", "application/json") } resp, err := c.httpClient.Do(req) if err != nil { return fmt.Errorf("send reqest: %s", err) } defer resp.Body.Close() slog.Debug("response", "status code", resp.StatusCode) if resp.StatusCode < 200 || resp.StatusCode >= 300 { return fmt.Errorf("API returned HTTP %d", resp.StatusCode) } if result == nil { return fmt.Errorf("decode response: %s", err) } if err := json.NewDecoder(resp.Body).Decode(result); err != nil { return fmt.Errorf("decode response: %w", err) } return nil }