18 Commits

Author SHA1 Message Date
6d42a230d1 Fix bugs with direct message api 2021-05-08 15:44:18 -04:00
7166300503 Add more attachment values 2021-05-08 15:44:18 -04:00
f92a8a7a86 Introducing Contexts
Contexts have been added to all API requests, in addition to other linting fixes
2021-01-22 16:47:22 -05:00
646bec0e27 Update README.md 2021-01-22 14:43:05 -05:00
b9317e3e37 Update and rename go.yml to go-test.yml 2021-01-22 14:39:15 -05:00
05eb619c40 Update golangci-lint.yml 2021-01-22 14:36:24 -05:00
055fdc7126 Delete go-test.yml 2021-01-22 14:35:10 -05:00
3bac8c4f92 Update go.yml 2021-01-22 14:34:56 -05:00
8fca7782ec Create go.yml 2021-01-22 14:30:44 -05:00
8628d37bef Update README.md 2021-01-22 13:56:31 -05:00
6f453ff6cc Merge pull request #10 from tekkamanendless/return-meta-on-error
Return Meta on error
2020-12-29 15:52:53 -05:00
73586d4b4c Ensure that we return the correct error code even if we can't read the body 2020-12-20 13:35:13 -05:00
7f8d829ff7 Return the Meta on error
Previously, this would never actually return the Meta data structure
since by the time that it got parsed, we already knew that the request
was good.  Now, we do a special parse when we know that it failed so
that we can return the structured data (in particular, we want to be
able to use the HTTP status code).
2020-12-20 13:28:12 -05:00
d657643538 Merge pull request #8 from tekkamanendless/add-member-by-search
Add the email and phone_number fields to the Member structure
2020-12-14 21:31:17 -05:00
3e663f8615 Update golangci-lint.yml
Trying a different marketplace action
2020-12-14 21:20:36 -05:00
eea12a3b50 Update golangci-lint.yml
Update version again
2020-12-14 21:17:56 -05:00
e6f29c4e73 Update golangci-lint.yml
Updated version
2020-12-14 21:07:14 -05:00
cd2551461d Add the email and phone_number fields to the Member structure
These fields aren't _returned_ with any member-related calls; however,
they are used when _adding_ a member to a group.  For example, you can
add a member to a group by email address, but you need to set the "email"
property.  Ditto for "phone_number".
2020-12-13 14:00:44 -05:00
36 changed files with 425 additions and 585 deletions

View File

@ -1,29 +1,21 @@
name: test
name: Go Test
on:
push:
tags:
- v*
branches:
- master
branches: [ master ]
pull_request:
branches: [ master ]
jobs:
test:
name: Test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Set up Go
uses: actions/setup-go@v1
uses: actions/setup-go@v2
with:
go-version: 1.14
go-version: 1.15
- name: Check out code
uses: actions/checkout@v1
- name: Run Unit tests.
run: go test -coverprofile cover.out -covermode=atomic ${PKG_LIST} && cat cover.out >> coverage.txt
- name: Upload Coverage report to CodeCov
uses: codecov/codecov-action@v1.0.0
with:
token: ${{secrets.CODECOV_TOKEN}}
file: ./coverage.txt
- name: Test
run: go test -v ./...

View File

@ -1,10 +1,6 @@
name: golangci-lint
on:
push:
tags:
- v*
branches:
- master
pull_request:
jobs:
golangci:
@ -13,7 +9,7 @@ jobs:
steps:
- uses: actions/checkout@v2
- name: golangci-lint
uses: golangci/golangci-lint-action@v1
uses: golangci/golangci-lint-action@v2
with:
# Required: the version of golangci-lint is required and must be specified without patch version: we always use the latest patch version.
version: v1.29
@ -26,3 +22,6 @@ jobs:
# Optional: show only new issues if it's a pull request. The default value is `false`.
# only-new-issues: true
# Optional: if set to true then the action will use pre-installed Go
# skip-go-installation: true

View File

