121 lines
2.7 KiB
Go
121 lines
2.7 KiB
Go
// Package groupme defines a client capable of executing API commands for the GroupMe chat service
|
|
package groupme
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"encoding/json"
|
|
"io/ioutil"
|
|
"net/http"
|
|
)
|
|
|
|
// GroupMeAPIBase - Endpoints are added on to this to get the full URI.
|
|
// Overridable for testing
|
|
const GroupMeAPIBase = "https://api.groupme.com/v3"
|
|
|
|
// Client communicates with the GroupMe API to perform actions
|
|
// on the basic types, i.e. Listing, Creating, Destroying
|
|
type Client struct {
|
|
httpClient *http.Client
|
|
endpointBase string
|
|
}
|
|
|
|
// NewClient creates a new GroupMe API Client
|
|
func NewClient() *Client {
|
|
return &Client{
|
|
// TODO: enable transport information passing in
|
|
httpClient: &http.Client{},
|
|
endpointBase: GroupMeAPIBase,
|
|
}
|
|
}
|
|
|
|
// Close safely shuts down the Client
|
|
func (c *Client) Close() error {
|
|
c.httpClient.CloseIdleConnections()
|
|
return nil
|
|
}
|
|
|
|
// String returns a json formatted string
|
|
func (c Client) String() string {
|
|
return marshal(&c)
|
|
}
|
|
|
|
/*/// Handle parsing of nested interface type response ///*/
|
|
type jsonResponse struct {
|
|
Response response `json:"response"`
|
|
Meta `json:"meta"`
|
|
}
|
|
|
|
func newJSONResponse(i interface{}) *jsonResponse {
|
|
return &jsonResponse{Response: response{i}}
|
|
}
|
|
|
|
type response struct {
|
|
i interface{}
|
|
}
|
|
|
|
func (r response) UnmarshalJSON(bs []byte) error {
|
|
return json.NewDecoder(bytes.NewBuffer(bs)).Decode(r.i)
|
|
}
|
|
|
|
const errorStatusCodeMin = 300
|
|
|
|
func (c Client) do(ctx context.Context, req *http.Request, i interface{}) error {
|
|
req = req.WithContext(ctx)
|
|
if req.Method == "POST" {
|
|
req.Header.Set("Content-Type", "application/json")
|
|
}
|
|
|
|
getResp, err := c.httpClient.Do(req)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer getResp.Body.Close()
|
|
|
|
var readBytes []byte
|
|
// Check Status Code is 1XX or 2XX
|
|
if getResp.StatusCode >= errorStatusCodeMin {
|
|
readBytes, err = ioutil.ReadAll(getResp.Body)
|
|
if err != nil {
|
|
// We couldn't read the output. Oh well; generate the appropriate error type anyway.
|
|
return &Meta{
|
|
Code: HTTPStatusCode(getResp.StatusCode),
|
|
}
|
|
}
|
|
|
|
resp := newJSONResponse(nil)
|
|
if err = json.Unmarshal(readBytes, &resp); err != nil {
|
|
// We couldn't parse the output. Oh well; generate the appropriate error type anyway.
|
|
return &Meta{
|
|
Code: HTTPStatusCode(getResp.StatusCode),
|
|
}
|
|
}
|
|
return &resp.Meta
|
|
}
|
|
|
|
if i == nil {
|
|
return nil
|
|
}
|
|
|
|
readBytes, err = ioutil.ReadAll(getResp.Body)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
resp := newJSONResponse(i)
|
|
if err := json.Unmarshal(readBytes, &resp); err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (c Client) doWithAuthToken(ctx context.Context, req *http.Request, i interface{}, authToken string) error {
|
|
URL := req.URL
|
|
query := URL.Query()
|
|
query.Set("token", authToken)
|
|
URL.RawQuery = query.Encode()
|
|
|
|
return c.do(ctx, req, i)
|
|
}
|