vegapokerbot/internal/integration/redmine/api/client.go

117 lines
2.6 KiB
Go
Raw Permalink Normal View History

2024-05-07 21:49:09 +03:00
package api
import (
"bytes"
"encoding/json"
2024-05-10 11:46:43 +03:00
"errors"
"go.uber.org/zap"
2024-05-07 21:49:09 +03:00
"io"
"net/http"
"net/url"
2024-05-07 21:49:09 +03:00
"strconv"
"strings"
"time"
)
type Client struct {
URL string
Key string
client *http.Client
2024-05-10 11:46:43 +03:00
log *zap.SugaredLogger
2024-05-07 21:49:09 +03:00
}
2024-05-10 11:46:43 +03:00
func New(url, key string, log *zap.SugaredLogger) *Client {
2024-05-07 21:49:09 +03:00
return &Client{
URL: strings.TrimSuffix(url, "/"),
Key: key,
client: &http.Client{Timeout: time.Second * 2},
2024-05-10 11:46:43 +03:00
log: log,
2024-05-07 21:49:09 +03:00
}
}
2024-05-10 11:46:43 +03:00
func (c *Client) Issue(id int) (*Issue, error) {
2024-05-07 21:49:09 +03:00
var resp IssueResponse
2024-05-10 11:46:43 +03:00
_, err := c.sendJSONRequest(http.MethodGet, "/issues/"+strconv.Itoa(id), nil, &resp)
2024-05-07 21:49:09 +03:00
if err != nil {
return nil, err
}
if resp.IsError() {
return nil, resp
}
return resp.Issue, nil
}
func (c *Client) SearchIssues(query string, offset, limit int) (*SearchIssuesResponse, error) {
req := url.Values{
"q": []string{query},
"offset": []string{strconv.Itoa(offset)},
"limit": []string{strconv.Itoa(limit)},
}
var resp SearchIssuesResponse
_, err := c.sendJSONRequest(http.MethodGet, "/search.json?"+req.Encode(), nil, &resp)
if err != nil {
return nil, err
}
if resp.IsError() {
return nil, resp
}
return &resp, nil
}
2024-05-10 11:46:43 +03:00
func (c *Client) UpdateIssue(id int, issue *Issue) error {
st, err := c.sendJSONRequest(http.MethodPut, "/issues/"+strconv.Itoa(id), IssueResponse{Issue: issue}, nil)
if err != nil {
return err
}
if st != http.StatusOK {
return errors.New("unexpected status code: " + strconv.Itoa(st))
}
return nil
}
func (c *Client) sendRequest(method, path string, headers map[string]string, body io.Reader) (*http.Response, error) {
2024-05-07 21:49:09 +03:00
req, err := http.NewRequest(method, c.URL+path, body)
if err != nil {
return nil, err
}
req.Header.Set("X-Redmine-API-Key", c.Key)
2024-05-10 11:46:43 +03:00
for name, value := range headers {
req.Header.Set(name, value)
}
2024-05-07 21:49:09 +03:00
return c.client.Do(req)
}
2024-05-10 11:46:43 +03:00
func (c *Client) sendJSONRequest(method, path string, body, out interface{}) (int, error) {
2024-05-07 21:49:09 +03:00
var buf io.Reader
if body != nil {
data, err := json.Marshal(body)
if err != nil {
2024-05-10 11:46:43 +03:00
return 0, err
2024-05-07 21:49:09 +03:00
}
buf = bytes.NewBuffer(data)
}
2024-05-10 11:46:43 +03:00
path = path + ".json"
c.log.Debugf("[Redmine Request] %s %s; body: %s", method, path, func() string {
if buf != nil {
return buf.(*bytes.Buffer).String()
}
return "<nil>"
}())
resp, err := c.sendRequest(method, path, map[string]string{
"Content-Type": "application/json",
}, buf)
2024-05-07 21:49:09 +03:00
if err != nil {
2024-05-10 11:46:43 +03:00
return 0, err
2024-05-07 21:49:09 +03:00
}
defer func() { _ = resp.Body.Close() }()
2024-05-10 11:46:43 +03:00
if out != nil {
return resp.StatusCode, json.NewDecoder(resp.Body).Decode(out)
}
c.log.Debugf("[Redmine Response] code: %d; body: %#v", resp.StatusCode, out)
return resp.StatusCode, nil
2024-05-07 21:49:09 +03:00
}