Compare commits

..

No commits in common. "master" and "v0.1.4" have entirely different histories.

39 changed files with 613 additions and 1163 deletions

View File

@ -1,21 +1,29 @@
name: Go Test
name: test
on:
push:
branches: [ master ]
tags:
- v*
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@v2
uses: actions/setup-go@v1
with:
go-version: 1.15
go-version: 1.14
- name: Test
run: go test -v ./...
- 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

View File

@ -1,6 +1,10 @@
name: golangci-lint
on:
push:
tags:
- v*
branches:
- master
pull_request:
jobs:
golangci:
@ -9,7 +13,7 @@ jobs:
steps:
- uses: actions/checkout@v2
- name: golangci-lint
uses: golangci/golangci-lint-action@v2
uses: golangci/golangci-lint-action@v1
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
@ -22,6 +26,3 @@ 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,6 +6,7 @@ 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).
@ -73,9 +74,6 @@ 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,14 +1,12 @@
// 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"
@ -20,10 +18,19 @@ const (
unblockEndpoint = blocksEndpointRoot // DELETE
)
/*//////// API Requests ////////*/
////////// API Requests //////////
// IndexBlock - A list of contacts you have blocked. These people cannot DM you
func (c *Client) IndexBlock(ctx context.Context, userID string, authToken string) ([]*Block, error) {
// 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) {
httpReq, err := http.NewRequest("GET", c.endpointBase+indexBlocksEndpoint, nil)
if err != nil {
return nil, err
@ -31,13 +38,13 @@ func (c *Client) IndexBlock(ctx context.Context, userID string, authToken string
URL := httpReq.URL
query := URL.Query()
query.Set("user", userID)
query.Set("user", userID.String())
URL.RawQuery = query.Encode()
var resp struct {
Blocks []*Block `json:"blocks"`
}
err = c.doWithAuthToken(ctx, httpReq, &resp, authToken)
err = c.doWithAuthToken(httpReq, &resp)
if err != nil {
return nil, err
}
@ -45,8 +52,17 @@ func (c *Client) IndexBlock(ctx context.Context, userID string, authToken string
return resp.Blocks, nil
}
// BlockBetween - Asks if a block exists between you and another user id
func (c *Client) BlockBetween(ctx context.Context, userID, otherUserID string, authToken string) (bool, error) {
// 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) {
httpReq, err := http.NewRequest("GET", c.endpointBase+blockBetweenEndpoint, nil)
if err != nil {
return false, err
@ -54,14 +70,14 @@ func (c *Client) BlockBetween(ctx context.Context, userID, otherUserID string, a
URL := httpReq.URL
query := URL.Query()
query.Set("user", userID)
query.Set("otherUser", otherUserID)
query.Set("user", userID.String())
query.Set("otherUser", otherUserID.String())
URL.RawQuery = query.Encode()
var resp struct {
Between bool `json:"between"`
}
err = c.doWithAuthToken(ctx, httpReq, &resp, authToken)
err = c.doWithAuthToken(httpReq, &resp)
if err != nil {
return false, err
}
@ -69,8 +85,18 @@ func (c *Client) BlockBetween(ctx context.Context, userID, otherUserID string, a
return resp.Between, nil
}
// CreateBlock - Creates a block between you and the contact
func (c *Client) CreateBlock(ctx context.Context, userID, otherUserID string, authToken string) (*Block, error) {
// 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) {
httpReq, err := http.NewRequest("POST", c.endpointBase+createBlockEndpoint, nil)
if err != nil {
return nil, err
@ -78,14 +104,14 @@ func (c *Client) CreateBlock(ctx context.Context, userID, otherUserID string, au
URL := httpReq.URL
query := URL.Query()
query.Set("user", userID)
query.Set("otherUser", otherUserID)
query.Set("user", userID.String())
query.Set("otherUser", otherUserID.String())
URL.RawQuery = query.Encode()
var resp struct {
Block *Block `json:"block"`
}
err = c.doWithAuthToken(ctx, httpReq, &resp, authToken)
err = c.doWithAuthToken(httpReq, &resp)
if err != nil {
return nil, err
}
@ -93,8 +119,18 @@ func (c *Client) CreateBlock(ctx context.Context, userID, otherUserID string, au
return resp.Block, nil
}
// Unblock - Removes block between you and other user
func (c *Client) Unblock(ctx context.Context, userID, otherUserID string, authToken string) error {
// 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 {
httpReq, err := http.NewRequest("DELETE", c.endpointBase+unblockEndpoint, nil)
if err != nil {
return err
@ -102,11 +138,11 @@ func (c *Client) Unblock(ctx context.Context, userID, otherUserID string, authTo
URL := httpReq.URL
query := URL.Query()
query.Set("user", userID)
query.Set("otherUser", otherUserID)
query.Set("user", userID.String())
query.Set("otherUser", otherUserID.String())
URL.RawQuery = query.Encode()
err = c.doWithAuthToken(ctx, httpReq, nil, authToken)
err = c.doWithAuthToken(httpReq, nil)
if err != nil {
return err
}

View File

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

View File

@ -1,9 +1,7 @@
// 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 +9,7 @@ import (
// GroupMe documentation: https://dev.groupme.com/docs/v3#bots
/*//////// Endpoints ////////*/
////////// Endpoints //////////
const (
// Used to build other endpoints
botsEndpointRoot = "/bots"
@ -23,11 +21,22 @@ const (
destroyBotEndpoint = botsEndpointRoot + "/destroy" // POST
)
/*//////// API Requests ////////*/
////////// API Requests //////////
// 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, authToken string) (*Bot, error) {
// 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) {
URL := c.endpointBase + createBotEndpoint
var data = struct {
@ -47,7 +56,7 @@ func (c *Client) CreateBot(ctx context.Context, bot *Bot, authToken string) (*Bo
}
var resp Bot
err = c.doWithAuthToken(ctx, httpReq, &resp, authToken)
err = c.doWithAuthToken(httpReq, &resp)
if err != nil {
return nil, err
}
@ -55,9 +64,21 @@ func (c *Client) CreateBot(ctx context.Context, bot *Bot, authToken string) (*Bo
return &resp, nil
}
// PostBotMessage - Post a message from a bot
// 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)
*/
// TODO: Move PostBotMessage to bot object, since it doesn't require access token
func (c *Client) PostBotMessage(ctx context.Context, botID ID, text string, pictureURL *string) error {
func (c *Client) PostBotMessage(botID ID, text string, pictureURL *string) error {
URL := fmt.Sprintf(c.endpointBase + postBotMessageEndpoint)
var data = struct {
@ -80,18 +101,24 @@ func (c *Client) PostBotMessage(ctx context.Context, botID ID, text string, pict
return err
}
return c.do(ctx, httpReq, nil)
return c.do(httpReq, nil)
}
// IndexBots - list bots that you have created
func (c *Client) IndexBots(ctx context.Context, authToken string) ([]*Bot, error) {
// Index
/*
IndexBots -
List bots that you have created
*/
func (c *Client) IndexBots() ([]*Bot, error) {
httpReq, err := http.NewRequest("GET", c.endpointBase+indexBotsEndpoint, nil)
if err != nil {
return nil, err
}
var resp []*Bot
err = c.doWithAuthToken(ctx, httpReq, &resp, authToken)
err = c.doWithAuthToken(httpReq, &resp)
if err != nil {
return nil, err
}
@ -99,8 +126,17 @@ func (c *Client) IndexBots(ctx context.Context, authToken string) ([]*Bot, error
return resp, nil
}
// DestroyBot - Remove a bot that you have created
func (c *Client) DestroyBot(ctx context.Context, botID ID, authToken string) error {
// Destroy
/*
DestroyBot -
Remove a bot that you have created
Parameters:
botID - required, ID(string)
*/
func (c *Client) DestroyBot(botID ID) error {
URL := fmt.Sprintf(c.endpointBase + destroyBotEndpoint)
var data = struct {
@ -119,5 +155,5 @@ func (c *Client) DestroyBot(ctx context.Context, botID ID, authToken string) err
return err
}
return c.doWithAuthToken(ctx, httpReq, nil, authToken)
return c.doWithAuthToken(httpReq, nil)
}

View File

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

View File

@ -1,15 +1,13 @@
// 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"
@ -17,7 +15,9 @@ const (
indexChatsEndpoint = chatsEndpointRoot // GET
)
// IndexChatsQuery defines the optional URL parameters for IndexChats
// Index
// ChatsQuery defines the optional URL parameters for IndexChats
type IndexChatsQuery struct {
// Page Number
Page int `json:"page"`
@ -25,9 +25,15 @@ type IndexChatsQuery struct {
PerPage int `json:"per_page"`
}
// 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, authToken string) ([]*Chat, error) {
/*
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) {
httpReq, err := http.NewRequest("GET", c.endpointBase+indexChatsEndpoint, nil)
if err != nil {
return nil, err
@ -46,27 +52,7 @@ func (c *Client) IndexChats(ctx context.Context, req *IndexChatsQuery, authToken
URL.RawQuery = query.Encode()
var resp []*Chat
err = c.doWithAuthToken(ctx, httpReq, &resp, authToken)
if err != nil {
return nil, err
}
return resp, nil
}
func (c *Client) IndexRelations(ctx context.Context, authToken string) ([]*User, error) {
httpReq, err := http.NewRequest("GET", "https://api.groupme.com/v4"+"/relationships", nil)
if err != nil {
return nil, err
}
URL := httpReq.URL
query := URL.Query()
query.Set("include_blocked", "true")
URL.RawQuery = query.Encode()
var resp []*User
err = c.doWithAuthToken(ctx, httpReq, &resp, authToken)
err = c.doWithAuthToken(httpReq, &resp)
if err != nil {
return nil, err
}

View File

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

View File

@ -1,15 +1,14 @@
// 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"
)
// GroupMeAPIBase - Endpoints are added on to this to get the full URI.
// Endpoints are added on to the GroupMeAPIBase to get the full URI.
// Overridable for testing
const GroupMeAPIBase = "https://api.groupme.com/v3"
@ -18,14 +17,16 @@ const GroupMeAPIBase = "https://api.groupme.com/v3"
type Client struct {
httpClient *http.Client
endpointBase string
authorizationToken string
}
// NewClient creates a new GroupMe API Client
func NewClient() *Client {
func NewClient(authToken string) *Client {
return &Client{
// TODO: enable transport information passing in
httpClient: &http.Client{},
endpointBase: GroupMeAPIBase,
authorizationToken: authToken,
}
}
@ -40,7 +41,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,10 +59,7 @@ func (r response) UnmarshalJSON(bs []byte) error {
return json.NewDecoder(bytes.NewBuffer(bs)).Decode(r.i)
}
const errorStatusCodeMin = 300
func (c Client) do(ctx context.Context, req *http.Request, i interface{}) error {
req = req.WithContext(ctx)
func (c Client) do(req *http.Request, i interface{}) error {
if req.Method == "POST" {
req.Header.Set("Content-Type", "application/json")
}
@ -72,49 +70,38 @@ func (c Client) do(ctx context.Context, req *http.Request, i interface{}) error
}
defer getResp.Body.Close()
var readBytes []byte
// Check Status Code is 1XX or 2XX
if getResp.StatusCode >= errorStatusCodeMin {
readBytes, err = ioutil.ReadAll(getResp.Body)
bytes, err := ioutil.ReadAll(getResp.Body)
if err != nil {
// We couldn't read the output. Oh well; generate the appropriate error type anyway.
return &Meta{
Code: HTTPStatusCode(getResp.StatusCode),
}
return err
}
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
// Check Status Code is 1XX or 2XX
if getResp.StatusCode/100 > 2 {
return fmt.Errorf("%s: %s", getResp.Status, string(bytes))
}
if i == nil {
return nil
}
readBytes, err = ioutil.ReadAll(getResp.Body)
if err != nil {
resp := newJSONResponse(i)
if err := json.Unmarshal(bytes, &resp); err != nil {
return err
}
resp := newJSONResponse(i)
if err := json.Unmarshal(readBytes, &resp); err != nil {
return err
// Check Status Code is 1XX or 2XX
if resp.Meta.Code/100 > 2 {
return &resp.Meta
}
return nil
}
func (c Client) doWithAuthToken(ctx context.Context, req *http.Request, i interface{}, authToken string) error {
func (c Client) doWithAuthToken(req *http.Request, i interface{}) error {
URL := req.URL
query := URL.Query()
query.Set("token", authToken)
query.Set("token", c.authorizationToken)
URL.RawQuery = query.Encode()
return c.do(ctx, req, i)
return c.do(req, i)
}

View File

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

View File

@ -1,4 +1,3 @@
// Package groupme defines a client capable of executing API commands for the GroupMe chat service
package groupme
import (
@ -45,7 +44,7 @@ func (t Timestamp) String() string {
type PhoneNumber string
// Treated as a constant
var phoneNumberRegex = regexp.MustCompile(`^\+\d+ \d{10}$`)
var phoneNumberRegex = regexp.MustCompile(`^\+[0-9]+ [0-9]{10}$`)
// Valid checks if the ID string is alpha numeric
func (pn PhoneNumber) Valid() bool {
@ -56,40 +55,40 @@ func (pn PhoneNumber) String() string {
return string(pn)
}
// HTTPStatusCode are returned by HTTP requests in
// StatusCodes are returned by HTTP requests in
// the header and the json "meta" field
type HTTPStatusCode int
// Text used as constant name
const (
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
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
)
// String returns the description of the status code according to GroupMe
func (c HTTPStatusCode) String() string {
return map[HTTPStatusCode]string{
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",
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",
}[c]
}

View File

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

View File

@ -1,9 +1,7 @@
// 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"
@ -13,7 +11,7 @@ import (
// GroupMe documentation: https://dev.groupme.com/docs/v3#direct_messages
/*//////// Endpoints ////////*/
////////// Endpoints //////////
const (
// Used to build other endpoints
directMessagesEndpointRoot = "/direct_messages"
@ -23,9 +21,11 @@ const (
createDirectMessageEndpoint = directMessagesEndpointRoot // POST
)
/*//////// API Requests ////////*/
////////// API Requests //////////
// IndexDirectMessagesQuery defines the optional URL parameters for IndexDirectMessages
// Index
// MessagesQuery defines the optional URL parameters for IndexDirectMessages
type IndexDirectMessagesQuery struct {
// Returns 20 messages created before the given message ID
BeforeID ID `json:"before_id"`
@ -63,18 +63,17 @@ Note that for historical reasons, likes are returned as an array
of user ids in the favorited_by key.
Parameters:
otherUserID - required, ID(string); the other participant in the conversation.
See IndexDirectMessagesQuery
*/
func (c *Client) IndexDirectMessages(ctx context.Context, otherUserID string, req *IndexDirectMessagesQuery, authToken string) (IndexDirectMessagesResponse, error) {
func (c *Client) IndexDirectMessages(otherUserID ID, 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)
query.Set("other_user_id", otherUserID.String())
if req != nil {
if req.BeforeID != "" {
query.Add("before_ID", req.BeforeID.String())
@ -83,10 +82,9 @@ func (c *Client) IndexDirectMessages(ctx context.Context, otherUserID string, re
query.Add("since_id", req.SinceID.String())
}
}
httpReq.URL.RawQuery = query.Encode()
var resp IndexDirectMessagesResponse
err = c.doWithAuthToken(ctx, httpReq, &resp, authToken)
err = c.doWithAuthToken(httpReq, &resp)
if err != nil {
return IndexDirectMessagesResponse{}, err
}
@ -94,8 +92,12 @@ func (c *Client) IndexDirectMessages(ctx context.Context, otherUserID string, re
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.
@ -107,8 +109,18 @@ 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(ctx context.Context, m *Message, authToken string) (*Message, error) {
func (c *Client) CreateDirectMessage(m *Message) (*Message, error) {
URL := fmt.Sprintf(c.endpointBase + createDirectMessageEndpoint)
m.SourceGUID = uuid.New().String()
@ -129,9 +141,9 @@ func (c *Client) CreateDirectMessage(ctx context.Context, m *Message, authToken
}
var resp struct {
*Message `json:"direct_message"`
*Message `json:"message"`
}
err = c.doWithAuthToken(ctx, httpReq, &resp, authToken)
err = c.doWithAuthToken(httpReq, &resp)
if err != nil {
return nil, err
}

View File

@ -1,8 +1,6 @@
// Package groupme defines a client capable of executing API commands for the GroupMe chat service
package groupme
import (
"context"
"fmt"
"net/http"
"testing"
@ -20,8 +18,7 @@ func (s *DirectMessagesAPISuite) SetupSuite() {
func (s *DirectMessagesAPISuite) TestDirectMessagesIndex() {
resp, err := s.client.IndexDirectMessages(
context.Background(),
"123",
ID("123"),
&IndexDirectMessagesQuery{
BeforeID: "0123456789",
SinceID: "9876543210",
@ -36,7 +33,6 @@ func (s *DirectMessagesAPISuite) TestDirectMessagesIndex() {
func (s *DirectMessagesAPISuite) TestDirectMessagesCreate() {
message, err := s.client.CreateDirectMessage(
context.Background(),
&Message{
RecipientID: ID("123"),
Text: "Test",
@ -51,7 +47,6 @@ 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,8 +1,9 @@
package main
import (
"context"
"fmt"
"github.com/densestvoid/groupme"
)
// This is not a real token. Please find yours by logging
@ -17,14 +18,11 @@ func main() {
client := groupme.NewClient(authorizationToken)
// Get the groups your user is part of
groups, err := client.IndexGroups(
context.Background(),
&groupme.GroupsQuery{
groups, err := client.IndexGroups(&groupme.GroupsQuery{
Page: 0,
PerPage: 5,
Omit: "memberships",
},
)
})
if err != nil {
fmt.Println(err)
@ -34,11 +32,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(context.Background(), groups[0].ID, &groupme.IndexMessagesQuery{
messages, err := client.IndexMessages(groups[0].ID, &groupme.IndexMessagesQuery{
Limit: 10,
})

View File

@ -1,8 +1,9 @@
package main
import (
"context"
"fmt"
"github.com/densestvoid/groupme"
)
// This is not a real Bot ID. Please find yours by logging
@ -15,5 +16,5 @@ const botID = "0123456789ABCDEF"
func main() {
// Create a new client with your auth token
client := groupme.NewClient("")
fmt.Println(client.PostBotMessage(context.Background(), botID, "Your message here!", nil))
fmt.Println(client.PostBotMessage(botID, "Your message here!", nil))
}

View File

@ -1,177 +0,0 @@
package main
import (
"context"
"fmt"
"log"
"gitea.watsonlabs.net/watsonb8/groupme-lib"
)
// This is not a real token. Please find yours by logging
// into the GroupMe development website: https://dev.groupme.com/
var authorizationToken = "ASD"
var authorizationToken2 = "ASDF"
// A short program that subscribes to 2 groups and 2 direct chats
// and prints out all recognized events in those
func main() {
//create push subscription and start listening
p := groupme.NewPushSubscription(context.Background())
err := p.Connect(context.TODO())
if err != nil {
return
}
// Create a new client with your auth token
client := groupme.NewClient()
User, _ := client.MyUser(context.Background(), authorizationToken)
User2, _ := client.MyUser(context.Background(), authorizationToken2)
//handles (in this case prints) all messages
p.AddFullHandler(Handler{User: User}, authorizationToken)
p.AddHandler(Handler{User: User2}, authorizationToken2)
//Subscribe to get messages and events for the specific user
p.SubscribeToUser(context.Background(), User.ID, authorizationToken)
p.SubscribeToUser(context.Background(), User2.ID, authorizationToken2)
if err != nil {
log.Fatal(err)
}
// Get the groups your user is part of
groups, err := client.IndexGroups(
context.Background(),
&groupme.GroupsQuery{
Page: 0,
PerPage: 2,
Omit: "memberships",
}, authorizationToken)
groups2, err := client.IndexGroups(
context.Background(),
&groupme.GroupsQuery{
Page: 0,
PerPage: 2,
Omit: "memberships",
}, authorizationToken2)
if err != nil {
fmt.Println(err)
return
}
//Subscribe to those groups
for _, j := range groups {
err = p.SubscribeToGroup(context.TODO(), j.ID, authorizationToken)
if err != nil {
log.Fatal(err)
}
}
for _, j := range groups2 {
err = p.SubscribeToGroup(context.TODO(), j.ID, authorizationToken2)
if err != nil {
log.Fatal(err)
}
}
//get chats your user is part of
chats, err := client.IndexChats(context.Background(),
&groupme.IndexChatsQuery{
Page: 0,
PerPage: 2,
}, authorizationToken)
chats2, err := client.IndexChats(context.Background(),
&groupme.IndexChatsQuery{
Page: 0,
PerPage: 2,
}, authorizationToken2)
//subscribe to all those chats
for _, j := range chats {
go func() {
err := p.SubscribeToDM(context.TODO(), j.LastMessage.ConversationID, authorizationToken)
if err != nil {
log.Fatal(err)
}
}()
}
for _, j := range chats2 {
go func() {
err := p.SubscribeToDM(context.TODO(), j.LastMessage.ConversationID, authorizationToken2)
if err != nil {
log.Fatal(err)
}
}()
}
//blocking
<-make(chan (struct{}))
}
// Following example handlers print out all data
type Handler struct {
User *groupme.User
}
func (h Handler) HandleError(e error) {
fmt.Println(e)
}
func (h Handler) HandleTextMessage(msg groupme.Message) {
fmt.Println(msg.Text, msg.Name, msg.Attachments)
}
func (h Handler) HandleJoin(group groupme.ID) {
fmt.Println("User joined group with id", group.String())
}
func (h Handler) HandleLike(msg groupme.Message) {
fmt.Println(msg.ID, "liked by", msg.FavoritedBy)
}
func (h Handler) HandlerMembership(i groupme.ID) {
fmt.Println("Membership event on", i.String())
}
func (h Handler) HandleGroupTopic(group groupme.ID, newTopic string) {
fmt.Println(group.String(), "has new topic of", newTopic)
}
func (h Handler) HandleGroupName(group groupme.ID, newName string) {
fmt.Println(group.String(), "has new name of", newName)
}
func (h Handler) HandleGroupAvatar(group groupme.ID, newAvatar string) {
fmt.Println(group.String(), "has new avatar url of", newAvatar)
}
func (h Handler) HandleLikeIcon(group groupme.ID, PackID, PackIndex int, Type string) {
//Not sure how to use without groupme icon packs
if len(Type) == 0 {
fmt.Println("Default like icon set")
return
}
fmt.Println(group.String(), "has new like icon of", PackID, PackIndex, Type)
}
func (h Handler) HandleNewNickname(group groupme.ID, user groupme.ID, newName string) {
fmt.Printf("In group %s, user %s has new nickname %s\n", group.String(), user.String(), newName)
}
func (h Handler) HandleNewAvatarInGroup(group groupme.ID, user groupme.ID, avatarURL string) {
if avatarURL == "" {
//get default avatar
avatarURL = h.User.ImageURL
}
fmt.Printf("In group %s, user %s has new avatar with url %s\n", group.String(), user.String(), avatarURL)
}
func (h Handler) HandleMembers(group groupme.ID, members []groupme.Member, added bool) {
action := "removed"
if added {
action = "added"
}
fmt.Printf("In group %s, users %v %s\n", group.String(), members, action)
}

27
go.mod
View File

@ -1,17 +1,18 @@
module gitea.watsonlabs.net/watsonb8/groupme-lib
module github.com/densestvoid/groupme
go 1.21.0
go 1.14
require (
gitea.watsonlabs.net/watsonb8/fayec v0.0.5-0.20230926180210-b375ab3c8c11
github.com/google/uuid v1.2.0
github.com/gorilla/mux v1.8.0
github.com/stretchr/testify v1.7.0
)
require (
github.com/davecgh/go-spew v1.1.0 // indirect
github.com/gorilla/websocket v1.5.0 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c // indirect
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
)

135
go.sum
View File

@ -1,50 +1,105 @@
gitea.watsonlabs.net/watsonb8/fayec v0.0.0-20230919020138-8f0db7048755 h1:FEhNSjSNvZ+nVg5Z3ds6X8ys3qjM+mmyLTSqKhCUHuQ=
gitea.watsonlabs.net/watsonb8/fayec v0.0.0-20230919020138-8f0db7048755/go.mod h1:gv8CWMq6dFJQhH30u8bO3u4k2irKlclZktLNYDebQ/0=
gitea.watsonlabs.net/watsonb8/fayec v0.0.0-20230919151904-5ca9ade6f946 h1:loc70tiaFs1U4sqn+lKMSBlo5OfvVfClYnWjfGLXaSg=
gitea.watsonlabs.net/watsonb8/fayec v0.0.0-20230919151904-5ca9ade6f946/go.mod h1:gv8CWMq6dFJQhH30u8bO3u4k2irKlclZktLNYDebQ/0=
gitea.watsonlabs.net/watsonb8/fayec v0.0.1 h1:MNFmTaTyyKKgrw04dGO9C5ojtm1jIvy8oHYqbj0ECeY=
gitea.watsonlabs.net/watsonb8/fayec v0.0.1/go.mod h1:gv8CWMq6dFJQhH30u8bO3u4k2irKlclZktLNYDebQ/0=
gitea.watsonlabs.net/watsonb8/fayec v0.0.2 h1:tqbgr1vRZ6Wq4W81xBg+FTOywSv3EJpK263SAVXXTco=
gitea.watsonlabs.net/watsonb8/fayec v0.0.2/go.mod h1:gv8CWMq6dFJQhH30u8bO3u4k2irKlclZktLNYDebQ/0=
gitea.watsonlabs.net/watsonb8/fayec v0.0.3 h1:YpaZBIee8Ix6uGm1UoEtBix1dEU1TURChAsJGJ3pVRo=
gitea.watsonlabs.net/watsonb8/fayec v0.0.3/go.mod h1:gv8CWMq6dFJQhH30u8bO3u4k2irKlclZktLNYDebQ/0=
gitea.watsonlabs.net/watsonb8/fayec v0.0.4 h1:SLvwip1DQy13QngVsEgoLtN7T6bS+X6348p6PQhUF2A=
gitea.watsonlabs.net/watsonb8/fayec v0.0.4/go.mod h1:gv8CWMq6dFJQhH30u8bO3u4k2irKlclZktLNYDebQ/0=
gitea.watsonlabs.net/watsonb8/fayec v0.0.5-0.20230926180210-b375ab3c8c11 h1:xJ9eSFyIrDA43UVpbxOD1QkA2jhg+vS+eezFKCDV3Dw=
gitea.watsonlabs.net/watsonb8/fayec v0.0.5-0.20230926180210-b375ab3c8c11/go.mod h1:gv8CWMq6dFJQhH30u8bO3u4k2irKlclZktLNYDebQ/0=
gitea.watsonlabs.net/watsonb8/fayec v0.0.5 h1:9+UHzUuEcLuZ5Gx5S/NTBxYshUhsiQ5M3vzUF8RAKxw=
gitea.watsonlabs.net/watsonb8/fayec v0.0.5/go.mod h1:gv8CWMq6dFJQhH30u8bO3u4k2irKlclZktLNYDebQ/0=
github.com/autogrowsystems/wray v0.0.0-20160519030252-f36984f6648c/go.mod h1:druJ8QMeBCUmwJ7ZSFowx77dWxEWF3SYlQlsqZaLZQg=
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/google/uuid v1.2.0 h1:qJYtXnJRWmpe7m/3XlyhrsLrEURqHRM2kxzoxXqyUDs=
github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI=
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
github.com/karmanyaahm/wray v0.0.0-20210303233435-756d58657c14 h1:NrATjZKvkY+ojL8FXTWa3fQ+wihFrAxLNE6T+wOkIcY=
github.com/karmanyaahm/wray v0.0.0-20210303233435-756d58657c14/go.mod h1:ysD86MIEevmAkdfdg5s6Qt3I07RN6fvMAyna7jCGG2o=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
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/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s=
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
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.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
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-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
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=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
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=
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=

View File

@ -1,9 +1,7 @@
// Package groupme defines a client capable of executing API commands for the GroupMe chat service
package groupme
import (
"bytes"
"context"
"encoding/json"
"errors"
"fmt"
@ -13,7 +11,7 @@ import (
// GroupMe documentation: https://dev.groupme.com/docs/v3#groups
/*//////// Endpoints ////////*/
////////// Endpoints //////////
const (
// Used to build other endpoints
groupsEndpointRoot = "/groups"
@ -31,7 +29,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 {
@ -53,9 +51,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 {
@ -86,7 +84,7 @@ app for users who are participating in huge groups.
Parameters: See GroupsQuery
*/
func (c *Client) IndexGroups(ctx context.Context, req *GroupsQuery, authToken string) ([]*Group, error) {
func (c *Client) IndexGroups(req *GroupsQuery) ([]*Group, error) {
httpReq, err := http.NewRequest("GET", c.endpointBase+indexGroupsEndpoint, nil)
if err != nil {
return nil, err
@ -108,7 +106,7 @@ func (c *Client) IndexGroups(ctx context.Context, req *GroupsQuery, authToken st
URL.RawQuery = query.Encode()
var resp []*Group
err = c.doWithAuthToken(ctx, httpReq, &resp, authToken)
err = c.doWithAuthToken(httpReq, &resp)
if err != nil {
return nil, err
}
@ -116,21 +114,21 @@ func (c *Client) IndexGroups(ctx context.Context, req *GroupsQuery, authToken st
return resp, nil
}
/*/// Former ///*/
///// Former /////
/*
FormerGroups -
List they groups you have left but can rejoin.
*/
func (c *Client) FormerGroups(ctx context.Context, authToken string) ([]*Group, error) {
func (c *Client) FormerGroups() ([]*Group, error) {
httpReq, err := http.NewRequest("GET", c.endpointBase+formerGroupsEndpoint, nil)
if err != nil {
return nil, err
}
var resp []*Group
err = c.doWithAuthToken(ctx, httpReq, &resp, authToken)
err = c.doWithAuthToken(httpReq, &resp)
if err != nil {
return nil, err
}
@ -138,7 +136,7 @@ func (c *Client) FormerGroups(ctx context.Context, authToken string) ([]*Group,
return resp, nil
}
/*/// Show ///*/
///// Show /////
/*
ShowGroup -
@ -146,10 +144,9 @@ ShowGroup -
Loads a specific group.
Parameters:
groupID - required, ID(string)
*/
func (c *Client) ShowGroup(ctx context.Context, groupID ID, authToken string) (*Group, error) {
func (c *Client) ShowGroup(groupID ID) (*Group, error) {
URL := fmt.Sprintf(c.endpointBase+showGroupEndpoint, groupID)
httpReq, err := http.NewRequest("GET", URL, nil)
@ -158,7 +155,7 @@ func (c *Client) ShowGroup(ctx context.Context, groupID ID, authToken string) (*
}
var resp Group
err = c.doWithAuthToken(ctx, httpReq, &resp, authToken)
err = c.doWithAuthToken(httpReq, &resp)
if err != nil {
return nil, err
}
@ -166,16 +163,16 @@ func (c *Client) ShowGroup(ctx context.Context, groupID ID, authToken string) (*
return &resp, nil
}
/*/// Create ///*/
///// Create /////
/*
CreateGroup -
# Create a new group
Create a new group
Parameters: See GroupSettings
*/
func (c *Client) CreateGroup(ctx context.Context, gs GroupSettings, authToken string) (*Group, error) {
func (c *Client) CreateGroup(gs GroupSettings) (*Group, error) {
URL := fmt.Sprintf(c.endpointBase + createGroupEndpoint)
jsonBytes, err := json.Marshal(&gs)
@ -189,7 +186,7 @@ func (c *Client) CreateGroup(ctx context.Context, gs GroupSettings, authToken st
}
var resp Group
err = c.doWithAuthToken(ctx, httpReq, &resp, authToken)
err = c.doWithAuthToken(httpReq, &resp)
if err != nil {
return nil, err
}
@ -197,19 +194,18 @@ func (c *Client) CreateGroup(ctx context.Context, gs GroupSettings, authToken st
return &resp, nil
}
/*/// Update ///*/
///// Update /////
/*
UpdateGroup -
# Update a group after creation
Update a group after creation
Parameters:
groupID - required, ID(string)
See GroupSettings
*/
func (c *Client) UpdateGroup(ctx context.Context, groupID ID, gs GroupSettings, authToken string) (*Group, error) {
func (c *Client) UpdateGroup(groupID ID, gs GroupSettings) (*Group, error) {
URL := fmt.Sprintf(c.endpointBase+updateGroupEndpoint, groupID)
jsonBytes, err := json.Marshal(&gs)
@ -223,7 +219,7 @@ func (c *Client) UpdateGroup(ctx context.Context, groupID ID, gs GroupSettings,
}
var resp Group
err = c.doWithAuthToken(ctx, httpReq, &resp, authToken)
err = c.doWithAuthToken(httpReq, &resp)
if err != nil {
return nil, err
}
@ -231,20 +227,19 @@ func (c *Client) UpdateGroup(ctx context.Context, groupID ID, gs GroupSettings,
return &resp, nil
}
/*/// Destroy ///*/
///// Destroy /////
/*
DestroyGroup -
# Disband a group
Disband a group
# This action is only available to the group creator
This action is only available to the group creator
Parameters:
groupID - required, ID(string)
*/
func (c *Client) DestroyGroup(ctx context.Context, groupID ID, authToken string) error {
func (c *Client) DestroyGroup(groupID ID) error {
url := fmt.Sprintf(c.endpointBase+destroyGroupEndpoint, groupID)
httpReq, err := http.NewRequest("POST", url, nil)
@ -252,22 +247,21 @@ func (c *Client) DestroyGroup(ctx context.Context, groupID ID, authToken string)
return err
}
return c.doWithAuthToken(ctx, httpReq, nil, authToken)
return c.doWithAuthToken(httpReq, nil)
}
/*/// Join ///*/
///// Join /////
/*
JoinGroup -
# Join a shared group
Join a shared group
Parameters:
groupID - required, ID(string)
shareToken - required, string
*/
func (c *Client) JoinGroup(ctx context.Context, groupID ID, shareToken string, authToken string) (*Group, error) {
func (c *Client) JoinGroup(groupID ID, shareToken string) (*Group, error) {
URL := fmt.Sprintf(c.endpointBase+joinGroupEndpoint, groupID, shareToken)
httpReq, err := http.NewRequest("POST", URL, nil)
@ -276,7 +270,7 @@ func (c *Client) JoinGroup(ctx context.Context, groupID ID, shareToken string, a
}
var resp Group
err = c.doWithAuthToken(ctx, httpReq, &resp, authToken)
err = c.doWithAuthToken(httpReq, &resp)
if err != nil {
return nil, err
}
@ -284,7 +278,7 @@ func (c *Client) JoinGroup(ctx context.Context, groupID ID, shareToken string, a
return &resp, nil
}
/*/// Rejoin ///*/
///// Rejoin /////
/*
RejoinGroup -
@ -292,10 +286,9 @@ RejoinGroup -
Rejoin a group. Only works if you previously removed yourself.
Parameters:
groupID - required, ID(string)
*/
func (c *Client) RejoinGroup(ctx context.Context, groupID ID, authToken string) (*Group, error) {
func (c *Client) RejoinGroup(groupID ID) (*Group, error) {
URL := fmt.Sprintf(c.endpointBase + rejoinGroupEndpoint)
var data = struct {
@ -315,7 +308,7 @@ func (c *Client) RejoinGroup(ctx context.Context, groupID ID, authToken string)
}
var resp Group
err = c.doWithAuthToken(ctx, httpReq, &resp, authToken)
err = c.doWithAuthToken(httpReq, &resp)
if err != nil {
return nil, err
}
@ -323,10 +316,12 @@ func (c *Client) RejoinGroup(ctx context.Context, groupID ID, authToken string)
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.
@ -335,7 +330,7 @@ the result of change owner action for the request
Parameters: See ChangeOwnerRequest
*/
func (c *Client) ChangeGroupOwner(ctx context.Context, reqs ChangeOwnerRequest, authToken string) (ChangeOwnerResult, error) {
func (c *Client) ChangeGroupOwner(reqs ChangeOwnerRequest) (ChangeOwnerResult, error) {
URL := fmt.Sprintf(c.endpointBase + changeGroupOwnerEndpoint)
var data = struct {
@ -358,7 +353,7 @@ func (c *Client) ChangeGroupOwner(ctx context.Context, reqs ChangeOwnerRequest,
Results []ChangeOwnerResult `json:"results"`
}
err = c.doWithAuthToken(ctx, httpReq, &resp, authToken)
err = c.doWithAuthToken(httpReq, &resp)
if err != nil {
return ChangeOwnerResult{}, err
}
@ -370,25 +365,24 @@ func (c *Client) ChangeGroupOwner(ctx context.Context, reqs ChangeOwnerRequest,
return resp.Results[0], nil
}
type changeOwnerStatusCode string
type ChangeOwnerStatusCode string
// Change owner Status Codes
const (
ChangeOwnerOk changeOwnerStatusCode = "200"
ChangeOwnerRequesterNewOwner changeOwnerStatusCode = "400"
ChangeOwnerNotOwner changeOwnerStatusCode = "403"
ChangeOwnerBadGroupOrOwner changeOwnerStatusCode = "404"
ChangeOwnerBadRequest changeOwnerStatusCode = "405"
ChangeOwner_Ok ChangeOwnerStatusCode = "200"
ChangeOwner_RequesterNewOwner ChangeOwnerStatusCode = "400"
ChangeOwner_NotOwner ChangeOwnerStatusCode = "403"
ChangeOwner_BadGroupOrOwner ChangeOwnerStatusCode = "404"
ChangeOwner_BadRequest ChangeOwnerStatusCode = "405"
)
// String returns the description of the status code according to GroupMe
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",
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",
}[c]
}
@ -411,7 +405,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,8 +1,6 @@
// Package groupme defines a client capable of executing API commands for the GroupMe chat service
package groupme
import (
"context"
"fmt"
"net/http"
"testing"
@ -19,14 +17,11 @@ func (s *GroupsAPISuite) SetupSuite() {
}
func (s *GroupsAPISuite) TestGroupsIndex() {
groups, err := s.client.IndexGroups(
context.Background(),
&GroupsQuery{
groups, err := s.client.IndexGroups(&GroupsQuery{
Page: 5,
PerPage: 20,
Omit: "memberships",
},
)
})
s.Require().NoError(err)
s.Require().NotZero(groups)
for _, group := range groups {
@ -35,7 +30,7 @@ func (s *GroupsAPISuite) TestGroupsIndex() {
}
func (s *GroupsAPISuite) TestGroupsFormer() {
groups, err := s.client.FormerGroups(context.Background())
groups, err := s.client.FormerGroups()
s.Require().NoError(err)
s.Require().NotZero(groups)
for _, group := range groups {
@ -44,28 +39,25 @@ func (s *GroupsAPISuite) TestGroupsFormer() {
}
func (s *GroupsAPISuite) TestGroupsShow() {
group, err := s.client.ShowGroup(context.Background(), "1")
group, err := s.client.ShowGroup("1")
s.Require().NoError(err)
s.Assert().NotZero(group)
}
func (s *GroupsAPISuite) TestGroupsCreate() {
group, err := s.client.CreateGroup(
context.Background(),
GroupSettings{
group, err := s.client.CreateGroup(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(context.Background(), "1", GroupSettings{
group, err := s.client.UpdateGroup("1", GroupSettings{
"Test",
"This is a test group",
"www.blank.com/image",
@ -77,25 +69,24 @@ func (s *GroupsAPISuite) TestGroupsUpdate() {
}
func (s *GroupsAPISuite) TestGroupsDestroy() {
err := s.client.DestroyGroup(context.Background(), "1")
err := s.client.DestroyGroup("1")
s.Require().NoError(err)
}
func (s *GroupsAPISuite) TestGroupsJoin() {
group, err := s.client.JoinGroup(context.Background(), "1", "please")
group, err := s.client.JoinGroup("1", "please")
s.Require().NoError(err)
s.Assert().NotZero(group)
}
func (s *GroupsAPISuite) TestGroupsRejoin() {
group, err := s.client.RejoinGroup(context.Background(), "1")
group, err := s.client.RejoinGroup("1")
s.Require().NoError(err)
s.Assert().NotZero(group)
}
func (s *GroupsAPISuite) TestGroupsChangeOwner() {
result, err := s.client.ChangeGroupOwner(
context.Background(),
ChangeOwnerRequest{
"1",
"123",
@ -108,9 +99,8 @@ 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()

64
json.go
View File

@ -1,4 +1,3 @@
// Package groupme defines a client capable of executing API commands for the GroupMe chat service
package groupme
import (
@ -54,7 +53,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
@ -66,7 +65,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
@ -76,8 +75,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
@ -90,12 +89,10 @@ 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
@ -107,12 +104,10 @@ 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"`
//ChatID - over push ConversationID seems to be called ChatID
ChatID ID `json:"chat_id,omitempty"`
ConversationID ID `json:"conversation_id,omitempty"`
AvatarURL string `json:"avatar_url,omitempty"`
// Maximum length of 1000 characters
@ -123,47 +118,44 @@ 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 (
SenderTypeUser senderType = "user"
SenderTypeBot senderType = "bot"
SenderTypeSystem senderType = "system"
SenderType_User SenderType = "user"
SenderType_Bot SenderType = "bot"
SenderType_System 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
@ -179,8 +171,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,
@ -193,11 +185,10 @@ 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"`
@ -207,11 +198,10 @@ 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,4 +1,3 @@
// Package groupme defines a client capable of executing API commands for the GroupMe chat service
package groupme
import (

View File

@ -1,15 +1,13 @@
// 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"
@ -20,22 +18,34 @@ 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 (
PeriodDay = "day"
PeriodWeek = "week"
PeriodMonth = "month"
Period_Day = "day"
Period_Week = "week"
Period_Month = "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.
func (c *Client) IndexLeaderboard(ctx context.Context, groupID ID, p period, authToken string) ([]*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.
Parameters:
groupID - required, ID(string)
p - required, period(string)
*/
func (c *Client) IndexLeaderboard(groupID ID, p period) ([]*Message, error) {
url := fmt.Sprintf(c.endpointBase+indexLeaderboardEndpoint, groupID)
httpReq, err := http.NewRequest("GET", url, nil)
if err != nil {
@ -44,13 +54,13 @@ func (c *Client) IndexLeaderboard(ctx context.Context, groupID ID, p period, aut
URL := httpReq.URL
query := URL.Query()
query.Set("period", string(p))
query.Set("period", p.String())
URL.RawQuery = query.Encode()
var resp struct {
Messages []*Message `json:"messages"`
}
err = c.doWithAuthToken(ctx, httpReq, &resp, authToken)
err = c.doWithAuthToken(httpReq, &resp)
if err != nil {
return nil, err
}
@ -68,10 +78,9 @@ reverse chrono-order. Note that the payload includes a liked_at
timestamp in ISO-8601 format.
Parameters:
groupID - required, ID(string)
*/
func (c *Client) MyLikesLeaderboard(ctx context.Context, groupID ID, authToken string) ([]*Message, error) {
func (c *Client) MyLikesLeaderboard(groupID ID) ([]*Message, error) {
url := fmt.Sprintf(c.endpointBase+myLikesLeaderboardEndpoint, groupID)
httpReq, err := http.NewRequest("GET", url, nil)
if err != nil {
@ -81,7 +90,7 @@ func (c *Client) MyLikesLeaderboard(ctx context.Context, groupID ID, authToken s
var resp struct {
Messages []*Message `json:"messages"`
}
err = c.doWithAuthToken(ctx, httpReq, &resp, authToken)
err = c.doWithAuthToken(httpReq, &resp)
if err != nil {
return nil, err
}
@ -99,10 +108,9 @@ reverse chrono-order. Note that the payload includes a liked_at
timestamp in ISO-8601 format.
Parameters:
groupID - required, ID(string)
*/
func (c *Client) MyHitsLeaderboard(ctx context.Context, groupID ID, authToken string) ([]*Message, error) {
func (c *Client) MyHitsLeaderboard(groupID ID) ([]*Message, error) {
url := fmt.Sprintf(c.endpointBase+myHitsLeaderboardEndpoint, groupID)
httpReq, err := http.NewRequest("GET", url, nil)
if err != nil {
@ -112,7 +120,7 @@ func (c *Client) MyHitsLeaderboard(ctx context.Context, groupID ID, authToken st
var resp struct {
Messages []*Message `json:"messages"`
}
err = c.doWithAuthToken(ctx, httpReq, &resp, authToken)
err = c.doWithAuthToken(httpReq, &resp)
if err != nil {
return nil, err
}

View File

@ -1,8 +1,6 @@
// Package groupme defines a client capable of executing API commands for the GroupMe chat service
package groupme
import (
"context"
"fmt"
"net/http"
"testing"
@ -19,7 +17,7 @@ func (s *LeaderboardAPISuite) SetupSuite() {
}
func (s *LeaderboardAPISuite) TestLeaderboardIndex() {
messages, err := s.client.IndexLeaderboard(context.Background(), "1", PeriodDay)
messages, err := s.client.IndexLeaderboard("1", Period_Day)
s.Require().NoError(err)
s.Require().NotZero(messages)
for _, message := range messages {
@ -28,7 +26,7 @@ func (s *LeaderboardAPISuite) TestLeaderboardIndex() {
}
func (s *LeaderboardAPISuite) TestLeaderboardMyLikes() {
messages, err := s.client.MyLikesLeaderboard(context.Background(), "1")
messages, err := s.client.MyLikesLeaderboard("1")
s.Require().NoError(err)
s.Require().NotZero(messages)
for _, message := range messages {
@ -37,7 +35,7 @@ func (s *LeaderboardAPISuite) TestLeaderboardMyLikes() {
}
func (s *LeaderboardAPISuite) TestLeaderboardMyHits() {
messages, err := s.client.MyHitsLeaderboard(context.Background(), "1")
messages, err := s.client.MyHitsLeaderboard("1")
s.Require().NoError(err)
s.Require().NotZero(messages)
for _, message := range messages {
@ -49,7 +47,6 @@ 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,15 +1,13 @@
// 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"
@ -18,12 +16,20 @@ const (
destroyLikeEndpoint = likesEndpointRoot + "/unlike" // POST
)
/*//////// API Requests ////////*/
////////// API Requests /////////
// Create
// CreateLike - Like a message.
func (c *Client) CreateLike(ctx context.Context, conversationID, messageID ID, authToken string) error {
/*
CreateLike -
Like a message.
Parameters:
conversationID - required, ID(string)
messageID - required, ID(string)
*/
func (c *Client) CreateLike(conversationID, messageID ID) error {
url := fmt.Sprintf(c.endpointBase+createLikeEndpoint, conversationID, messageID)
httpReq, err := http.NewRequest("POST", url, nil)
@ -31,11 +37,21 @@ func (c *Client) CreateLike(ctx context.Context, conversationID, messageID ID, a
return err
}
return c.doWithAuthToken(ctx, httpReq, nil, authToken)
return c.doWithAuthToken(httpReq, nil)
}
// DestroyLike - Unlike a message.
func (c *Client) DestroyLike(ctx context.Context, conversationID, messageID ID, authToken string) error {
// Destroy
/*
DestroyLike -
Unlike a message.
Parameters:
conversationID - required, ID(string)
messageID - required, ID(string)
*/
func (c *Client) DestroyLike(conversationID, messageID ID) error {
url := fmt.Sprintf(c.endpointBase+destroyLikeEndpoint, conversationID, messageID)
httpReq, err := http.NewRequest("POST", url, nil)
@ -43,5 +59,5 @@ func (c *Client) DestroyLike(ctx context.Context, conversationID, messageID ID,
return err
}
return c.doWithAuthToken(ctx, httpReq, nil, authToken)
return c.doWithAuthToken(httpReq, nil)
}

View File

@ -1,8 +1,6 @@
// Package groupme defines a client capable of executing API commands for the GroupMe chat service
package groupme
import (
"context"
"net/http"
"testing"
@ -18,20 +16,18 @@ func (s *LikesAPISuite) SetupSuite() {
}
func (s *LikesAPISuite) TestLikesCreate() {
err := s.client.CreateLike(context.Background(), "1", "1")
err := s.client.CreateLike("1", "1")
s.Require().NoError(err)
}
func (s *LikesAPISuite) TestLikesDestroy() {
err := s.client.DestroyLike(context.Background(), "1", "1")
err := s.client.DestroyLike("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,4 +1,3 @@
// Package groupme defines a client capable of executing API commands for the GroupMe chat service
package groupme
import (
@ -15,7 +14,7 @@ import (
"github.com/stretchr/testify/suite"
)
/*//////// Base API Suite ////////*/
////////// Base API Suite //////////
type APISuite struct {
// Base attributes
suite.Suite
@ -23,7 +22,7 @@ type APISuite struct {
server *http.Server
wg sync.WaitGroup
// Overridden by child Suite
// Overriden by child Suite
addr string
handler http.Handler
}
@ -43,7 +42,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,
@ -61,7 +60,6 @@ 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
}
@ -69,7 +67,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
@ -78,11 +76,10 @@ 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,9 +1,7 @@
// 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 +9,7 @@ import (
// GroupMe documentation: https://dev.groupme.com/docs/v3#members
/*//////// Endpoints ////////*/
////////// Endpoints //////////
const (
// Used to build other endpoints
membersEndpointRoot = groupEndpointRoot + "/members"
@ -23,7 +21,7 @@ const (
updateMemberEndpoint = groupEndpointRoot + "/memberships/update" // POST
)
/*/// Add ///*/
///// Add /////
/*
AddMembers -
@ -40,7 +38,6 @@ GUIDs can be added to the members parameters. These GUIDs will
be reflected in the membership JSON objects.
Parameters:
groupID - required, ID(string)
See Member.
Nickname - required
@ -49,7 +46,7 @@ Parameters:
PhoneNumber - PhoneNumber(string)
Email - string
*/
func (c *Client) AddMembers(ctx context.Context, groupID ID, authToken string, members ...*Member) (string, error) {
func (c *Client) AddMembers(groupID ID, members ...*Member) (string, error) {
URL := fmt.Sprintf(c.endpointBase+addMembersEndpoint, groupID)
var data = struct {
@ -72,7 +69,7 @@ func (c *Client) AddMembers(ctx context.Context, groupID ID, authToken string, m
ResultsID string `json:"results_id"`
}
err = c.doWithAuthToken(ctx, httpReq, &resp, authToken)
err = c.doWithAuthToken(httpReq, &resp)
if err != nil {
return "", err
}
@ -80,7 +77,7 @@ func (c *Client) AddMembers(ctx context.Context, groupID ID, authToken string, m
return resp.ResultsID, nil
}
/*/// Results ///*/
///// Results /////
/*
AddMembersResults -
@ -95,11 +92,10 @@ Keep in mind that results are temporary -- they will only be
available for 1 hour after the add request.
Parameters:
groupID - required, ID(string)
resultID - required, string
*/
func (c *Client) AddMembersResults(ctx context.Context, groupID ID, resultID string, authToken string) ([]*Member, error) {
func (c *Client) AddMembersResults(groupID ID, resultID string) ([]*Member, error) {
URL := fmt.Sprintf(c.endpointBase+addMembersResultsEndpoint, groupID, resultID)
httpReq, err := http.NewRequest("GET", URL, nil)
@ -111,7 +107,7 @@ func (c *Client) AddMembersResults(ctx context.Context, groupID ID, resultID str
Members []*Member `json:"members"`
}
err = c.doWithAuthToken(ctx, httpReq, &resp, authToken)
err = c.doWithAuthToken(httpReq, &resp)
if err != nil {
return nil, err
}
@ -119,7 +115,7 @@ func (c *Client) AddMembersResults(ctx context.Context, groupID ID, resultID str
return resp.Members, nil
}
/*/// Remove ///*/
///// Remove /////
/*
RemoveMember -
@ -129,11 +125,10 @@ Remove a member (or yourself) from a group.
Note: The creator of the group cannot be removed or exit.
Parameters:
groupID - required, ID(string)
membershipID - required, ID(string). Not the same as userID
*/
func (c *Client) RemoveMember(ctx context.Context, groupID, membershipID ID, authToken string) error {
func (c *Client) RemoveMember(groupID, membershipID ID) error {
URL := fmt.Sprintf(c.endpointBase+removeMemberEndpoint, groupID, membershipID)
httpReq, err := http.NewRequest("POST", URL, nil)
@ -141,10 +136,10 @@ func (c *Client) RemoveMember(ctx context.Context, groupID, membershipID ID, aut
return err
}
return c.doWithAuthToken(ctx, httpReq, nil, authToken)
return c.doWithAuthToken(httpReq, nil)
}
/*/// Update ///*/
///// Update /////
/*
UpdateMember -
@ -152,7 +147,7 @@ UpdateMember -
Update your nickname in a group. The nickname must be
between 1 and 50 characters.
*/
func (c *Client) UpdateMember(ctx context.Context, groupID ID, nickname string, authToken string) (*Member, error) {
func (c *Client) UpdateMember(groupID ID, nickname string) (*Member, error) {
URL := fmt.Sprintf(c.endpointBase+updateMemberEndpoint, groupID)
type Nickname struct {
@ -176,7 +171,7 @@ func (c *Client) UpdateMember(ctx context.Context, groupID ID, nickname string,
var resp Member
err = c.doWithAuthToken(ctx, httpReq, &resp, authToken)
err = c.doWithAuthToken(httpReq, &resp)
if err != nil {
return nil, err
}

View File

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

View File

@ -1,9 +1,7 @@
// 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"
@ -14,7 +12,7 @@ import (
// GroupMe documentation: https://dev.groupme.com/docs/v3#messages
/*//////// Endpoints ////////*/
////////// Endpoints //////////
const (
// Used to build other endpoints
messagesEndpointRoot = groupEndpointRoot + "/messages"
@ -23,7 +21,9 @@ const (
createMessagesEndpoint = messagesEndpointRoot // POST
)
// IndexMessagesQuery defines the optional URL parameters for IndexMessages
// Index
// MessagesQuery 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)
}
// IndexMessagesResponse contains the count and set of
// MessagesIndexResponse contains the count and set of
// messages returned by the IndexMessages API request
type IndexMessagesResponse struct {
Count int `json:"count"`
@ -51,31 +51,41 @@ func (r IndexMessagesResponse) String() string {
}
/*
IndexMessages - Retrieves messages for a group.
IndexMessages -
Retrieve 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(ctx context.Context, groupID ID, req *IndexMessagesQuery, authToken string) (IndexMessagesResponse, error) {
func (c *Client) IndexMessages(groupID ID, req *IndexMessagesQuery) (IndexMessagesResponse, error) {
url := fmt.Sprintf(c.endpointBase+indexMessagesEndpoint, groupID)
httpReq, err := http.NewRequest("GET", url, nil)
if err != nil {
@ -101,7 +111,7 @@ func (c *Client) IndexMessages(ctx context.Context, groupID ID, req *IndexMessag
URL.RawQuery = query.Encode()
var resp IndexMessagesResponse
err = c.doWithAuthToken(ctx, httpReq, &resp, authToken)
err = c.doWithAuthToken(httpReq, &resp)
if err != nil {
return IndexMessagesResponse{}, err
}
@ -109,8 +119,11 @@ func (c *Client) IndexMessages(ctx context.Context, groupID ID, req *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.
@ -124,8 +137,19 @@ 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(ctx context.Context, groupID ID, m *Message, authToken string) (*Message, error) {
func (c *Client) CreateMessage(groupID ID, m *Message) (*Message, error) {
URL := fmt.Sprintf(c.endpointBase+createMessagesEndpoint, groupID)
m.SourceGUID = uuid.New().String()
@ -148,7 +172,7 @@ func (c *Client) CreateMessage(ctx context.Context, groupID ID, m *Message, auth
var resp struct {
*Message `json:"message"`
}
err = c.doWithAuthToken(ctx, httpReq, &resp, authToken)
err = c.doWithAuthToken(httpReq, &resp)
if err != nil {
return nil, err
}

View File

@ -1,8 +1,6 @@
// Package groupme defines a client capable of executing API commands for the GroupMe chat service
package groupme
import (
"context"
"fmt"
"net/http"
"testing"
@ -20,7 +18,6 @@ func (s *MessagesAPISuite) SetupSuite() {
func (s *MessagesAPISuite) TestMessagesIndex() {
resp, err := s.client.IndexMessages(
context.Background(),
ID("123"),
&IndexMessagesQuery{
BeforeID: "0123456789",
@ -38,7 +35,6 @@ func (s *MessagesAPISuite) TestMessagesIndex() {
func (s *MessagesAPISuite) TestMessagesCreate() {
message, err := s.client.CreateMessage(
context.Background(),
ID("123"),
&Message{
Text: "Test",
@ -53,7 +49,6 @@ 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,196 +0,0 @@
package groupme
import (
"context"
"errors"
"gitea.watsonlabs.net/watsonb8/fayec"
"gitea.watsonlabs.net/watsonb8/fayec/message"
"gitea.watsonlabs.net/watsonb8/fayec/subscription"
"log"
"strings"
"sync"
"time"
)
const (
PushServer = "wss://push.groupme.com/faye"
userChannel = "/user/"
groupChannel = "/group/"
dmChannel = "/direct_message/"
)
var (
ErrHandlerNotFound = errors.New("Handler not found")
ErrListenerNotStarted = errors.New("GroupMe listener not started")
)
var concur = sync.Mutex{}
type HandlerAll interface {
Handler
//of self
HandlerText
HandlerLike
HandlerMembership
//of group
HandleGroupTopic
HandleGroupAvatar
HandleGroupName
HandleGroupLikeIcon
//of group members
HandleMemberNewNickname
HandleMemberNewAvatar
HandleMembers
}
type Handler interface {
HandleError(error)
}
type HandlerText interface {
HandleTextMessage(Message)
}
type HandlerLike interface {
HandleLike(Message)
}
type HandlerMembership interface {
HandleJoin(ID)
}
// Group Handlers
type HandleGroupTopic interface {
HandleGroupTopic(group ID, newTopic string)
}
type HandleGroupName interface {
HandleGroupName(group ID, newName string)
}
type HandleGroupAvatar interface {
HandleGroupAvatar(group ID, newAvatar string)
}
type HandleGroupLikeIcon interface {
HandleLikeIcon(group ID, PackID, PackIndex int, Type string)
}
// Group member handlers
type HandleMemberNewNickname interface {
HandleNewNickname(group ID, user ID, newName string)
}
type HandleMemberNewAvatar interface {
HandleNewAvatarInGroup(group ID, user ID, avatarURL string)
}
type HandleMembers interface {
//HandleNewMembers returns only partial member with id and nickname; added is false if removing
HandleMembers(group ID, members []Member, added bool)
}
// PushSubscription manages real time subscription
type PushSubscription struct {
channel chan message.Data
client *fayec.Client
handlers map[string][]Handler // key == token
LastConnected int64
}
// NewPushSubscription creates and returns a push subscription object
func NewPushSubscription(context context.Context) PushSubscription {
r := PushSubscription{
channel: make(chan message.Data),
handlers: make(map[string][]Handler),
}
return r
}
func (r *PushSubscription) AddHandler(h Handler, authToken string) {
if r.handlers[authToken] == nil {
r.handlers[authToken] = []Handler{h}
} else {
r.handlers[authToken] = append(r.handlers[authToken], h)
}
//r.handlers = append(r.handlers, h)
}
// AddFullHandler is the same as AddHandler except it ensures the interface implements everything
func (r *PushSubscription) AddFullHandler(h HandlerAll, authToken string) {
if r.handlers[authToken] == nil {
r.handlers[authToken] = []Handler{h}
} else {
r.handlers[authToken] = append(r.handlers[authToken], h)
}
//r.handlers = append(r.handlers, h)
}
var RealTimeHandlers map[string]func(r *PushSubscription, channel string, authToken string, data ...interface{})
var RealTimeSystemHandlers map[string]func(r *PushSubscription, channel string, id ID, authToken string, rawData []byte)
// Listen connects to GroupMe. Runs in Goroutine.
func (r *PushSubscription) Connect(context context.Context) error {
c, err := fayec.NewClient(PushServer)
if err != nil {
return err
}
r.client = c
return nil
}
// SubscribeToUser to users
func (r *PushSubscription) SubscribeToUser(context context.Context, id ID, authToken string) error {
return r.subscribeWithPrefix(userChannel, context, id, authToken)
}
// SubscribeToGroup to groups for typing notification
func (r *PushSubscription) SubscribeToGroup(context context.Context, id ID, authToken string) error {
return r.subscribeWithPrefix(groupChannel, context, id, authToken)
}
// SubscribeToDM to users
func (r *PushSubscription) SubscribeToDM(context context.Context, id ID, authToken string) error {
id = ID(strings.Replace(id.String(), "+", "_", 1))
return r.subscribeWithPrefix(dmChannel, context, id, authToken)
}
func (r *PushSubscription) subscribeWithPrefix(prefix string, context context.Context, groupID ID, authToken string) error {
concur.Lock()
defer concur.Unlock()
if r.client == nil {
return ErrListenerNotStarted
}
var sub *subscription.Subscription
sub, err := r.client.Subscribe(prefix+groupID.String(), authToken)
if err != nil {
panic(err)
}
err = sub.OnMessage(func(channel string, data message.Data) {
r.LastConnected = time.Now().Unix()
dataMap := data.(map[string]interface{})
content := dataMap["subject"]
contentType := dataMap["type"].(string)
handler, ok := RealTimeHandlers[contentType]
if !ok {
if contentType == "ping" ||
len(contentType) == 0 ||
content == "" {
return
}
log.Println("Unable to handle GroupMe message type", contentType)
} else {
handler(r, channel, authToken, content)
}
})
return nil
}
// Connected check if connected
func (r *PushSubscription) Connected() bool {
return r.LastConnected+30 >= time.Now().Unix()
}

View File

@ -1,266 +0,0 @@
package groupme
import (
"encoding/json"
"fmt"
"log"
"strconv"
)
func init() {
RealTimeHandlers = make(map[string]func(r *PushSubscription, channel string, authToken string, data ...interface{}))
//Base Handlers on user channel
RealTimeHandlers["direct_message.create"] = func(r *PushSubscription, channel string, authToken string, data ...interface{}) {
b, _ := json.Marshal(data[0])
out := Message{}
_ = json.Unmarshal(b, &out)
//maybe something with API versioning
out.ConversationID = out.ChatID
if out.UserID.String() == "system" {
event := struct {
Event struct {
Kind string `json:"type"`
Data interface{}
}
}{}
err := json.Unmarshal(b, &event)
if err != nil {
fmt.Println(err)
}
rawData, _ := json.Marshal(event.Event.Data)
handler, ok := RealTimeSystemHandlers[event.Event.Kind]
if !ok {
log.Println("Unable to handle system message of type", event.Event.Kind)
return
}
id := out.GroupID
if len(id) == 0 {
id = out.ConversationID
}
handler(r, channel, id, authToken, rawData)
return
}
handlers := r.handlers[authToken]
for _, h := range handlers {
if h, ok := h.(HandlerText); ok {
h.HandleTextMessage(out)
}
}
}
RealTimeHandlers["line.create"] = RealTimeHandlers["direct_message.create"]
RealTimeHandlers["like.create"] = func(r *PushSubscription, channel string, authToken string, data ...interface{}) { //should be an associated chatEvent
}
RealTimeHandlers["membership.create"] = func(r *PushSubscription, channel string, authToken string, data ...interface{}) {
c, _ := data[0].(map[string]interface{})
id, _ := c["id"].(string)
handlers := r.handlers[authToken]
for _, h := range handlers {
if h, ok := h.(HandlerMembership); ok {
h.HandleJoin(ID(id))
}
}
}
//following are for each chat
RealTimeHandlers["favorite"] = func(r *PushSubscription, channel string, authToken string, data ...interface{}) {
c, ok := data[0].(map[string]interface{})
if !ok {
fmt.Println(data, "err")
return
}
e, ok := c["line"]
if !ok {
fmt.Println(data, "err")
return
}
d, _ := json.Marshal(e)
msg := Message{}
_ = json.Unmarshal(d, &msg)
handlers := r.handlers[authToken]
for _, h := range handlers {
if h, ok := h.(HandlerLike); ok {
h.HandleLike(msg)
}
}
}
//following are for messages from system (administrative/settings changes)
RealTimeSystemHandlers = make(map[string]func(r *PushSubscription, channel string, id ID, authToken string, rawData []byte))
RealTimeSystemHandlers["membership.nickname_changed"] = func(r *PushSubscription, channel string, id ID, authToken string, rawData []byte) {
thing := struct {
Name string
User struct {
ID int
}
}{}
_ = json.Unmarshal(rawData, &thing)
handlers := r.handlers[authToken]
for _, h := range handlers {
if h, ok := h.(HandleMemberNewNickname); ok {
h.HandleNewNickname(id, ID(strconv.Itoa(thing.User.ID)), thing.Name)
}
}
}
RealTimeSystemHandlers["membership.avatar_changed"] = func(r *PushSubscription, channel string, id ID, authToken string, rawData []byte) {
content := struct {
AvatarURL string `json:"avatar_url"`
User struct {
ID int
}
}{}
_ = json.Unmarshal(rawData, &content)
handlers := r.handlers[authToken]
for _, h := range handlers {
if h, ok := h.(HandleMemberNewAvatar); ok {
h.HandleNewAvatarInGroup(id, ID(strconv.Itoa(content.User.ID)), content.AvatarURL)
}
}
}
RealTimeSystemHandlers["membership.announce.added"] = func(r *PushSubscription, channel string, id ID, authToken string, rawData []byte) {
data := struct {
Added []Member `json:"added_users"`
}{}
_ = json.Unmarshal(rawData, &data)
handlers := r.handlers[authToken]
for _, h := range handlers {
if h, ok := h.(HandleMembers); ok {
h.HandleMembers(id, data.Added, true)
}
}
}
RealTimeSystemHandlers["membership.notifications.removed"] = func(r *PushSubscription, channel string, id ID, authToken string, rawData []byte) {
data := struct {
Added Member `json:"removed_user"`
}{}
_ = json.Unmarshal(rawData, &data)
handlers := r.handlers[authToken]
for _, h := range handlers {
if h, ok := h.(HandleMembers); ok {
h.HandleMembers(id, []Member{data.Added}, false)
}
}
}
RealTimeSystemHandlers["membership.name_change"] = func(r *PushSubscription, channel string, id ID, authToken string, rawData []byte) {
data := struct {
Name string
}{}
_ = json.Unmarshal(rawData, &data)
handlers := r.handlers[authToken]
for _, h := range handlers {
if h, ok := h.(HandleGroupName); ok {
h.HandleGroupName(id, data.Name)
}
}
}
RealTimeSystemHandlers["group.name_change"] = func(r *PushSubscription, channel string, id ID, authToken string, rawData []byte) {
data := struct {
Name string
}{}
_ = json.Unmarshal(rawData, &data)
handlers := r.handlers[authToken]
for _, h := range handlers {
if h, ok := h.(HandleGroupName); ok {
h.HandleGroupName(id, data.Name)
}
}
}
RealTimeSystemHandlers["group.topic_change"] = func(r *PushSubscription, channel string, id ID, authToken string, rawData []byte) {
data := struct {
Topic string
}{}
_ = json.Unmarshal(rawData, &data)
handlers := r.handlers[authToken]
for _, h := range handlers {
if h, ok := h.(HandleGroupTopic); ok {
h.HandleGroupTopic(id, data.Topic)
}
}
}
RealTimeSystemHandlers["group.avatar_change"] = func(r *PushSubscription, channel string, id ID, authToken string, rawData []byte) {
data := struct {
AvatarURL string `json:"avatar_url"`
}{}
_ = json.Unmarshal(rawData, &data)
handlers := r.handlers[authToken]
for _, h := range handlers {
if h, ok := h.(HandleGroupAvatar); ok {
h.HandleGroupAvatar(id, data.AvatarURL)
}
}
}
RealTimeSystemHandlers["group.like_icon_set"] = func(r *PushSubscription, channel string, id ID, authToken string, rawData []byte) {
data := struct {
LikeIcon struct {
PackID int `json:"pack_id"`
PackIndex int `json:"pack_index"`
Type string
} `json:"like_icon"`
}{}
_ = json.Unmarshal(rawData, &data)
handlers := r.handlers[authToken]
for _, h := range handlers {
if h, ok := h.(HandleGroupLikeIcon); ok {
h.HandleLikeIcon(id, data.LikeIcon.PackID, data.LikeIcon.PackIndex, data.LikeIcon.Type)
}
}
}
RealTimeSystemHandlers["group.like_icon_removed"] = func(r *PushSubscription, channel string, id ID, authToken string, rawData []byte) {
handlers := r.handlers[authToken]
for _, h := range handlers {
if h, ok := h.(HandleGroupLikeIcon); ok {
h.HandleLikeIcon(id, 0, 0, "")
}
}
}
}

View File

@ -1,9 +1,7 @@
// 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 +9,7 @@ import (
// GroupMe documentation: https://dev.groupme.com/docs/v3#sms_mode
/*//////// Endpoints ////////*/
////////// Endpoints //////////
const (
// Used to build other endpoints
smsModeEndpointRoot = usersEndpointRoot + "/sms_mode"
@ -21,7 +19,7 @@ const (
deleteSMSModeEndpoint = smsModeEndpointRoot + "/delete" // POST
)
/*//////// API Requests ////////*/
////////// API Requests //////////
// Create
@ -31,14 +29,13 @@ Enables SMS mode for N hours, where N is at most 48. After N
hours have elapsed, user will receive push notfications.
Parameters:
duration - required, integer
registration_id - string; The push notification ID/token
that should be suppressed during SMS mode. If this is
omitted, both SMS and push notifications will be
delivered to the device.
*/
func (c *Client) CreateSMSMode(ctx context.Context, duration int, registrationID *ID, authToken string) error {
func (c *Client) CreateSMSMode(duration int, registrationID *ID) error {
URL := fmt.Sprintf(c.endpointBase + createSMSModeEndpoint)
var data = struct {
@ -59,7 +56,7 @@ func (c *Client) CreateSMSMode(ctx context.Context, duration int, registrationID
return err
}
err = c.doWithAuthToken(ctx, httpReq, nil, authToken)
err = c.doWithAuthToken(httpReq, nil)
if err != nil {
return err
}
@ -74,7 +71,7 @@ DeleteSMSMode -
Disables SMS mode
*/
func (c *Client) DeleteSMSMode(ctx context.Context, authToken string) error {
func (c *Client) DeleteSMSMode() error {
url := fmt.Sprintf(c.endpointBase + deleteSMSModeEndpoint)
httpReq, err := http.NewRequest("POST", url, nil)
@ -82,5 +79,5 @@ func (c *Client) DeleteSMSMode(ctx context.Context, authToken string) error {
return err
}
return c.doWithAuthToken(ctx, httpReq, nil, authToken)
return c.doWithAuthToken(httpReq, nil)
}

View File

@ -1,8 +1,6 @@
// Package groupme defines a client capable of executing API commands for the GroupMe chat service
package groupme
import (
"context"
"net/http"
"testing"
@ -18,17 +16,16 @@ func (s *SMSModeAPISuite) SetupSuite() {
}
func (s *SMSModeAPISuite) TestSMSModeCreate() {
s.Assert().NoError(s.client.CreateSMSMode(context.Background(), 10, nil))
s.Assert().NoError(s.client.CreateSMSMode(10, nil))
}
func (s *SMSModeAPISuite) TestSMSModeDelete() {
s.Assert().NoError(s.client.DeleteSMSMode(context.Background()))
s.Assert().NoError(s.client.DeleteSMSMode())
}
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,9 +1,7 @@
// 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 +9,7 @@ import (
// GroupMe documentation: https://dev.groupme.com/docs/v3#users
/*//////// Endpoints ////////*/
////////// Endpoints //////////
const (
// Used to build other endpoints
usersEndpointRoot = "/users"
@ -21,7 +19,7 @@ const (
updateMyUserEndpoint = usersEndpointRoot + "/update" // POST
)
/*//////// API Requests ////////*/
////////// API Requests //////////
// Me
@ -31,10 +29,9 @@ MyUser -
Loads a specific group.
Parameters:
groupID - required, ID(string)
*/
func (c *Client) MyUser(ctx context.Context, authToken string) (*User, error) {
func (c *Client) MyUser() (*User, error) {
URL := fmt.Sprintf(c.endpointBase + myUserEndpoint)
httpReq, err := http.NewRequest("GET", URL, nil)
@ -43,7 +40,7 @@ func (c *Client) MyUser(ctx context.Context, authToken string) (*User, error) {
}
var resp User
err = c.doWithAuthToken(ctx, httpReq, &resp, authToken)
err = c.doWithAuthToken(httpReq, &resp)
if err != nil {
return nil, err
}
@ -51,7 +48,8 @@ func (c *Client) MyUser(ctx context.Context, authToken string) (*User, error) {
return &resp, nil
}
// UserSettings are the settings for a GroupMe user
// Update
type UserSettings struct {
// URL to valid JPG/PNG/GIF image. URL will be converted into
// an image service link (https://i.groupme.com/....)
@ -66,11 +64,11 @@ type UserSettings struct {
/*
UpdateMyUser -
# Update attributes about your own account
Update attributes about your own account
Parameters: See UserSettings
*/
func (c *Client) UpdateMyUser(ctx context.Context, us UserSettings, authToken string) (*User, error) {
func (c *Client) UpdateMyUser(us UserSettings) (*User, error) {
URL := fmt.Sprintf(c.endpointBase + updateMyUserEndpoint)
jsonBytes, err := json.Marshal(&us)
@ -84,7 +82,7 @@ func (c *Client) UpdateMyUser(ctx context.Context, us UserSettings, authToken st
}
var resp User
err = c.doWithAuthToken(ctx, httpReq, &resp, authToken)
err = c.doWithAuthToken(httpReq, &resp)
if err != nil {
return nil, err
}

View File

@ -1,8 +1,6 @@
// Package groupme defines a client capable of executing API commands for the GroupMe chat service
package groupme
import (
"context"
"fmt"
"net/http"
"testing"
@ -19,13 +17,13 @@ func (s *UsersAPISuite) SetupSuite() {
}
func (s *UsersAPISuite) TestUsersMe() {
user, err := s.client.MyUser(context.Background())
user, err := s.client.MyUser()
s.Require().NoError(err)
s.Assert().NotZero(user)
}
func (s *UsersAPISuite) TestUsersUpdate() {
user, err := s.client.UpdateMyUser(context.Background(), UserSettings{})
user, err := s.client.UpdateMyUser(UserSettings{})
s.Require().NoError(err)
s.Assert().NotZero(user)
}
@ -33,8 +31,6 @@ 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()