@ -6,7 +6,6 @@ I would like to add common helper functions/features inspired by the package use
# GroupMe API Wrapper
![GitHub tag (latest SemVer)](https://img.shields.io/github/v/tag/densestvoid/groupme?label=version&logo=version&sort=semver)
[![PkgGoDev](https://pkg.go.dev/badge/github.com/densestvoid/groupme)](https://pkg.go.dev/github.com/densestvoid/groupme)
[![codecov](https://codecov.io/gh/densestvoid/groupme/branch/master/graph/badge.svg)](https://codecov.io/gh/densestvoid/groupme)
## Description
The design of this package is meant to be super simple. Wrap the exposed API endpoints [documented](https://dev.groupme.com/docs/v3#v3) by the GroupMe team. While you can achieve the core of this package with cURL, there are some small added features, coupled along with a modern language, that should simplify writing GroupMe [bots](https://dev.groupme.com/bots) and [applications](https://dev.groupme.com/applications).
@ -74,6 +73,9 @@ func main() {
### [*FUTURE*] CLI
## Support
You can join the [GroupMe support group](https://groupme.com/join_group/65686806/il1737tE) (you will need to provide a reason for joining), or the [Discord server](https://discord.gg/raAdxWuKTU).
## Contribute
I find the hours I can spend developing personal projects decreasing every year, so I welcome any help I can get. Feel free to tackle any open issues, or if a feature request catches your eye, feel free to reach out to me and we can discuss adding it to the package. However, once version 1.0 is released, I don't foresee much work happening on this project unless the GroupMe API is updated.

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,14 +1,15 @@
// Package groupme defines a client capable of executing API commands for the GroupMe chat service
package groupme
import (
"bytes"
"context"
"encoding/json"
"fmt"
"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"
@ -41,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"`
@ -59,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")
}
@ -70,38 +74,49 @@ func (c Client) do(req *http.Request, i interface{}) error {
}
defer getResp.Body.Close()
bytes, err := ioutil.ReadAll(getResp.Body)
var readBytes []byte
// Check Status Code is 1XX or 2XX
if getResp.StatusCode >= errorStatusCodeMin {
readBytes, err = ioutil.ReadAll(getResp.Body)
if err != nil {
return err
// We couldn't read the output. Oh well; generate the appropriate error type anyway.
return &Meta{
Code: HTTPStatusCode(getResp.StatusCode),
}
}
// Check Status Code is 1XX or 2XX
if getResp.StatusCode/100 > 2 {
return fmt.Errorf("%s: %s", getResp.Status, string(bytes))
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
}
resp := newJSONResponse(i)
if err := json.Unmarshal(bytes, &resp); err != nil {
readBytes, err = ioutil.ReadAll(getResp.Body)
if err != nil {
return err
}
// Check Status Code is 1XX or 2XX
if resp.Meta.Code/100 > 2 {
return &resp.Meta
resp := newJSONResponse(i)
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())
@ -82,9 +82,10 @@ func (c *Client) IndexDirectMessages(otherUserID ID, req *IndexDirectMessagesQue
query.Add("since_id", req.SinceID.String())
}
}
httpReq.URL.RawQuery = query.Encode()
var resp IndexDirectMessagesResponse
err = c.doWithAuthToken(httpReq, &resp)
err = c.doWithAuthToken(ctx, httpReq, &resp)
if err != nil {
return IndexDirectMessagesResponse{}, err
}
@ -92,12 +93,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 +106,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()
@ -141,9 +128,9 @@ func (c *Client) CreateDirectMessage(m *Message) (*Message, error) {
}
var resp struct {
*Message `json:"message"`
*Message `json:"direct_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{
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{
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{
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()

62
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
@ -89,10 +90,12 @@ type Member struct {
AutoKicked bool `json:"autokicked,omitempty"`
AppInstalled bool `json:"app_installed,omitempty"`
GUID string `json:"guid,omitempty"`
PhoneNumber string `json:"phone_number,omitempty"` // Only used when searching for the member to add to a group.
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
@ -104,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"`
@ -118,44 +121,47 @@ 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"`
FileID string `json:"file_id,omitempty"`
VideoPreviewURL string `json:"preview_url,omitempty"`
Name string `json:"name,omitempty"`
Latitude string `json:"lat,omitempty"`
Longitude string `json:"lng,omitempty"`
Placeholder string `json:"placeholder,omitempty"`
Charmap [][]int `json:"charmap,omitempty"`
ReplyID ID `json:"reply_id,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
@ -171,8 +177,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,
@ -185,10 +191,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"`
@ -198,10 +205,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()