Introducing Contexts

Contexts have been added to all API requests, in addition to other linting fixes
This commit is contained in:
densestvoid 2021-01-22 16:47:22 -05:00
parent 646bec0e27
commit f92a8a7a86
33 changed files with 374 additions and 542 deletions

View File

@ -1,12 +1,14 @@
// Package groupme defines a client capable of executing API commands for the GroupMe chat service
package groupme
import (
"context"
"net/http"
)
// GroupMe documentation: https://dev.groupme.com/docs/v3#blocks
////////// Endpoints //////////
/*//////// Endpoints ////////*/
const (
// Used to build other endpoints
blocksEndpointRoot = "/blocks"
@ -18,19 +20,10 @@ const (
unblockEndpoint = blocksEndpointRoot // DELETE
)
////////// API Requests //////////
/*//////// API Requests ////////*/
// Index
/*
IndexBlock -
A list of contacts you have blocked. These people cannot DM you
Parameters:
userID - required, ID(string)
*/
func (c *Client) IndexBlock(userID ID) ([]*Block, error) {
// IndexBlock - A list of contacts you have blocked. These people cannot DM you
func (c *Client) IndexBlock(ctx context.Context, userID string) ([]*Block, error) {
httpReq, err := http.NewRequest("GET", c.endpointBase+indexBlocksEndpoint, nil)
if err != nil {
return nil, err
@ -38,13 +31,13 @@ func (c *Client) IndexBlock(userID ID) ([]*Block, error) {
URL := httpReq.URL
query := URL.Query()
query.Set("user", userID.String())
query.Set("user", userID)
URL.RawQuery = query.Encode()
var resp struct {
Blocks []*Block `json:"blocks"`
}
err = c.doWithAuthToken(httpReq, &resp)
err = c.doWithAuthToken(ctx, httpReq, &resp)
if err != nil {
return nil, err
}
@ -52,17 +45,8 @@ func (c *Client) IndexBlock(userID ID) ([]*Block, error) {
return resp.Blocks, nil
}
// Between
/*
BlockBetween -
Asks if a block exists between you and another user id
Parameters:
otherUserID - required, ID(string)
*/
func (c *Client) BlockBetween(userID, otherUserID ID) (bool, error) {
// BlockBetween - Asks if a block exists between you and another user id
func (c *Client) BlockBetween(ctx context.Context, userID, otherUserID string) (bool, error) {
httpReq, err := http.NewRequest("GET", c.endpointBase+blockBetweenEndpoint, nil)
if err != nil {
return false, err
@ -70,14 +54,14 @@ func (c *Client) BlockBetween(userID, otherUserID ID) (bool, error) {
URL := httpReq.URL
query := URL.Query()
query.Set("user", userID.String())
query.Set("otherUser", otherUserID.String())
query.Set("user", userID)
query.Set("otherUser", otherUserID)
URL.RawQuery = query.Encode()
var resp struct {
Between bool `json:"between"`
}
err = c.doWithAuthToken(httpReq, &resp)
err = c.doWithAuthToken(ctx, httpReq, &resp)
if err != nil {
return false, err
}
@ -85,18 +69,8 @@ func (c *Client) BlockBetween(userID, otherUserID ID) (bool, error) {
return resp.Between, nil
}
// Create
/*
CreateBlock -
Creates a block between you and the contact
Parameters:
userID - required, ID(string)
otherUserID - required, ID(string)
*/
func (c *Client) CreateBlock(userID, otherUserID ID) (*Block, error) {
// CreateBlock - Creates a block between you and the contact
func (c *Client) CreateBlock(ctx context.Context, userID, otherUserID string) (*Block, error) {
httpReq, err := http.NewRequest("POST", c.endpointBase+createBlockEndpoint, nil)
if err != nil {
return nil, err
@ -104,14 +78,14 @@ func (c *Client) CreateBlock(userID, otherUserID ID) (*Block, error) {
URL := httpReq.URL
query := URL.Query()
query.Set("user", userID.String())
query.Set("otherUser", otherUserID.String())
query.Set("user", userID)
query.Set("otherUser", otherUserID)
URL.RawQuery = query.Encode()
var resp struct {
Block *Block `json:"block"`
}
err = c.doWithAuthToken(httpReq, &resp)
err = c.doWithAuthToken(ctx, httpReq, &resp)
if err != nil {
return nil, err
}
@ -119,18 +93,8 @@ func (c *Client) CreateBlock(userID, otherUserID ID) (*Block, error) {
return resp.Block, nil
}
// Unblock
/*
Unblock -
Removes block between you and other user
Parameters:
userID - required, ID(string)
otherUserID - required, ID(string)
*/
func (c *Client) Unblock(userID, otherUserID ID) error {
// Unblock - Removes block between you and other user
func (c *Client) Unblock(ctx context.Context, userID, otherUserID string) error {
httpReq, err := http.NewRequest("DELETE", c.endpointBase+unblockEndpoint, nil)
if err != nil {
return err
@ -138,11 +102,11 @@ func (c *Client) Unblock(userID, otherUserID ID) error {
URL := httpReq.URL
query := URL.Query()
query.Set("user", userID.String())
query.Set("otherUser", otherUserID.String())
query.Set("user", userID)
query.Set("otherUser", otherUserID)
URL.RawQuery = query.Encode()
err = c.doWithAuthToken(httpReq, nil)
err = c.doWithAuthToken(ctx, httpReq, nil)
if err != nil {
return err
}

View File

@ -1,6 +1,8 @@
// Package groupme defines a client capable of executing API commands for the GroupMe chat service
package groupme
import (
"context"
"fmt"
"net/http"
"testing"
@ -17,7 +19,7 @@ func (s *BlocksAPISuite) SetupSuite() {
}
func (s *BlocksAPISuite) TestBlocksIndex() {
blocks, err := s.client.IndexBlock("1")
blocks, err := s.client.IndexBlock(context.Background(), "1")
s.Require().NoError(err)
s.Require().NotZero(blocks)
for _, block := range blocks {
@ -26,19 +28,19 @@ func (s *BlocksAPISuite) TestBlocksIndex() {
}
func (s *BlocksAPISuite) TestBlocksBetween() {
between, err := s.client.BlockBetween("1", "2")
between, err := s.client.BlockBetween(context.Background(), "1", "2")
s.Require().NoError(err)
s.Assert().True(between)
}
func (s *BlocksAPISuite) TestBlocksCreate() {
block, err := s.client.CreateBlock("1", "2")
block, err := s.client.CreateBlock(context.Background(), "1", "2")
s.Require().NoError(err)
s.Assert().NotZero(block)
}
func (s *BlocksAPISuite) TestBlocksUnblock() {
s.Assert().NoError(s.client.Unblock("1", "2"))
s.Assert().NoError(s.client.Unblock(context.Background(), "1", "2"))
}
func TestBlocksAPISuite(t *testing.T) {

View File

@ -1,7 +1,9 @@
// Package groupme defines a client capable of executing API commands for the GroupMe chat service
package groupme
import (
"bytes"
"context"
"encoding/json"
"fmt"
"net/http"
@ -9,7 +11,7 @@ import (
// GroupMe documentation: https://dev.groupme.com/docs/v3#bots
////////// Endpoints //////////
/*//////// Endpoints ////////*/
const (
// Used to build other endpoints
botsEndpointRoot = "/bots"
@ -21,22 +23,11 @@ const (
destroyBotEndpoint = botsEndpointRoot + "/destroy" // POST
)
////////// API Requests //////////
/*//////// API Requests ////////*/
// Create
/*
CreateBot -
Create a bot. See the Bots Tutorial (https://dev.groupme.com/tutorials/bots)
for a full walkthrough.
Parameters:
See Bot
Name - required
GroupID - required
*/
func (c *Client) CreateBot(bot *Bot) (*Bot, error) {
// CreateBot - Create a bot. See the Bots Tutorial (https://dev.groupme.com/tutorials/bots)
// for a full walkthrough.
func (c *Client) CreateBot(ctx context.Context, bot *Bot) (*Bot, error) {
URL := c.endpointBase + createBotEndpoint
var data = struct {
@ -56,7 +47,7 @@ func (c *Client) CreateBot(bot *Bot) (*Bot, error) {
}
var resp Bot
err = c.doWithAuthToken(httpReq, &resp)
err = c.doWithAuthToken(ctx, httpReq, &resp)
if err != nil {
return nil, err
}
@ -64,21 +55,9 @@ func (c *Client) CreateBot(bot *Bot) (*Bot, error) {
return &resp, nil
}
// PostMessage
/*
PostBotMessage -
Post a message from a bot
Parameters:
botID - required, ID(string)
text - required, string
pictureURL - string; image must be processed through image
service (https://dev.groupme.com/docs/image_service)
*/
// PostBotMessage - Post a message from a bot
// TODO: Move PostBotMessage to bot object, since it doesn't require access token
func (c *Client) PostBotMessage(botID ID, text string, pictureURL *string) error {
func (c *Client) PostBotMessage(ctx context.Context, botID ID, text string, pictureURL *string) error {
URL := fmt.Sprintf(c.endpointBase + postBotMessageEndpoint)
var data = struct {
@ -101,24 +80,18 @@ func (c *Client) PostBotMessage(botID ID, text string, pictureURL *string) error
return err
}
return c.do(httpReq, nil)
return c.do(ctx, httpReq, nil)
}
// Index
/*
IndexBots -
List bots that you have created
*/
func (c *Client) IndexBots() ([]*Bot, error) {
// IndexBots - list bots that you have created
func (c *Client) IndexBots(ctx context.Context) ([]*Bot, error) {
httpReq, err := http.NewRequest("GET", c.endpointBase+indexBotsEndpoint, nil)
if err != nil {
return nil, err
}
var resp []*Bot
err = c.doWithAuthToken(httpReq, &resp)
err = c.doWithAuthToken(ctx, httpReq, &resp)
if err != nil {
return nil, err
}
@ -126,17 +99,8 @@ func (c *Client) IndexBots() ([]*Bot, error) {
return resp, nil
}
// Destroy
/*
DestroyBot -
Remove a bot that you have created
Parameters:
botID - required, ID(string)
*/
func (c *Client) DestroyBot(botID ID) error {
// DestroyBot - Remove a bot that you have created
func (c *Client) DestroyBot(ctx context.Context, botID ID) error {
URL := fmt.Sprintf(c.endpointBase + destroyBotEndpoint)
var data = struct {
@ -155,5 +119,5 @@ func (c *Client) DestroyBot(botID ID) error {
return err
}
return c.doWithAuthToken(httpReq, nil)
return c.doWithAuthToken(ctx, httpReq, nil)
}

View File

@ -1,6 +1,8 @@
// Package groupme defines a client capable of executing API commands for the GroupMe chat service
package groupme
import (
"context"
"fmt"
"net/http"
"testing"
@ -17,7 +19,7 @@ func (s *BotsAPISuite) SetupSuite() {
}
func (s *BotsAPISuite) TestBotsCreate() {
bot, err := s.client.CreateBot(&Bot{
bot, err := s.client.CreateBot(context.Background(), &Bot{
Name: "test",
GroupID: "1",
AvatarURL: "url.com",
@ -29,12 +31,12 @@ func (s *BotsAPISuite) TestBotsCreate() {
}
func (s *BotsAPISuite) TestBotsPostMessage() {
err := s.client.PostBotMessage("1", "test message", nil)
err := s.client.PostBotMessage(context.Background(), "1", "test message", nil)
s.Require().NoError(err)
}
func (s *BotsAPISuite) TestBotsIndex() {
bots, err := s.client.IndexBots()
bots, err := s.client.IndexBots(context.Background())
s.Require().NoError(err)
s.Require().NotZero(bots)
for _, bot := range bots {
@ -43,7 +45,7 @@ func (s *BotsAPISuite) TestBotsIndex() {
}
func (s *BotsAPISuite) TestBotsDestroy() {
s.Require().NoError(s.client.DestroyBot("1"))
s.Require().NoError(s.client.DestroyBot(context.Background(), "1"))
}
func TestBotsAPISuite(t *testing.T) {

View File

@ -1,13 +1,15 @@
// Package groupme defines a client capable of executing API commands for the GroupMe chat service
package groupme
import (
"context"
"net/http"
"strconv"
)
// GroupMe documentation: https://dev.groupme.com/docs/v3#chats
////////// Endpoints //////////
/*//////// Endpoints ////////*/
const (
// Used to build other endpoints
chatsEndpointRoot = "/chats"
@ -15,9 +17,7 @@ const (
indexChatsEndpoint = chatsEndpointRoot // GET
)
// Index
// ChatsQuery defines the optional URL parameters for IndexChats
// IndexChatsQuery defines the optional URL parameters for IndexChats
type IndexChatsQuery struct {
// Page Number
Page int `json:"page"`
@ -25,15 +25,9 @@ type IndexChatsQuery struct {
PerPage int `json:"per_page"`
}
/*
IndexChats -
Returns a paginated list of direct message chats, or
conversations, sorted by updated_at descending.
Parameters: See ChatsQuery
*/
func (c *Client) IndexChats(req *IndexChatsQuery) ([]*Chat, error) {
// IndexChats - Returns a paginated list of direct message chats, or
// conversations, sorted by updated_at descending.
func (c *Client) IndexChats(ctx context.Context, req *IndexChatsQuery) ([]*Chat, error) {
httpReq, err := http.NewRequest("GET", c.endpointBase+indexChatsEndpoint, nil)
if err != nil {
return nil, err
@ -52,7 +46,7 @@ func (c *Client) IndexChats(req *IndexChatsQuery) ([]*Chat, error) {
URL.RawQuery = query.Encode()
var resp []*Chat
err = c.doWithAuthToken(httpReq, &resp)
err = c.doWithAuthToken(ctx, httpReq, &resp)
if err != nil {
return nil, err
}

View File

@ -1,6 +1,8 @@
// Package groupme defines a client capable of executing API commands for the GroupMe chat service
package groupme
import (
"context"
"fmt"
"net/http"
"testing"
@ -18,6 +20,7 @@ func (s *ChatsAPISuite) SetupSuite() {
func (s *ChatsAPISuite) TestChatsIndex() {
chats, err := s.client.IndexChats(
context.Background(),
&IndexChatsQuery{
Page: 1,
PerPage: 20,

View File

@ -1,13 +1,15 @@
// 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"
)
// Endpoints are added on to the GroupMeAPIBase to get the full URI.
// GroupMeAPIBase - Endpoints are added on to this to get the full URI.
// Overridable for testing
const GroupMeAPIBase = "https://api.groupme.com/v3"
@ -40,7 +42,7 @@ func (c Client) String() string {
return marshal(&c)
}
///// Handle parsing of nested interface type response /////
/*/// Handle parsing of nested interface type response ///*/
type jsonResponse struct {
Response response `json:"response"`
Meta `json:"meta"`
@ -58,7 +60,10 @@ func (r response) UnmarshalJSON(bs []byte) error {
return json.NewDecoder(bytes.NewBuffer(bs)).Decode(r.i)
}
func (c Client) do(req *http.Request, i interface{}) error {
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")
}
@ -69,9 +74,10 @@ func (c Client) do(req *http.Request, i interface{}) error {
}
defer getResp.Body.Close()
var readBytes []byte
// Check Status Code is 1XX or 2XX
if getResp.StatusCode/100 > 2 {
bytes, err := ioutil.ReadAll(getResp.Body)
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{
@ -80,7 +86,7 @@ func (c Client) do(req *http.Request, i interface{}) error {
}
resp := newJSONResponse(nil)
if err := json.Unmarshal(bytes, &resp); err != 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),
@ -93,24 +99,24 @@ func (c Client) do(req *http.Request, i interface{}) error {
return nil
}
bytes, err := ioutil.ReadAll(getResp.Body)
readBytes, err = ioutil.ReadAll(getResp.Body)
if err != nil {
return err
}
resp := newJSONResponse(i)
if err := json.Unmarshal(bytes, &resp); err != nil {
if err := json.Unmarshal(readBytes, &resp); err != nil {
return err
}
return nil
}
func (c Client) doWithAuthToken(req *http.Request, i interface{}) error {
func (c Client) doWithAuthToken(ctx context.Context, req *http.Request, i interface{}) error {
URL := req.URL
query := URL.Query()
query.Set("token", c.authorizationToken)
URL.RawQuery = query.Encode()
return c.do(req, i)
return c.do(ctx, req, i)
}

View File

@ -1,6 +1,8 @@
// Package groupme defines a client capable of executing API commands for the GroupMe chat service
package groupme
import (
"context"
"net/http"
"testing"
@ -34,7 +36,7 @@ func (s *ClientSuite) TestClient_do_PostContentType() {
req, err := http.NewRequest("POST", "", nil)
s.Require().NoError(err)
s.Assert().Error(s.client.do(req, struct{}{}))
s.Assert().Error(s.client.do(context.Background(), req, struct{}{}))
s.Assert().EqualValues(req.Header.Get("Content-Type"), "application/json")
}
@ -42,14 +44,14 @@ func (s *ClientSuite) TestClient_do_DoError() {
req, err := http.NewRequest("", "", nil)
s.Require().NoError(err)
s.Assert().Error(s.client.do(req, struct{}{}))
s.Assert().Error(s.client.do(context.Background(), req, struct{}{}))
}
func (s *ClientSuite) TestClient_do_UnmarshalError() {
req, err := http.NewRequest("GET", s.addr, nil)
s.Require().NoError(err)
s.Assert().Error(s.client.do(req, struct{}{}))
s.Assert().Error(s.client.do(context.Background(), req, struct{}{}))
}
func TestClientSuite(t *testing.T) {

View File

@ -1,3 +1,4 @@
// Package groupme defines a client capable of executing API commands for the GroupMe chat service
package groupme
import (
@ -44,7 +45,7 @@ func (t Timestamp) String() string {
type PhoneNumber string
// Treated as a constant
var phoneNumberRegex = regexp.MustCompile(`^\+[0-9]+ [0-9]{10}$`)
var phoneNumberRegex = regexp.MustCompile(`^\+\d+ \d{10}$`)
// Valid checks if the ID string is alpha numeric
func (pn PhoneNumber) Valid() bool {
@ -55,40 +56,40 @@ func (pn PhoneNumber) String() string {
return string(pn)
}
// StatusCodes are returned by HTTP requests in
// HTTPStatusCode are returned by HTTP requests in
// the header and the json "meta" field
type HTTPStatusCode int
// Text used as constant name
const (
HTTP_Ok HTTPStatusCode = 200
HTTP_Created HTTPStatusCode = 201
HTTP_NoContent HTTPStatusCode = 204
HTTP_NotModified HTTPStatusCode = 304
HTTP_BadRequest HTTPStatusCode = 400
HTTP_Unauthorized HTTPStatusCode = 401
HTTP_Forbidden HTTPStatusCode = 403
HTTP_NotFound HTTPStatusCode = 404
HTTP_EnhanceYourCalm HTTPStatusCode = 420
HTTP_InternalServerError HTTPStatusCode = 500
HTTP_BadGateway HTTPStatusCode = 502
HTTP_ServiceUnavailable HTTPStatusCode = 503
HTTPOk HTTPStatusCode = 200
HTTPCreated HTTPStatusCode = 201
HTTPNoContent HTTPStatusCode = 204
HTTPNotModified HTTPStatusCode = 304
HTTPBadRequest HTTPStatusCode = 400
HTTPUnauthorized HTTPStatusCode = 401
HTTPForbidden HTTPStatusCode = 403
HTTPNotFound HTTPStatusCode = 404
HTTPEnhanceYourCalm HTTPStatusCode = 420
HTTPInternalServerError HTTPStatusCode = 500
HTTPBadGateway HTTPStatusCode = 502
HTTPServiceUnavailable HTTPStatusCode = 503
)
// String returns the description of the status code according to GroupMe
func (c HTTPStatusCode) String() string {
return map[HTTPStatusCode]string{
HTTP_Ok: "success",
HTTP_Created: "resource was created successfully",
HTTP_NoContent: "resource was deleted successfully",
HTTP_NotModified: "no new data to return",
HTTP_BadRequest: "invalid format or data specified in the request",
HTTP_Unauthorized: "authentication credentials missing or incorrect",
HTTP_Forbidden: "request refused due to update limits",
HTTP_NotFound: "URI is invalid or resource does not exist",
HTTP_EnhanceYourCalm: "application is being rate limited",
HTTP_InternalServerError: "something unexpected occurred",
HTTP_BadGateway: "GroupMe is down or being upgraded",
HTTP_ServiceUnavailable: "servers are overloaded, try again later",
HTTPOk: "success",
HTTPCreated: "resource was created successfully",
HTTPNoContent: "resource was deleted successfully",
HTTPNotModified: "no new data to return",
HTTPBadRequest: "invalid format or data specified in the request",
HTTPUnauthorized: "authentication credentials missing or incorrect",
HTTPForbidden: "request refused due to update limits",
HTTPNotFound: "URI is invalid or resource does not exist",
HTTPEnhanceYourCalm: "application is being rate limited",
HTTPInternalServerError: "something unexpected occurred",
HTTPBadGateway: "GroupMe is down or being upgraded",
HTTPServiceUnavailable: "servers are overloaded, try again later",
}[c]
}

View File

@ -1,3 +1,4 @@
// Package groupme defines a client capable of executing API commands for the GroupMe chat service
package groupme
import (

View File

@ -1,7 +1,9 @@
// Package groupme defines a client capable of executing API commands for the GroupMe chat service
package groupme
import (
"bytes"
"context"
"encoding/json"
"fmt"
"net/http"
@ -11,7 +13,7 @@ import (
// GroupMe documentation: https://dev.groupme.com/docs/v3#direct_messages
////////// Endpoints //////////
/*//////// Endpoints ////////*/
const (
// Used to build other endpoints
directMessagesEndpointRoot = "/direct_messages"
@ -21,11 +23,9 @@ const (
createDirectMessageEndpoint = directMessagesEndpointRoot // POST
)
////////// API Requests //////////
/*//////// API Requests ////////*/
// Index
// MessagesQuery defines the optional URL parameters for IndexDirectMessages
// IndexDirectMessagesQuery defines the optional URL parameters for IndexDirectMessages
type IndexDirectMessagesQuery struct {
// Returns 20 messages created before the given message ID
BeforeID ID `json:"before_id"`
@ -66,14 +66,14 @@ Parameters:
otherUserID - required, ID(string); the other participant in the conversation.
See IndexDirectMessagesQuery
*/
func (c *Client) IndexDirectMessages(otherUserID ID, req *IndexDirectMessagesQuery) (IndexDirectMessagesResponse, error) {
func (c *Client) IndexDirectMessages(ctx context.Context, otherUserID string, req *IndexDirectMessagesQuery) (IndexDirectMessagesResponse, error) {
httpReq, err := http.NewRequest("GET", c.endpointBase+indexDirectMessagesEndpoint, nil)
if err != nil {
return IndexDirectMessagesResponse{}, err
}
query := httpReq.URL.Query()
query.Set("other_user_id", otherUserID.String())
query.Set("other_user_id", otherUserID)
if req != nil {
if req.BeforeID != "" {
query.Add("before_ID", req.BeforeID.String())
@ -84,7 +84,7 @@ func (c *Client) IndexDirectMessages(otherUserID ID, req *IndexDirectMessagesQue
}
var resp IndexDirectMessagesResponse
err = c.doWithAuthToken(httpReq, &resp)
err = c.doWithAuthToken(ctx, httpReq, &resp)
if err != nil {
return IndexDirectMessagesResponse{}, err
}
@ -92,12 +92,8 @@ func (c *Client) IndexDirectMessages(otherUserID ID, req *IndexDirectMessagesQue
return resp, nil
}
// Create
/*
CreateDirectMessage -
Send a DM to another user
CreateDirectMessage - Send a DM to another user
If you want to attach an image, you must first process it
through our image service.
@ -109,18 +105,8 @@ specify a replacement charmap to substitute emoji characters
The character map is an array of arrays containing rune data
([[{pack_id,offset}],...]).
Parameters:
See Message.
recipientID - required, ID(string); The GroupMe user ID of the recipient of this message.
text - required, string. Can be ommitted if at least one
attachment is present
attachments - a polymorphic list of attachments (locations,
images, etc). You may have You may have more than
one of any type of attachment, provided clients can
display it.
*/
func (c *Client) CreateDirectMessage(m *Message) (*Message, error) {
func (c *Client) CreateDirectMessage(ctx context.Context, m *Message) (*Message, error) {
URL := fmt.Sprintf(c.endpointBase + createDirectMessageEndpoint)
m.SourceGUID = uuid.New().String()
@ -143,7 +129,7 @@ func (c *Client) CreateDirectMessage(m *Message) (*Message, error) {
var resp struct {
*Message `json:"message"`
}
err = c.doWithAuthToken(httpReq, &resp)
err = c.doWithAuthToken(ctx, httpReq, &resp)
if err != nil {
return nil, err
}

View File

@ -1,6 +1,8 @@
// Package groupme defines a client capable of executing API commands for the GroupMe chat service
package groupme
import (
"context"
"fmt"
"net/http"
"testing"
@ -18,7 +20,8 @@ func (s *DirectMessagesAPISuite) SetupSuite() {
func (s *DirectMessagesAPISuite) TestDirectMessagesIndex() {
resp, err := s.client.IndexDirectMessages(
ID("123"),
context.Background(),
"123",
&IndexDirectMessagesQuery{
BeforeID: "0123456789",
SinceID: "9876543210",
@ -33,6 +36,7 @@ func (s *DirectMessagesAPISuite) TestDirectMessagesIndex() {
func (s *DirectMessagesAPISuite) TestDirectMessagesCreate() {
message, err := s.client.CreateDirectMessage(
context.Background(),
&Message{
RecipientID: ID("123"),
Text: "Test",
@ -47,6 +51,7 @@ func TestDirectMessagesAPISuite(t *testing.T) {
suite.Run(t, new(DirectMessagesAPISuite))
}
// nolint // not duplicate code
func directMessagesTestRouter() *mux.Router {
router := mux.NewRouter().Queries("token", "").Subrouter()

View File

@ -1,6 +1,7 @@
package main
import (
"context"
"fmt"
"github.com/densestvoid/groupme"
@ -18,11 +19,14 @@ func main() {
client := groupme.NewClient(authorizationToken)
// Get the groups your user is part of
groups, err := client.IndexGroups(&groupme.GroupsQuery{
Page: 0,
PerPage: 5,
Omit: "memberships",
})
groups, err := client.IndexGroups(
context.Background(),
&groupme.GroupsQuery{
Page: 0,
PerPage: 5,
Omit: "memberships",
},
)
if err != nil {
fmt.Println(err)
@ -32,11 +36,11 @@ func main() {
fmt.Println(groups)
// Get first 10 messages of the first group
if len(groups) <= 0 {
if len(groups) == 0 {
fmt.Println("No groups")
}
messages, err := client.IndexMessages(groups[0].ID, &groupme.IndexMessagesQuery{
messages, err := client.IndexMessages(context.Background(), groups[0].ID, &groupme.IndexMessagesQuery{
Limit: 10,
})

View File

@ -1,6 +1,7 @@
package main
import (
"context"
"fmt"
"github.com/densestvoid/groupme"
@ -16,5 +17,5 @@ const botID = "0123456789ABCDEF"
func main() {
// Create a new client with your auth token
client := groupme.NewClient("")
fmt.Println(client.PostBotMessage(botID, "Your message here!", nil))
fmt.Println(client.PostBotMessage(context.Background(), botID, "Your message here!", nil))
}

17
go.mod
View File

@ -1,18 +1,9 @@
module github.com/densestvoid/groupme
go 1.14
go 1.15
require (
github.com/go-critic/go-critic v0.5.0 // indirect
github.com/go-toolsmith/astinfo v1.0.0 // indirect
github.com/google/go-cmp v0.5.1 // indirect
github.com/google/uuid v1.1.1
github.com/gorilla/mux v1.7.4
github.com/logrusorgru/aurora v2.0.3+incompatible // indirect
github.com/mattn/goveralls v0.0.6 // indirect
github.com/quasilyte/go-consistent v0.0.0-20200404105227-766526bf1e96 // indirect
github.com/quasilyte/go-ruleguard v0.1.3 // indirect
github.com/quasilyte/regex/syntax v0.0.0-20200419152657-af9db7f4a3ab // indirect
github.com/stretchr/testify v1.5.1
golang.org/x/tools v0.0.0-20200728190822-edd3c8e9e279 // indirect
github.com/google/uuid v1.2.0
github.com/gorilla/mux v1.8.0
github.com/stretchr/testify v1.7.0
)

107
go.sum
View File

@ -1,105 +1,16 @@
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/go-critic/go-critic v0.5.0 h1:Ic2p5UCl5fX/2WX2w8nroPpPhxRNsNTMlJzsu/uqwnM=
github.com/go-critic/go-critic v0.5.0/go.mod h1:4jeRh3ZAVnRYhuWdOEvwzVqLUpxMSoAT0xZ74JsTPlo=
github.com/go-lintpack/lintpack v0.5.2/go.mod h1:NwZuYi2nUHho8XEIZ6SIxihrnPoqBTDqfpXvXAN0sXM=
github.com/go-toolsmith/astcast v1.0.0 h1:JojxlmI6STnFVG9yOImLeGREv8W2ocNUM+iOhR6jE7g=
github.com/go-toolsmith/astcast v1.0.0/go.mod h1:mt2OdQTeAQcY4DQgPSArJjHCcOwlX+Wl/kwN+LbLGQ4=
github.com/go-toolsmith/astcopy v1.0.0 h1:OMgl1b1MEpjFQ1m5ztEO06rz5CUd3oBv9RF7+DyvdG8=
github.com/go-toolsmith/astcopy v1.0.0/go.mod h1:vrgyG+5Bxrnz4MZWPF+pI4R8h3qKRjjyvV/DSez4WVQ=
github.com/go-toolsmith/astequal v0.0.0-20180903214952-dcb477bfacd6/go.mod h1:H+xSiq0+LtiDC11+h1G32h7Of5O3CYFJ99GVbS5lDKY=
github.com/go-toolsmith/astequal v1.0.0 h1:4zxD8j3JRFNyLN46lodQuqz3xdKSrur7U/sr0SDS/gQ=
github.com/go-toolsmith/astequal v1.0.0/go.mod h1:H+xSiq0+LtiDC11+h1G32h7Of5O3CYFJ99GVbS5lDKY=
github.com/go-toolsmith/astfmt v0.0.0-20180903215011-8f8ee99c3086/go.mod h1:mP93XdblcopXwlyN4X4uodxXQhldPGZbcEJIimQHrkg=
github.com/go-toolsmith/astfmt v1.0.0 h1:A0vDDXt+vsvLEdbMFJAUBI/uTbRw1ffOPnxsILnFL6k=
github.com/go-toolsmith/astfmt v1.0.0/go.mod h1:cnWmsOAuq4jJY6Ct5YWlVLmcmLMn1JUPuQIHCY7CJDw=
github.com/go-toolsmith/astinfo v0.0.0-20180906194353-9809ff7efb21 h1:wP6mXeB2V/d1P1K7bZ5vDUO3YqEzcvOREOxZPEu3gVI=
github.com/go-toolsmith/astinfo v0.0.0-20180906194353-9809ff7efb21/go.mod h1:dDStQCHtmZpYOmjRP/8gHHnCCch3Zz3oEgCdZVdtweU=
github.com/go-toolsmith/astinfo v1.0.0 h1:rNuhpyhsnsze/Pe1l/GUHwxo1rmN7Dyb6oAnFcrXh+w=
github.com/go-toolsmith/astinfo v1.0.0/go.mod h1:dDStQCHtmZpYOmjRP/8gHHnCCch3Zz3oEgCdZVdtweU=
github.com/go-toolsmith/astp v0.0.0-20180903215135-0af7e3c24f30/go.mod h1:SV2ur98SGypH1UjcPpCatrV5hPazG6+IfNHbkDXBRrk=
github.com/go-toolsmith/astp v1.0.0 h1:alXE75TXgcmupDsMK1fRAy0YUzLzqPVvBKoyWV+KPXg=
github.com/go-toolsmith/astp v1.0.0/go.mod h1:RSyrtpVlfTFGDYRbrjyWP1pYu//tSFcvdYrA8meBmLI=
github.com/go-toolsmith/pkgload v0.0.0-20181119091011-e9e65178eee8/go.mod h1:WoMrjiy4zvdS+Bg6z9jZH82QXwkcgCBX6nOfnmdaHks=
github.com/go-toolsmith/pkgload v1.0.0 h1:4DFWWMXVfbcN5So1sBNW9+yeiMqLFGl1wFLTL5R0Tgg=
github.com/go-toolsmith/pkgload v1.0.0/go.mod h1:5eFArkbO80v7Z0kdngIxsRXRMTaX4Ilcwuh3clNrQJc=
github.com/go-toolsmith/strparse v1.0.0 h1:Vcw78DnpCAKlM20kSbAyO4mPfJn/lyYA4BJUDxe2Jb4=
github.com/go-toolsmith/strparse v1.0.0/go.mod h1:YI2nUKP9YGZnL/L1/DLFBfixrcjslWct4wyljWhSRy8=
github.com/go-toolsmith/typep v1.0.0/go.mod h1:JSQCQMUPdRlMZFswiq3TGpNp1GMktqkR2Ns5AIQkATU=
github.com/go-toolsmith/typep v1.0.2 h1:8xdsa1+FSIH/RhEkgnD1j2CJOy5mNllW1Q9tRiYwvlk=
github.com/go-toolsmith/typep v1.0.2/go.mod h1:JSQCQMUPdRlMZFswiq3TGpNp1GMktqkR2Ns5AIQkATU=
github.com/google/go-cmp v0.2.0 h1:+dTQ8DZQJz0Mb/HjFlkptS1FeQ4cWSnN941F8aEG4SQ=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.5.1 h1:JFrFEBb2xKufg6XkJsJr+WbKb4FQlURi5RUcBveYu9k=
github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY=
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/gorilla/mux v1.7.4 h1:VuZ8uybHlWmqV03+zRzdwKL4tUnIp1MAQtp1mIFE1bc=
github.com/gorilla/mux v1.7.4/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
github.com/kisielk/gotool v1.0.0 h1:AV2c/EiW3KqPNT9ZKl07ehoAGi4C5/01Cfbblndcapg=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/logrusorgru/aurora v0.0.0-20181002194514-a7b3b318ed4e h1:9MlwzLdW7QSDrhDjFlsEYmxpFyIoXmYRon3dt0io31k=
github.com/logrusorgru/aurora v0.0.0-20181002194514-a7b3b318ed4e/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4=
github.com/logrusorgru/aurora v2.0.3+incompatible h1:tOpm7WcpBTn4fjmVfgpQq0EfczGlG91VSDkswnjF5A8=
github.com/logrusorgru/aurora v2.0.3+incompatible/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4=
github.com/mattn/goveralls v0.0.2 h1:7eJB6EqsPhRVxvwEXGnqdO2sJI0PTsrWoTMXEk9/OQc=
github.com/mattn/goveralls v0.0.2/go.mod h1:8d1ZMHsd7fW6IRPKQh46F2WRpyib5/X4FOpevwGNQEw=
github.com/mattn/goveralls v0.0.6 h1:cr8Y0VMo/MnEZBjxNN/vh6G90SZ7IMb6lms1dzMoO+Y=
github.com/mattn/goveralls v0.0.6/go.mod h1:h8b4ow6FxSPMQHF6o2ve3qsclnffZjYTNEKmLesRwqw=
github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k=
github.com/google/uuid v1.2.0 h1:qJYtXnJRWmpe7m/3XlyhrsLrEURqHRM2kxzoxXqyUDs=
github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI=
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/quasilyte/go-consistent v0.0.0-20190521200055-c6f3937de18c h1:JoUA0uz9U0FVFq5p4LjEq4C0VgQ0El320s3Ms0V4eww=
github.com/quasilyte/go-consistent v0.0.0-20190521200055-c6f3937de18c/go.mod h1:5STLWrekHfjyYwxBRVRXNOSewLJ3PWfDJd1VyTS21fI=
github.com/quasilyte/go-consistent v0.0.0-20200404105227-766526bf1e96 h1:6VBkISnfYpPtRvpE9wsVoxX+i0cDQFBPQPYzw259xWY=
github.com/quasilyte/go-consistent v0.0.0-20200404105227-766526bf1e96/go.mod h1:h5ob45vcE3sydtmo0lUDUmG3Y0HXudxMId1w+5G99VI=
github.com/quasilyte/go-ruleguard v0.1.2-0.20200318202121-b00d7a75d3d8 h1:DvnesvLtRPQOvaUbfXfh0tpMHg29by0H7F2U+QIkSu8=
github.com/quasilyte/go-ruleguard v0.1.2-0.20200318202121-b00d7a75d3d8/go.mod h1:CGFX09Ci3pq9QZdj86B+VGIdNj4VyCo2iPOGS9esB/k=
github.com/quasilyte/go-ruleguard v0.1.3 h1:6BU9UaNiSbTRYriG0PTZACIMi1dLHzIWWseSpX4icNM=
github.com/quasilyte/go-ruleguard v0.1.3/go.mod h1:CGFX09Ci3pq9QZdj86B+VGIdNj4VyCo2iPOGS9esB/k=
github.com/quasilyte/regex/syntax v0.0.0-20200407221936-30656e2c4a95 h1:L8QM9bvf68pVdQ3bCFZMDmnt9yqcMBro1pC7F+IPYMY=
github.com/quasilyte/regex/syntax v0.0.0-20200407221936-30656e2c4a95/go.mod h1:rlzQ04UMyJXu/aOvhd8qT+hvDrFpiwqp8MRXDY9szc0=
github.com/quasilyte/regex/syntax v0.0.0-20200419152657-af9db7f4a3ab h1:rjBjlam2Bbr6Dwp0T8HY2paibXTjMsNQU7vUH8hB+C4=
github.com/quasilyte/regex/syntax v0.0.0-20200419152657-af9db7f4a3ab/go.mod h1:rlzQ04UMyJXu/aOvhd8qT+hvDrFpiwqp8MRXDY9szc0=
github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/tools v0.0.0-20181117154741-2ddaf7f79a09/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190110163146-51295c7ec13a/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190521203540-521d6ed310dd h1:7E3PabyysDSEjnaANKBgums/hyvMI/HoHQ50qZEzTrg=
golang.org/x/tools v0.0.0-20190521203540-521d6ed310dd/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20200329025819-fd4102a86c65/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8=
golang.org/x/tools v0.0.0-20200522201501-cb1345f3a375/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200728190822-edd3c8e9e279 h1:VUQjqirfpXJk5i+LtIdDjCAqYrCqTarkUCmMVLqMmVQ=
golang.org/x/tools v0.0.0-20200728190822-edd3c8e9e279/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

View File

@ -1,7 +1,9 @@
// Package groupme defines a client capable of executing API commands for the GroupMe chat service
package groupme
import (
"bytes"
"context"
"encoding/json"
"errors"
"fmt"
@ -11,7 +13,7 @@ import (
// GroupMe documentation: https://dev.groupme.com/docs/v3#groups
////////// Endpoints //////////
/*//////// Endpoints ////////*/
const (
// Used to build other endpoints
groupsEndpointRoot = "/groups"
@ -29,7 +31,7 @@ const (
changeGroupOwnerEndpoint = groupsEndpointRoot + "/change_owners" // POST
)
////////// Common Request Parameters //////////
/*//////// Common Request Parameters ////////*/
// GroupSettings is the settings for a group, used by CreateGroup and UpdateGroup
type GroupSettings struct {
@ -51,9 +53,9 @@ func (gss GroupSettings) String() string {
return marshal(&gss)
}
////////// API Requests //////////
/*//////// API Requests ////////*/
///// Index /////
/*/// Index ///*/
// GroupsQuery defines optional URL parameters for IndexGroups
type GroupsQuery struct {
@ -84,7 +86,7 @@ app for users who are participating in huge groups.
Parameters: See GroupsQuery
*/
func (c *Client) IndexGroups(req *GroupsQuery) ([]*Group, error) {
func (c *Client) IndexGroups(ctx context.Context, req *GroupsQuery) ([]*Group, error) {
httpReq, err := http.NewRequest("GET", c.endpointBase+indexGroupsEndpoint, nil)
if err != nil {
return nil, err
@ -106,7 +108,7 @@ func (c *Client) IndexGroups(req *GroupsQuery) ([]*Group, error) {
URL.RawQuery = query.Encode()
var resp []*Group
err = c.doWithAuthToken(httpReq, &resp)
err = c.doWithAuthToken(ctx, httpReq, &resp)
if err != nil {
return nil, err
}
@ -114,21 +116,21 @@ func (c *Client) IndexGroups(req *GroupsQuery) ([]*Group, error) {
return resp, nil
}
///// Former /////
/*/// Former ///*/
/*
FormerGroups -
List they groups you have left but can rejoin.
*/
func (c *Client) FormerGroups() ([]*Group, error) {
func (c *Client) FormerGroups(ctx context.Context) ([]*Group, error) {
httpReq, err := http.NewRequest("GET", c.endpointBase+formerGroupsEndpoint, nil)
if err != nil {
return nil, err
}
var resp []*Group
err = c.doWithAuthToken(httpReq, &resp)
err = c.doWithAuthToken(ctx, httpReq, &resp)
if err != nil {
return nil, err
}
@ -136,7 +138,7 @@ func (c *Client) FormerGroups() ([]*Group, error) {
return resp, nil
}
///// Show /////
/*/// Show ///*/
/*
ShowGroup -
@ -146,7 +148,7 @@ Loads a specific group.
Parameters:
groupID - required, ID(string)
*/
func (c *Client) ShowGroup(groupID ID) (*Group, error) {
func (c *Client) ShowGroup(ctx context.Context, groupID ID) (*Group, error) {
URL := fmt.Sprintf(c.endpointBase+showGroupEndpoint, groupID)
httpReq, err := http.NewRequest("GET", URL, nil)
@ -155,7 +157,7 @@ func (c *Client) ShowGroup(groupID ID) (*Group, error) {
}
var resp Group
err = c.doWithAuthToken(httpReq, &resp)
err = c.doWithAuthToken(ctx, httpReq, &resp)
if err != nil {
return nil, err
}
@ -163,7 +165,7 @@ func (c *Client) ShowGroup(groupID ID) (*Group, error) {
return &resp, nil
}
///// Create /////
/*/// Create ///*/
/*
CreateGroup -
@ -172,7 +174,7 @@ Create a new group
Parameters: See GroupSettings
*/
func (c *Client) CreateGroup(gs GroupSettings) (*Group, error) {
func (c *Client) CreateGroup(ctx context.Context, gs GroupSettings) (*Group, error) {
URL := fmt.Sprintf(c.endpointBase + createGroupEndpoint)
jsonBytes, err := json.Marshal(&gs)
@ -186,7 +188,7 @@ func (c *Client) CreateGroup(gs GroupSettings) (*Group, error) {
}
var resp Group
err = c.doWithAuthToken(httpReq, &resp)
err = c.doWithAuthToken(ctx, httpReq, &resp)
if err != nil {
return nil, err
}
@ -194,7 +196,7 @@ func (c *Client) CreateGroup(gs GroupSettings) (*Group, error) {
return &resp, nil
}
///// Update /////
/*/// Update ///*/
/*
UpdateGroup -
@ -205,7 +207,7 @@ Parameters:
groupID - required, ID(string)
See GroupSettings
*/
func (c *Client) UpdateGroup(groupID ID, gs GroupSettings) (*Group, error) {
func (c *Client) UpdateGroup(ctx context.Context, groupID ID, gs GroupSettings) (*Group, error) {
URL := fmt.Sprintf(c.endpointBase+updateGroupEndpoint, groupID)
jsonBytes, err := json.Marshal(&gs)
@ -219,7 +221,7 @@ func (c *Client) UpdateGroup(groupID ID, gs GroupSettings) (*Group, error) {
}
var resp Group
err = c.doWithAuthToken(httpReq, &resp)
err = c.doWithAuthToken(ctx, httpReq, &resp)
if err != nil {
return nil, err
}
@ -227,7 +229,7 @@ func (c *Client) UpdateGroup(groupID ID, gs GroupSettings) (*Group, error) {
return &resp, nil
}
///// Destroy /////
/*/// Destroy ///*/
/*
DestroyGroup -
@ -239,7 +241,7 @@ This action is only available to the group creator
Parameters:
groupID - required, ID(string)
*/
func (c *Client) DestroyGroup(groupID ID) error {
func (c *Client) DestroyGroup(ctx context.Context, groupID ID) error {
url := fmt.Sprintf(c.endpointBase+destroyGroupEndpoint, groupID)
httpReq, err := http.NewRequest("POST", url, nil)
@ -247,10 +249,10 @@ func (c *Client) DestroyGroup(groupID ID) error {
return err
}
return c.doWithAuthToken(httpReq, nil)
return c.doWithAuthToken(ctx, httpReq, nil)
}
///// Join /////
/*/// Join ///*/
/*
JoinGroup -
@ -261,7 +263,7 @@ Parameters:
groupID - required, ID(string)
shareToken - required, string
*/
func (c *Client) JoinGroup(groupID ID, shareToken string) (*Group, error) {
func (c *Client) JoinGroup(ctx context.Context, groupID ID, shareToken string) (*Group, error) {
URL := fmt.Sprintf(c.endpointBase+joinGroupEndpoint, groupID, shareToken)
httpReq, err := http.NewRequest("POST", URL, nil)
@ -270,7 +272,7 @@ func (c *Client) JoinGroup(groupID ID, shareToken string) (*Group, error) {
}
var resp Group
err = c.doWithAuthToken(httpReq, &resp)
err = c.doWithAuthToken(ctx, httpReq, &resp)
if err != nil {
return nil, err
}
@ -278,7 +280,7 @@ func (c *Client) JoinGroup(groupID ID, shareToken string) (*Group, error) {
return &resp, nil
}
///// Rejoin /////
/*/// Rejoin ///*/
/*
RejoinGroup -
@ -288,7 +290,7 @@ Rejoin a group. Only works if you previously removed yourself.
Parameters:
groupID - required, ID(string)
*/
func (c *Client) RejoinGroup(groupID ID) (*Group, error) {
func (c *Client) RejoinGroup(ctx context.Context, groupID ID) (*Group, error) {
URL := fmt.Sprintf(c.endpointBase + rejoinGroupEndpoint)
var data = struct {
@ -308,7 +310,7 @@ func (c *Client) RejoinGroup(groupID ID) (*Group, error) {
}
var resp Group
err = c.doWithAuthToken(httpReq, &resp)
err = c.doWithAuthToken(ctx, httpReq, &resp)
if err != nil {
return nil, err
}
@ -316,12 +318,10 @@ func (c *Client) RejoinGroup(groupID ID) (*Group, error) {
return &resp, nil
}
///// Change Owner /////
/*/// Change Owner ///*/
/*
ChangeGroupOwner-
Change owner of requested groups.
ChangeGroupOwner - Change owner of requested groups.
This action is only available to the group creator.
@ -330,7 +330,7 @@ the result of change owner action for the request
Parameters: See ChangeOwnerRequest
*/
func (c *Client) ChangeGroupOwner(reqs ChangeOwnerRequest) (ChangeOwnerResult, error) {
func (c *Client) ChangeGroupOwner(ctx context.Context, reqs ChangeOwnerRequest) (ChangeOwnerResult, error) {
URL := fmt.Sprintf(c.endpointBase + changeGroupOwnerEndpoint)
var data = struct {
@ -353,7 +353,7 @@ func (c *Client) ChangeGroupOwner(reqs ChangeOwnerRequest) (ChangeOwnerResult, e
Results []ChangeOwnerResult `json:"results"`
}
err = c.doWithAuthToken(httpReq, &resp)
err = c.doWithAuthToken(ctx, httpReq, &resp)
if err != nil {
return ChangeOwnerResult{}, err
}
@ -365,24 +365,25 @@ func (c *Client) ChangeGroupOwner(reqs ChangeOwnerRequest) (ChangeOwnerResult, e
return resp.Results[0], nil
}
type ChangeOwnerStatusCode string
type changeOwnerStatusCode string
// Change owner Status Codes
const (
ChangeOwner_Ok ChangeOwnerStatusCode = "200"
ChangeOwner_RequesterNewOwner ChangeOwnerStatusCode = "400"
ChangeOwner_NotOwner ChangeOwnerStatusCode = "403"
ChangeOwner_BadGroupOrOwner ChangeOwnerStatusCode = "404"
ChangeOwner_BadRequest ChangeOwnerStatusCode = "405"
ChangeOwnerOk changeOwnerStatusCode = "200"
ChangeOwnerRequesterNewOwner changeOwnerStatusCode = "400"
ChangeOwnerNotOwner changeOwnerStatusCode = "403"
ChangeOwnerBadGroupOrOwner changeOwnerStatusCode = "404"
ChangeOwnerBadRequest changeOwnerStatusCode = "405"
)
// String returns the description of the status code according to GroupMe
func (c ChangeOwnerStatusCode) String() string {
return map[ChangeOwnerStatusCode]string{
ChangeOwner_Ok: "success",
ChangeOwner_RequesterNewOwner: "requester is also a new owner",
ChangeOwner_NotOwner: "requester is not the owner of the group",
ChangeOwner_BadGroupOrOwner: "group or new owner not found or new owner is not memeber of the group",
ChangeOwner_BadRequest: "request object is missing required field or any of the required fields is not an ID",
func (c changeOwnerStatusCode) String() string {
return map[changeOwnerStatusCode]string{
ChangeOwnerOk: "success",
ChangeOwnerRequesterNewOwner: "requester is also a new owner",
ChangeOwnerNotOwner: "requester is not the owner of the group",
ChangeOwnerBadGroupOrOwner: "group or new owner not found or new owner is not member of the group",
ChangeOwnerBadRequest: "request object is missing required field or any of the required fields is not an ID",
}[c]
}
@ -405,7 +406,7 @@ type ChangeOwnerResult struct {
// UserId of the new owner of the group who is
// an active member of the group
OwnerID string `json:"owner_id"`
Status ChangeOwnerStatusCode `json:"status"`
Status changeOwnerStatusCode `json:"status"`
}
func (r ChangeOwnerResult) String() string {

View File

@ -1,6 +1,8 @@
// Package groupme defines a client capable of executing API commands for the GroupMe chat service
package groupme
import (
"context"
"fmt"
"net/http"
"testing"
@ -17,11 +19,14 @@ func (s *GroupsAPISuite) SetupSuite() {
}
func (s *GroupsAPISuite) TestGroupsIndex() {
groups, err := s.client.IndexGroups(&GroupsQuery{
Page: 5,
PerPage: 20,
Omit: "memberships",
})
groups, err := s.client.IndexGroups(
context.Background(),
&GroupsQuery{
Page: 5,
PerPage: 20,
Omit: "memberships",
},
)
s.Require().NoError(err)
s.Require().NotZero(groups)
for _, group := range groups {
@ -30,7 +35,7 @@ func (s *GroupsAPISuite) TestGroupsIndex() {
}
func (s *GroupsAPISuite) TestGroupsFormer() {
groups, err := s.client.FormerGroups()
groups, err := s.client.FormerGroups(context.Background())
s.Require().NoError(err)
s.Require().NotZero(groups)
for _, group := range groups {
@ -39,25 +44,28 @@ func (s *GroupsAPISuite) TestGroupsFormer() {
}
func (s *GroupsAPISuite) TestGroupsShow() {
group, err := s.client.ShowGroup("1")
group, err := s.client.ShowGroup(context.Background(), "1")
s.Require().NoError(err)
s.Assert().NotZero(group)
}
func (s *GroupsAPISuite) TestGroupsCreate() {
group, err := s.client.CreateGroup(GroupSettings{
"Test",
"This is a test group",
"www.blank.com/image",
false,
true,
})
group, err := s.client.CreateGroup(
context.Background(),
GroupSettings{
"Test",
"This is a test group",
"www.blank.com/image",
false,
true,
},
)
s.Require().NoError(err)
s.Assert().NotZero(group)
}
func (s *GroupsAPISuite) TestGroupsUpdate() {
group, err := s.client.UpdateGroup("1", GroupSettings{
group, err := s.client.UpdateGroup(context.Background(), "1", GroupSettings{
"Test",
"This is a test group",
"www.blank.com/image",
@ -69,24 +77,25 @@ func (s *GroupsAPISuite) TestGroupsUpdate() {
}
func (s *GroupsAPISuite) TestGroupsDestroy() {
err := s.client.DestroyGroup("1")
err := s.client.DestroyGroup(context.Background(), "1")
s.Require().NoError(err)
}
func (s *GroupsAPISuite) TestGroupsJoin() {
group, err := s.client.JoinGroup("1", "please")
group, err := s.client.JoinGroup(context.Background(), "1", "please")
s.Require().NoError(err)
s.Assert().NotZero(group)
}
func (s *GroupsAPISuite) TestGroupsRejoin() {
group, err := s.client.RejoinGroup("1")
group, err := s.client.RejoinGroup(context.Background(), "1")
s.Require().NoError(err)
s.Assert().NotZero(group)
}
func (s *GroupsAPISuite) TestGroupsChangeOwner() {
result, err := s.client.ChangeGroupOwner(
context.Background(),
ChangeOwnerRequest{
"1",
"123",
@ -99,8 +108,9 @@ func TestGroupsAPISuite(t *testing.T) {
suite.Run(t, new(GroupsAPISuite))
}
////////// Test Groups Router //////////
/*//////// Test Groups Router ////////*/
// nolint // not duplicate code
func groupsTestRouter() *mux.Router {
router := mux.NewRouter().Queries("token", "").Subrouter()

57
json.go
View File

@ -1,3 +1,4 @@
// Package groupme defines a client capable of executing API commands for the GroupMe chat service
package groupme
import (
@ -53,7 +54,7 @@ type MessagePreview struct {
// GetMemberByUserID gets the group member by their UserID,
// nil if no member matches
func (g Group) GetMemberByUserID(userID ID) *Member {
func (g *Group) GetMemberByUserID(userID ID) *Member {
for _, member := range g.Members {
if member.UserID == userID {
return member
@ -65,7 +66,7 @@ func (g Group) GetMemberByUserID(userID ID) *Member {
// GetMemberByNickname gets the group member by their Nickname,
// nil if no member matches
func (g Group) GetMemberByNickname(nickname string) *Member {
func (g *Group) GetMemberByNickname(nickname string) *Member {
for _, member := range g.Members {
if member.Nickname == nickname {
return member
@ -75,8 +76,8 @@ func (g Group) GetMemberByNickname(nickname string) *Member {
return nil
}
func (g Group) String() string {
return marshal(&g)
func (g *Group) String() string {
return marshal(g)
}
// Member is a GroupMe group member, returned in JSON API responses
@ -93,8 +94,8 @@ type Member struct {
Email string `json:"email,omitempty"` // Only used when searching for the member to add to a group.
}
func (m Member) String() string {
return marshal(&m)
func (m *Member) String() string {
return marshal(m)
}
// Message is a GroupMe group message, returned in JSON API responses
@ -106,7 +107,7 @@ type Message struct {
UserID ID `json:"user_id,omitempty"`
BotID ID `json:"bot_id,omitempty"`
SenderID ID `json:"sender_id,omitempty"`
SenderType SenderType `json:"sender_type,omitempty"`
SenderType senderType `json:"sender_type,omitempty"`
System bool `json:"system,omitempty"`
Name string `json:"name,omitempty"`
RecipientID ID `json:"recipient_id,omitempty"`
@ -120,32 +121,32 @@ type Message struct {
Attachments []*Attachment `json:"attachments,omitempty"`
}
func (m Message) String() string {
return marshal(&m)
func (m *Message) String() string {
return marshal(m)
}
type SenderType string
type senderType string
// SenderType constants
const (
SenderType_User SenderType = "user"
SenderType_Bot SenderType = "bot"
SenderType_System SenderType = "system"
SenderTypeUser senderType = "user"
SenderTypeBot senderType = "bot"
SenderTypeSystem senderType = "system"
)
type AttachmentType string
type attachmentType string
// AttachmentType constants
const (
Mentions AttachmentType = "mentions"
Image AttachmentType = "image"
Location AttachmentType = "location"
Emoji AttachmentType = "emoji"
Mentions attachmentType = "mentions"
Image attachmentType = "image"
Location attachmentType = "location"
Emoji attachmentType = "emoji"
)
// Attachment is a GroupMe message attachment, returned in JSON API responses
type Attachment struct {
Type AttachmentType `json:"type,omitempty"`
Type attachmentType `json:"type,omitempty"`
Loci [][]int `json:"loci,omitempty"`
UserIDs []ID `json:"user_ids,omitempty"`
URL string `json:"url,omitempty"`
@ -156,8 +157,8 @@ type Attachment struct {
Charmap [][]int `json:"charmap,omitempty"`
}
func (a Attachment) String() string {
return marshal(&a)
func (a *Attachment) String() string {
return marshal(a)
}
// User is a GroupMe user, returned in JSON API responses
@ -173,8 +174,8 @@ type User struct {
SMS bool `json:"sms,omitempty"`
}
func (u User) String() string {
return marshal(&u)
func (u *User) String() string {
return marshal(u)
}
// Chat is a GroupMe direct message conversation between two users,
@ -187,10 +188,11 @@ type Chat struct {
OtherUser User `json:"other_user,omitempty"`
}
func (c Chat) String() string {
return marshal(&c)
func (c *Chat) String() string {
return marshal(c)
}
// Bot is a GroupMe bot, it is connected to a specific group which it can send messages to
type Bot struct {
BotID ID `json:"bot_id,omitempty"`
GroupID ID `json:"group_id,omitempty"`
@ -200,10 +202,11 @@ type Bot struct {
DMNotification bool `json:"dm_notification,omitempty"`
}
func (b Bot) String() string {
return marshal(&b)
func (b *Bot) String() string {
return marshal(b)
}
// Block is a GroupMe block between two users, direct messages are not allowed
type Block struct {
UserID ID `json:"user_id,omitempty"`
BlockedUserID ID `json:"blocked_user_id,omitempty"`

View File

@ -1,3 +1,4 @@
// Package groupme defines a client capable of executing API commands for the GroupMe chat service
package groupme
import (

View File

@ -1,13 +1,15 @@
// Package groupme defines a client capable of executing API commands for the GroupMe chat service
package groupme
import (
"context"
"fmt"
"net/http"
)
// GroupMe documentation: https://dev.groupme.com/docs/v3#leaderboard
////////// Endpoints //////////
/*//////// Endpoints ////////*/
const (
// Used to build other endpoints
leaderboardEndpointRoot = groupEndpointRoot + "/likes"
@ -18,34 +20,22 @@ const (
myHitsLeaderboardEndpoint = leaderboardEndpointRoot + "/for_me" // GET
)
////////// API Requests //////////
/*//////// API Requests ////////*/
// Index
type period string
func (p period) String() string {
return string(p)
}
// Define acceptable period values
const (
Period_Day = "day"
Period_Week = "week"
Period_Month = "month"
PeriodDay = "day"
PeriodWeek = "week"
PeriodMonth = "month"
)
/*
IndexLeaderboard -
A list of the liked messages in the group for a given period of
time. Messages are ranked in order of number of likes.
Parameters:
groupID - required, ID(string)
p - required, period(string)
*/
func (c *Client) IndexLeaderboard(groupID ID, p period) ([]*Message, error) {
// IndexLeaderboard - A list of the liked messages in the group for a given period of
// time. Messages are ranked in order of number of likes.
func (c *Client) IndexLeaderboard(ctx context.Context, groupID ID, p period) ([]*Message, error) {
url := fmt.Sprintf(c.endpointBase+indexLeaderboardEndpoint, groupID)
httpReq, err := http.NewRequest("GET", url, nil)
if err != nil {
@ -54,13 +44,13 @@ func (c *Client) IndexLeaderboard(groupID ID, p period) ([]*Message, error) {
URL := httpReq.URL
query := URL.Query()
query.Set("period", p.String())
query.Set("period", string(p))
URL.RawQuery = query.Encode()
var resp struct {
Messages []*Message `json:"messages"`
}
err = c.doWithAuthToken(httpReq, &resp)
err = c.doWithAuthToken(ctx, httpReq, &resp)
if err != nil {
return nil, err
}
@ -80,7 +70,7 @@ timestamp in ISO-8601 format.
Parameters:
groupID - required, ID(string)
*/
func (c *Client) MyLikesLeaderboard(groupID ID) ([]*Message, error) {
func (c *Client) MyLikesLeaderboard(ctx context.Context, groupID ID) ([]*Message, error) {
url := fmt.Sprintf(c.endpointBase+myLikesLeaderboardEndpoint, groupID)
httpReq, err := http.NewRequest("GET", url, nil)
if err != nil {
@ -90,7 +80,7 @@ func (c *Client) MyLikesLeaderboard(groupID ID) ([]*Message, error) {
var resp struct {
Messages []*Message `json:"messages"`
}
err = c.doWithAuthToken(httpReq, &resp)
err = c.doWithAuthToken(ctx, httpReq, &resp)
if err != nil {
return nil, err
}
@ -110,7 +100,7 @@ timestamp in ISO-8601 format.
Parameters:
groupID - required, ID(string)
*/
func (c *Client) MyHitsLeaderboard(groupID ID) ([]*Message, error) {
func (c *Client) MyHitsLeaderboard(ctx context.Context, groupID ID) ([]*Message, error) {
url := fmt.Sprintf(c.endpointBase+myHitsLeaderboardEndpoint, groupID)
httpReq, err := http.NewRequest("GET", url, nil)
if err != nil {
@ -120,7 +110,7 @@ func (c *Client) MyHitsLeaderboard(groupID ID) ([]*Message, error) {
var resp struct {
Messages []*Message `json:"messages"`
}
err = c.doWithAuthToken(httpReq, &resp)
err = c.doWithAuthToken(ctx, httpReq, &resp)
if err != nil {
return nil, err
}

View File

@ -1,6 +1,8 @@
// Package groupme defines a client capable of executing API commands for the GroupMe chat service
package groupme
import (
"context"
"fmt"
"net/http"
"testing"
@ -17,7 +19,7 @@ func (s *LeaderboardAPISuite) SetupSuite() {
}
func (s *LeaderboardAPISuite) TestLeaderboardIndex() {
messages, err := s.client.IndexLeaderboard("1", Period_Day)
messages, err := s.client.IndexLeaderboard(context.Background(), "1", PeriodDay)
s.Require().NoError(err)
s.Require().NotZero(messages)
for _, message := range messages {
@ -26,7 +28,7 @@ func (s *LeaderboardAPISuite) TestLeaderboardIndex() {
}
func (s *LeaderboardAPISuite) TestLeaderboardMyLikes() {
messages, err := s.client.MyLikesLeaderboard("1")
messages, err := s.client.MyLikesLeaderboard(context.Background(), "1")
s.Require().NoError(err)
s.Require().NotZero(messages)
for _, message := range messages {
@ -35,7 +37,7 @@ func (s *LeaderboardAPISuite) TestLeaderboardMyLikes() {
}
func (s *LeaderboardAPISuite) TestLeaderboardMyHits() {
messages, err := s.client.MyHitsLeaderboard("1")
messages, err := s.client.MyHitsLeaderboard(context.Background(), "1")
s.Require().NoError(err)
s.Require().NotZero(messages)
for _, message := range messages {
@ -47,6 +49,7 @@ func TestLeaderboardAPISuite(t *testing.T) {
suite.Run(t, new(LeaderboardAPISuite))
}
// nolint // not duplicate code
func leaderboardTestRouter() *mux.Router {
router := mux.NewRouter().Queries("token", "").Subrouter()

View File

@ -1,13 +1,15 @@
// Package groupme defines a client capable of executing API commands for the GroupMe chat service
package groupme
import (
"context"
"fmt"
"net/http"
)
// GroupMe documentation: https://dev.groupme.com/docs/v3#likes
////////// Endpoints //////////
/*//////// Endpoints ////////*/
const (
// Used to build other endpoints
likesEndpointRoot = "/messages/%s/%s"
@ -16,20 +18,12 @@ const (
destroyLikeEndpoint = likesEndpointRoot + "/unlike" // POST
)
////////// API Requests /////////
/*//////// API Requests ////////*/
// Create
/*
CreateLike -
Like a message.
Parameters:
conversationID - required, ID(string)
messageID - required, ID(string)
*/
func (c *Client) CreateLike(conversationID, messageID ID) error {
// CreateLike - Like a message.
func (c *Client) CreateLike(ctx context.Context, conversationID, messageID ID) error {
url := fmt.Sprintf(c.endpointBase+createLikeEndpoint, conversationID, messageID)
httpReq, err := http.NewRequest("POST", url, nil)
@ -37,21 +31,11 @@ func (c *Client) CreateLike(conversationID, messageID ID) error {
return err
}
return c.doWithAuthToken(httpReq, nil)
return c.doWithAuthToken(ctx, httpReq, nil)
}
// Destroy
/*
DestroyLike -
Unlike a message.
Parameters:
conversationID - required, ID(string)
messageID - required, ID(string)
*/
func (c *Client) DestroyLike(conversationID, messageID ID) error {
// DestroyLike - Unlike a message.
func (c *Client) DestroyLike(ctx context.Context, conversationID, messageID ID) error {
url := fmt.Sprintf(c.endpointBase+destroyLikeEndpoint, conversationID, messageID)
httpReq, err := http.NewRequest("POST", url, nil)
@ -59,5 +43,5 @@ func (c *Client) DestroyLike(conversationID, messageID ID) error {
return err
}
return c.doWithAuthToken(httpReq, nil)
return c.doWithAuthToken(ctx, httpReq, nil)
}

View File

@ -1,6 +1,8 @@
// Package groupme defines a client capable of executing API commands for the GroupMe chat service
package groupme
import (
"context"
"net/http"
"testing"
@ -16,18 +18,20 @@ func (s *LikesAPISuite) SetupSuite() {
}
func (s *LikesAPISuite) TestLikesCreate() {
err := s.client.CreateLike("1", "1")
err := s.client.CreateLike(context.Background(), "1", "1")
s.Require().NoError(err)
}
func (s *LikesAPISuite) TestLikesDestroy() {
err := s.client.DestroyLike("1", "1")
err := s.client.DestroyLike(context.Background(), "1", "1")
s.Require().NoError(err)
}
func TestLikesAPISuite(t *testing.T) {
suite.Run(t, new(LikesAPISuite))
}
// nolint // not duplicate code
func likesTestRouter() *mux.Router {
router := mux.NewRouter().Queries("token", "").Subrouter()

View File

@ -1,3 +1,4 @@
// Package groupme defines a client capable of executing API commands for the GroupMe chat service
package groupme
import (
@ -14,7 +15,7 @@ import (
"github.com/stretchr/testify/suite"
)
////////// Base API Suite //////////
/*//////// Base API Suite ////////*/
type APISuite struct {
// Base attributes
suite.Suite
@ -22,7 +23,7 @@ type APISuite struct {
server *http.Server
wg sync.WaitGroup
// Overriden by child Suite
// Overridden by child Suite
addr string
handler http.Handler
}
@ -42,7 +43,7 @@ func (s *APISuite) TearDownSuite() {
s.wg.Wait()
}
///// Start Server /////
/*/// Start Server ///*/
func (s *APISuite) startServer(addr string, handler http.Handler) *http.Server {
server := &http.Server{
Addr: addr,
@ -60,6 +61,7 @@ func (s *APISuite) startServer(addr string, handler http.Handler) *http.Server {
// Wait until server has started listening
url := fmt.Sprintf("http://%s", addr)
// nolint // url is meant to be variable
for _, err := http.Get(url); err != nil; _, err = http.Get(url) {
continue
}
@ -67,7 +69,7 @@ func (s *APISuite) startServer(addr string, handler http.Handler) *http.Server {
return server
}
///// Generate Ephemeral Port /////
/*/// Generate Ephemeral Port ///*/
const (
portMin = 49152
portMax = 65535
@ -76,10 +78,11 @@ const (
func (s *APISuite) generatePort() string {
rand.Seed(time.Now().UnixNano())
// nolint // weak random generator is ok for creating port number in a test
return strconv.Itoa((rand.Intn(portRange) + portMin))
}
////////// Test Main //////////
/*//////// Test Main ////////*/
func TestMain(m *testing.M) {
os.Exit(m.Run())
}

View File

@ -1,7 +1,9 @@
// Package groupme defines a client capable of executing API commands for the GroupMe chat service
package groupme
import (
"bytes"
"context"
"encoding/json"
"fmt"
"net/http"
@ -9,7 +11,7 @@ import (
// GroupMe documentation: https://dev.groupme.com/docs/v3#members
////////// Endpoints //////////
/*//////// Endpoints ////////*/
const (
// Used to build other endpoints
membersEndpointRoot = groupEndpointRoot + "/members"
@ -21,7 +23,7 @@ const (
updateMemberEndpoint = groupEndpointRoot + "/memberships/update" // POST
)
///// Add /////
/*/// Add ///*/
/*
AddMembers -
@ -46,7 +48,7 @@ Parameters:
PhoneNumber - PhoneNumber(string)
Email - string
*/
func (c *Client) AddMembers(groupID ID, members ...*Member) (string, error) {
func (c *Client) AddMembers(ctx context.Context, groupID ID, members ...*Member) (string, error) {
URL := fmt.Sprintf(c.endpointBase+addMembersEndpoint, groupID)
var data = struct {
@ -69,7 +71,7 @@ func (c *Client) AddMembers(groupID ID, members ...*Member) (string, error) {
ResultsID string `json:"results_id"`
}
err = c.doWithAuthToken(httpReq, &resp)
err = c.doWithAuthToken(ctx, httpReq, &resp)
if err != nil {
return "", err
}
@ -77,7 +79,7 @@ func (c *Client) AddMembers(groupID ID, members ...*Member) (string, error) {
return resp.ResultsID, nil
}
///// Results /////
/*/// Results ///*/
/*
AddMembersResults -
@ -95,7 +97,7 @@ Parameters:
groupID - required, ID(string)
resultID - required, string
*/
func (c *Client) AddMembersResults(groupID ID, resultID string) ([]*Member, error) {
func (c *Client) AddMembersResults(ctx context.Context, groupID ID, resultID string) ([]*Member, error) {
URL := fmt.Sprintf(c.endpointBase+addMembersResultsEndpoint, groupID, resultID)
httpReq, err := http.NewRequest("GET", URL, nil)
@ -107,7 +109,7 @@ func (c *Client) AddMembersResults(groupID ID, resultID string) ([]*Member, erro
Members []*Member `json:"members"`
}
err = c.doWithAuthToken(httpReq, &resp)
err = c.doWithAuthToken(ctx, httpReq, &resp)
if err != nil {
return nil, err
}
@ -115,7 +117,7 @@ func (c *Client) AddMembersResults(groupID ID, resultID string) ([]*Member, erro
return resp.Members, nil
}
///// Remove /////
/*/// Remove ///*/
/*
RemoveMember -
@ -128,7 +130,7 @@ Parameters:
groupID - required, ID(string)
membershipID - required, ID(string). Not the same as userID
*/
func (c *Client) RemoveMember(groupID, membershipID ID) error {
func (c *Client) RemoveMember(ctx context.Context, groupID, membershipID ID) error {
URL := fmt.Sprintf(c.endpointBase+removeMemberEndpoint, groupID, membershipID)
httpReq, err := http.NewRequest("POST", URL, nil)
@ -136,10 +138,10 @@ func (c *Client) RemoveMember(groupID, membershipID ID) error {
return err
}
return c.doWithAuthToken(httpReq, nil)
return c.doWithAuthToken(ctx, httpReq, nil)
}
///// Update /////
/*/// Update ///*/
/*
UpdateMember -
@ -147,7 +149,7 @@ UpdateMember -
Update your nickname in a group. The nickname must be
between 1 and 50 characters.
*/
func (c *Client) UpdateMember(groupID ID, nickname string) (*Member, error) {
func (c *Client) UpdateMember(ctx context.Context, groupID ID, nickname string) (*Member, error) {
URL := fmt.Sprintf(c.endpointBase+updateMemberEndpoint, groupID)
type Nickname struct {
@ -171,7 +173,7 @@ func (c *Client) UpdateMember(groupID ID, nickname string) (*Member, error) {
var resp Member
err = c.doWithAuthToken(httpReq, &resp)
err = c.doWithAuthToken(ctx, httpReq, &resp)
if err != nil {
return nil, err
}

View File

@ -1,6 +1,8 @@
// Package groupme defines a client capable of executing API commands for the GroupMe chat service
package groupme
import (
"context"
"fmt"
"net/http"
"testing"
@ -18,6 +20,7 @@ func (s *MembersAPISuite) SetupSuite() {
func (s *MembersAPISuite) TestMembersAdd() {
_, err := s.client.AddMembers(
context.Background(),
"1",
&Member{Nickname: "test"},
)
@ -25,17 +28,17 @@ func (s *MembersAPISuite) TestMembersAdd() {
}
func (s *MembersAPISuite) TestMembersResults() {
_, err := s.client.AddMembersResults("1", "123")
_, err := s.client.AddMembersResults(context.Background(), "1", "123")
s.Require().NoError(err)
}
func (s *MembersAPISuite) TestMembersRemove() {
err := s.client.RemoveMember("1", "123")
err := s.client.RemoveMember(context.Background(), "1", "123")
s.Require().NoError(err)
}
func (s *MembersAPISuite) TestMembersUpdate() {
_, err := s.client.UpdateMember("1", "nickname")
_, err := s.client.UpdateMember(context.Background(), "1", "nickname")
s.Require().NoError(err)
}

View File

@ -1,7 +1,9 @@
// Package groupme defines a client capable of executing API commands for the GroupMe chat service
package groupme
import (
"bytes"
"context"
"encoding/json"
"fmt"
"net/http"
@ -12,7 +14,7 @@ import (
// GroupMe documentation: https://dev.groupme.com/docs/v3#messages
////////// Endpoints //////////
/*//////// Endpoints ////////*/
const (
// Used to build other endpoints
messagesEndpointRoot = groupEndpointRoot + "/messages"
@ -21,9 +23,7 @@ const (
createMessagesEndpoint = messagesEndpointRoot // POST
)
// Index
// MessagesQuery defines the optional URL parameters for IndexMessages
// IndexMessagesQuery defines the optional URL parameters for IndexMessages
type IndexMessagesQuery struct {
// Returns messages created before the given message ID
BeforeID ID
@ -39,7 +39,7 @@ func (q IndexMessagesQuery) String() string {
return marshal(&q)
}
// MessagesIndexResponse contains the count and set of
// IndexMessagesResponse contains the count and set of
// messages returned by the IndexMessages API request
type IndexMessagesResponse struct {
Count int `json:"count"`
@ -51,41 +51,31 @@ func (r IndexMessagesResponse) String() string {
}
/*
IndexMessages -
Retrieve messages for a group.
IndexMessages - Retrieves messages for a group.
By default, messages are returned in groups of 20, ordered by
created_at descending. This can be raised or lowered by passing
a limit parameter, up to a maximum of 100 messages.
Messages can be scanned by providing a message ID as either the
before_id, since_id, or after_id parameter. If before_id is
provided, then messages immediately preceding the given message
will be returned, in descending order. This can be used to
continually page back through a group's messages.
The after_id parameter will return messages that immediately
follow a given message, this time in ascending order (which
makes it easy to pick off the last result for continued
pagination).
Finally, the since_id parameter also returns messages created
after the given message, but it retrieves the most recent
messages. For example, if more than twenty messages are created
after the since_id message, using this parameter will omit the
messages that immediately follow the given message. This is a
bit counterintuitive, so take care.
If no messages are found (e.g. when filtering with before_id)
we return code 304.
Note that for historical reasons, likes are returned as an
array of user ids in the favorited_by key.
Parameters: See MessageQuery
*/
func (c *Client) IndexMessages(groupID ID, req *IndexMessagesQuery) (IndexMessagesResponse, error) {
func (c *Client) IndexMessages(ctx context.Context, groupID ID, req *IndexMessagesQuery) (IndexMessagesResponse, error) {
url := fmt.Sprintf(c.endpointBase+indexMessagesEndpoint, groupID)
httpReq, err := http.NewRequest("GET", url, nil)
if err != nil {
@ -111,7 +101,7 @@ func (c *Client) IndexMessages(groupID ID, req *IndexMessagesQuery) (IndexMessag
URL.RawQuery = query.Encode()
var resp IndexMessagesResponse
err = c.doWithAuthToken(httpReq, &resp)
err = c.doWithAuthToken(ctx, httpReq, &resp)
if err != nil {
return IndexMessagesResponse{}, err
}
@ -119,11 +109,8 @@ func (c *Client) IndexMessages(groupID ID, req *IndexMessagesQuery) (IndexMessag
return resp, nil
}
// Create
/*
CreateMessage -
Send a message to a group
CreateMessage - Send a message to a group
If you want to attach an image, you must first process it
through our image service.
@ -137,19 +124,8 @@ The character map is an array of arrays containing rune data
([[{pack_id,offset}],...]).
The placeholder should be a high-point/invisible UTF-8 character.
Parameters:
groupID - required, ID(String)
See Message.
text - required, string. Can be ommitted if at least one
attachment is present
attachments - a polymorphic list of attachments (locations,
images, etc). You may have You may have more than
one of any type of attachment, provided clients can
display it.
*/
func (c *Client) CreateMessage(groupID ID, m *Message) (*Message, error) {
func (c *Client) CreateMessage(ctx context.Context, groupID ID, m *Message) (*Message, error) {
URL := fmt.Sprintf(c.endpointBase+createMessagesEndpoint, groupID)
m.SourceGUID = uuid.New().String()
@ -172,7 +148,7 @@ func (c *Client) CreateMessage(groupID ID, m *Message) (*Message, error) {
var resp struct {
*Message `json:"message"`
}
err = c.doWithAuthToken(httpReq, &resp)
err = c.doWithAuthToken(ctx, httpReq, &resp)
if err != nil {
return nil, err
}

View File

@ -1,6 +1,8 @@
// Package groupme defines a client capable of executing API commands for the GroupMe chat service
package groupme
import (
"context"
"fmt"
"net/http"
"testing"
@ -18,6 +20,7 @@ func (s *MessagesAPISuite) SetupSuite() {
func (s *MessagesAPISuite) TestMessagesIndex() {
resp, err := s.client.IndexMessages(
context.Background(),
ID("123"),
&IndexMessagesQuery{
BeforeID: "0123456789",
@ -35,6 +38,7 @@ func (s *MessagesAPISuite) TestMessagesIndex() {
func (s *MessagesAPISuite) TestMessagesCreate() {
message, err := s.client.CreateMessage(
context.Background(),
ID("123"),
&Message{
Text: "Test",
@ -49,6 +53,7 @@ func TestMessagesAPISuite(t *testing.T) {
suite.Run(t, new(MessagesAPISuite))
}
// nolint // not duplicate code
func messagesTestRouter() *mux.Router {
router := mux.NewRouter().Queries("token", "").Subrouter()

View File

@ -1,7 +1,9 @@
// Package groupme defines a client capable of executing API commands for the GroupMe chat service
package groupme
import (
"bytes"
"context"
"encoding/json"
"fmt"
"net/http"
@ -9,7 +11,7 @@ import (
// GroupMe documentation: https://dev.groupme.com/docs/v3#sms_mode
////////// Endpoints //////////
/*//////// Endpoints ////////*/
const (
// Used to build other endpoints
smsModeEndpointRoot = usersEndpointRoot + "/sms_mode"
@ -19,7 +21,7 @@ const (
deleteSMSModeEndpoint = smsModeEndpointRoot + "/delete" // POST
)
////////// API Requests //////////
/*//////// API Requests ////////*/
// Create
@ -35,7 +37,7 @@ Parameters:
omitted, both SMS and push notifications will be
delivered to the device.
*/
func (c *Client) CreateSMSMode(duration int, registrationID *ID) error {
func (c *Client) CreateSMSMode(ctx context.Context, duration int, registrationID *ID) error {
URL := fmt.Sprintf(c.endpointBase + createSMSModeEndpoint)
var data = struct {
@ -56,7 +58,7 @@ func (c *Client) CreateSMSMode(duration int, registrationID *ID) error {
return err
}
err = c.doWithAuthToken(httpReq, nil)
err = c.doWithAuthToken(ctx, httpReq, nil)
if err != nil {
return err
}
@ -71,7 +73,7 @@ DeleteSMSMode -
Disables SMS mode
*/
func (c *Client) DeleteSMSMode() error {
func (c *Client) DeleteSMSMode(ctx context.Context) error {
url := fmt.Sprintf(c.endpointBase + deleteSMSModeEndpoint)
httpReq, err := http.NewRequest("POST", url, nil)
@ -79,5 +81,5 @@ func (c *Client) DeleteSMSMode() error {
return err
}
return c.doWithAuthToken(httpReq, nil)
return c.doWithAuthToken(ctx, httpReq, nil)
}

View File

@ -1,6 +1,8 @@
// Package groupme defines a client capable of executing API commands for the GroupMe chat service
package groupme
import (
"context"
"net/http"
"testing"
@ -16,16 +18,17 @@ func (s *SMSModeAPISuite) SetupSuite() {
}
func (s *SMSModeAPISuite) TestSMSModeCreate() {
s.Assert().NoError(s.client.CreateSMSMode(10, nil))
s.Assert().NoError(s.client.CreateSMSMode(context.Background(), 10, nil))
}
func (s *SMSModeAPISuite) TestSMSModeDelete() {
s.Assert().NoError(s.client.DeleteSMSMode())
s.Assert().NoError(s.client.DeleteSMSMode(context.Background()))
}
func TestSMSModeAPISuite(t *testing.T) {
suite.Run(t, new(SMSModeAPISuite))
}
// nolint // not duplicate code
func smsModeTestRouter() *mux.Router {
router := mux.NewRouter().Queries("token", "").Subrouter()

View File

@ -1,7 +1,9 @@
// Package groupme defines a client capable of executing API commands for the GroupMe chat service
package groupme
import (
"bytes"
"context"
"encoding/json"
"fmt"
"net/http"
@ -9,7 +11,7 @@ import (
// GroupMe documentation: https://dev.groupme.com/docs/v3#users
////////// Endpoints //////////
/*//////// Endpoints ////////*/
const (
// Used to build other endpoints
usersEndpointRoot = "/users"
@ -19,7 +21,7 @@ const (
updateMyUserEndpoint = usersEndpointRoot + "/update" // POST
)
////////// API Requests //////////
/*//////// API Requests ////////*/
// Me
@ -31,7 +33,7 @@ Loads a specific group.
Parameters:
groupID - required, ID(string)
*/
func (c *Client) MyUser() (*User, error) {
func (c *Client) MyUser(ctx context.Context) (*User, error) {
URL := fmt.Sprintf(c.endpointBase + myUserEndpoint)
httpReq, err := http.NewRequest("GET", URL, nil)
@ -40,7 +42,7 @@ func (c *Client) MyUser() (*User, error) {
}
var resp User
err = c.doWithAuthToken(httpReq, &resp)
err = c.doWithAuthToken(ctx, httpReq, &resp)
if err != nil {
return nil, err
}
@ -48,8 +50,7 @@ func (c *Client) MyUser() (*User, error) {
return &resp, nil
}
// Update
// UserSettings are the settings for a GroupMe user
type UserSettings struct {
// URL to valid JPG/PNG/GIF image. URL will be converted into
// an image service link (https://i.groupme.com/....)
@ -68,7 +69,7 @@ Update attributes about your own account
Parameters: See UserSettings
*/
func (c *Client) UpdateMyUser(us UserSettings) (*User, error) {
func (c *Client) UpdateMyUser(ctx context.Context, us UserSettings) (*User, error) {
URL := fmt.Sprintf(c.endpointBase + updateMyUserEndpoint)
jsonBytes, err := json.Marshal(&us)
@ -82,7 +83,7 @@ func (c *Client) UpdateMyUser(us UserSettings) (*User, error) {
}
var resp User
err = c.doWithAuthToken(httpReq, &resp)
err = c.doWithAuthToken(ctx, httpReq, &resp)
if err != nil {
return nil, err
}

View File

@ -1,6 +1,8 @@
// Package groupme defines a client capable of executing API commands for the GroupMe chat service
package groupme
import (
"context"
"fmt"
"net/http"
"testing"
@ -17,13 +19,13 @@ func (s *UsersAPISuite) SetupSuite() {
}
func (s *UsersAPISuite) TestUsersMe() {
user, err := s.client.MyUser()
user, err := s.client.MyUser(context.Background())
s.Require().NoError(err)
s.Assert().NotZero(user)
}
func (s *UsersAPISuite) TestUsersUpdate() {
user, err := s.client.UpdateMyUser(UserSettings{})
user, err := s.client.UpdateMyUser(context.Background(), UserSettings{})
s.Require().NoError(err)
s.Assert().NotZero(user)
}
@ -31,6 +33,8 @@ func (s *UsersAPISuite) TestUsersUpdate() {
func TestUsersAPISuite(t *testing.T) {
suite.Run(t, new(UsersAPISuite))
}
// nolint // not duplicate code
func usersTestRouter() *mux.Router {
router := mux.NewRouter().Queries("token", "").Subrouter()