420 lines
		
	
	
		
			9.8 KiB
		
	
	
	
		
			Go
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			420 lines
		
	
	
		
			9.8 KiB
		
	
	
	
		
			Go
		
	
	
		
			Executable File
		
	
	
	
	
// Package groupme defines a client capable of executing API commands for the GroupMe chat service
 | 
						|
package groupme
 | 
						|
 | 
						|
import (
 | 
						|
	"bytes"
 | 
						|
	"context"
 | 
						|
	"encoding/json"
 | 
						|
	"errors"
 | 
						|
	"fmt"
 | 
						|
	"net/http"
 | 
						|
	"strconv"
 | 
						|
)
 | 
						|
 | 
						|
// GroupMe documentation: https://dev.groupme.com/docs/v3#groups
 | 
						|
 | 
						|
/*//////// Endpoints ////////*/
 | 
						|
const (
 | 
						|
	// Used to build other endpoints
 | 
						|
	groupsEndpointRoot = "/groups"
 | 
						|
	groupEndpointRoot  = "/groups/%s"
 | 
						|
 | 
						|
	// Actual Endpoints
 | 
						|
	indexGroupsEndpoint      = groupsEndpointRoot                    // GET
 | 
						|
	formerGroupsEndpoint     = groupsEndpointRoot + "/former"        // GET
 | 
						|
	showGroupEndpoint        = groupEndpointRoot                     // GET
 | 
						|
	createGroupEndpoint      = groupsEndpointRoot                    // POST
 | 
						|
	updateGroupEndpoint      = groupEndpointRoot + "/update"         // POST
 | 
						|
	destroyGroupEndpoint     = groupEndpointRoot + "/destroy"        // POST
 | 
						|
	joinGroupEndpoint        = groupEndpointRoot + "/join/%s"        // POST
 | 
						|
	rejoinGroupEndpoint      = groupsEndpointRoot + "/join"          // POST
 | 
						|
	changeGroupOwnerEndpoint = groupsEndpointRoot + "/change_owners" // POST
 | 
						|
)
 | 
						|
 | 
						|
/*//////// Common Request Parameters ////////*/
 | 
						|
 | 
						|
// GroupSettings is the settings for a group, used by CreateGroup and UpdateGroup
 | 
						|
type GroupSettings struct {
 | 
						|
	// Required. Primary name of the group. Maximum 140 characters
 | 
						|
	Name string `json:"name"`
 | 
						|
	// A subheading for the group. Maximum 255 characters
 | 
						|
	Description string `json:"description"`
 | 
						|
	// GroupMe Image Service URL
 | 
						|
	ImageURL string `json:"image_url"`
 | 
						|
	// Defaults false. If true, disables notifications for all members.
 | 
						|
	// Documented for use only for UpdateGroup
 | 
						|
	OfficeMode bool `json:"office_mode"`
 | 
						|
	// Defaults false. If true, generates a share URL.
 | 
						|
	// Anyone with the URL can join the group
 | 
						|
	Share bool `json:"share"`
 | 
						|
}
 | 
						|
 | 
						|
func (gss GroupSettings) String() string {
 | 
						|
	return marshal(&gss)
 | 
						|
}
 | 
						|
 | 
						|
/*//////// API Requests ////////*/
 | 
						|
 | 
						|
/*/// Index ///*/
 | 
						|
 | 
						|
// GroupsQuery defines optional URL parameters for IndexGroups
 | 
						|
type GroupsQuery struct {
 | 
						|
	// Fetch a particular page of results. Defaults to 1.
 | 
						|
	Page int `json:"page"`
 | 
						|
	// Define page size. Defaults to 10.
 | 
						|
	PerPage int `json:"per_page"`
 | 
						|
	// Comma separated list of data to omit from output.
 | 
						|
	// Currently supported value is only "memberships".
 | 
						|
	// If used then response will contain empty (null) members field.
 | 
						|
	Omit string `json:"omit"`
 | 
						|
}
 | 
						|
 | 
						|
func (q GroupsQuery) String() string {
 | 
						|
	return marshal(&q)
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
IndexGroups -
 | 
						|
 | 
						|
List the authenticated user's active groups.
 | 
						|
 | 
						|
The response is paginated, with a default of 10 groups per page.
 | 
						|
 | 
						|
Please consider using of omit=memberships parameter. Not including
 | 
						|
member lists might significantly improve user experience of your
 | 
						|
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) {
 | 
						|
	httpReq, err := http.NewRequest("GET", c.endpointBase+indexGroupsEndpoint, nil)
 | 
						|
	if err != nil {
 | 
						|
		return nil, err
 | 
						|
	}
 | 
						|
 | 
						|
	URL := httpReq.URL
 | 
						|
	query := URL.Query()
 | 
						|
	if req != nil {
 | 
						|
		if req.Page != 0 {
 | 
						|
			query.Set("page", strconv.Itoa(req.Page))
 | 
						|
		}
 | 
						|
		if req.PerPage != 0 {
 | 
						|
			query.Set("per_page", strconv.Itoa(req.PerPage))
 | 
						|
		}
 | 
						|
		if req.Omit != "" {
 | 
						|
			query.Set("omit", req.Omit)
 | 
						|
		}
 | 
						|
	}
 | 
						|
	URL.RawQuery = query.Encode()
 | 
						|
 | 
						|
	var resp []*Group
 | 
						|
	err = c.doWithAuthToken(ctx, httpReq, &resp, authToken)
 | 
						|
	if err != nil {
 | 
						|
		return nil, err
 | 
						|
	}
 | 
						|
 | 
						|
	return resp, nil
 | 
						|
}
 | 
						|
 | 
						|
/*/// Former ///*/
 | 
						|
 | 
						|
/*
 | 
						|
FormerGroups -
 | 
						|
 | 
						|
List they groups you have left but can rejoin.
 | 
						|
*/
 | 
						|
func (c *Client) FormerGroups(ctx context.Context, authToken string) ([]*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)
 | 
						|
	if err != nil {
 | 
						|
		return nil, err
 | 
						|
	}
 | 
						|
 | 
						|
	return resp, nil
 | 
						|
}
 | 
						|
 | 
						|
/*/// Show ///*/
 | 
						|
 | 
						|
/*
 | 
						|
ShowGroup -
 | 
						|
 | 
						|
Loads a specific group.
 | 
						|
 | 
						|
Parameters:
 | 
						|
 | 
						|
	groupID - required, ID(string)
 | 
						|
*/
 | 
						|
func (c *Client) ShowGroup(ctx context.Context, groupID ID, authToken string) (*Group, error) {
 | 
						|
	URL := fmt.Sprintf(c.endpointBase+showGroupEndpoint, groupID)
 | 
						|
 | 
						|
	httpReq, err := http.NewRequest("GET", URL, nil)
 | 
						|
	if err != nil {
 | 
						|
		return nil, err
 | 
						|
	}
 | 
						|
 | 
						|
	var resp Group
 | 
						|
	err = c.doWithAuthToken(ctx, httpReq, &resp, authToken)
 | 
						|
	if err != nil {
 | 
						|
		return nil, err
 | 
						|
	}
 | 
						|
 | 
						|
	return &resp, nil
 | 
						|
}
 | 
						|
 | 
						|
/*/// Create ///*/
 | 
						|
 | 
						|
/*
 | 
						|
CreateGroup -
 | 
						|
 | 
						|
# Create a new group
 | 
						|
 | 
						|
Parameters: See GroupSettings
 | 
						|
*/
 | 
						|
func (c *Client) CreateGroup(ctx context.Context, gs GroupSettings, authToken string) (*Group, error) {
 | 
						|
	URL := fmt.Sprintf(c.endpointBase + createGroupEndpoint)
 | 
						|
 | 
						|
	jsonBytes, err := json.Marshal(&gs)
 | 
						|
	if err != nil {
 | 
						|
		return nil, err
 | 
						|
	}
 | 
						|
 | 
						|
	httpReq, err := http.NewRequest("POST", URL, bytes.NewBuffer(jsonBytes))
 | 
						|
	if err != nil {
 | 
						|
		return nil, err
 | 
						|
	}
 | 
						|
 | 
						|
	var resp Group
 | 
						|
	err = c.doWithAuthToken(ctx, httpReq, &resp, authToken)
 | 
						|
	if err != nil {
 | 
						|
		return nil, err
 | 
						|
	}
 | 
						|
 | 
						|
	return &resp, nil
 | 
						|
}
 | 
						|
 | 
						|
/*/// Update ///*/
 | 
						|
 | 
						|
/*
 | 
						|
UpdateGroup -
 | 
						|
 | 
						|
# 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) {
 | 
						|
	URL := fmt.Sprintf(c.endpointBase+updateGroupEndpoint, groupID)
 | 
						|
 | 
						|
	jsonBytes, err := json.Marshal(&gs)
 | 
						|
	if err != nil {
 | 
						|
		return nil, err
 | 
						|
	}
 | 
						|
 | 
						|
	httpReq, err := http.NewRequest("POST", URL, bytes.NewBuffer(jsonBytes))
 | 
						|
	if err != nil {
 | 
						|
		return nil, err
 | 
						|
	}
 | 
						|
 | 
						|
	var resp Group
 | 
						|
	err = c.doWithAuthToken(ctx, httpReq, &resp, authToken)
 | 
						|
	if err != nil {
 | 
						|
		return nil, err
 | 
						|
	}
 | 
						|
 | 
						|
	return &resp, nil
 | 
						|
}
 | 
						|
 | 
						|
/*/// Destroy ///*/
 | 
						|
 | 
						|
/*
 | 
						|
DestroyGroup -
 | 
						|
 | 
						|
# Disband a group
 | 
						|
 | 
						|
# 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 {
 | 
						|
	url := fmt.Sprintf(c.endpointBase+destroyGroupEndpoint, groupID)
 | 
						|
 | 
						|
	httpReq, err := http.NewRequest("POST", url, nil)
 | 
						|
	if err != nil {
 | 
						|
		return err
 | 
						|
	}
 | 
						|
 | 
						|
	return c.doWithAuthToken(ctx, httpReq, nil, authToken)
 | 
						|
}
 | 
						|
 | 
						|
/*/// Join ///*/
 | 
						|
 | 
						|
/*
 | 
						|
JoinGroup -
 | 
						|
 | 
						|
# 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) {
 | 
						|
	URL := fmt.Sprintf(c.endpointBase+joinGroupEndpoint, groupID, shareToken)
 | 
						|
 | 
						|
	httpReq, err := http.NewRequest("POST", URL, nil)
 | 
						|
	if err != nil {
 | 
						|
		return nil, err
 | 
						|
	}
 | 
						|
 | 
						|
	var resp Group
 | 
						|
	err = c.doWithAuthToken(ctx, httpReq, &resp, authToken)
 | 
						|
	if err != nil {
 | 
						|
		return nil, err
 | 
						|
	}
 | 
						|
 | 
						|
	return &resp, nil
 | 
						|
}
 | 
						|
 | 
						|
/*/// Rejoin ///*/
 | 
						|
 | 
						|
/*
 | 
						|
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) {
 | 
						|
	URL := fmt.Sprintf(c.endpointBase + rejoinGroupEndpoint)
 | 
						|
 | 
						|
	var data = struct {
 | 
						|
		GroupID ID `json:"group_id"`
 | 
						|
	}{
 | 
						|
		groupID,
 | 
						|
	}
 | 
						|
 | 
						|
	jsonBytes, err := json.Marshal(&data)
 | 
						|
	if err != nil {
 | 
						|
		return nil, err
 | 
						|
	}
 | 
						|
 | 
						|
	httpReq, err := http.NewRequest("POST", URL, bytes.NewBuffer(jsonBytes))
 | 
						|
	if err != nil {
 | 
						|
		return nil, err
 | 
						|
	}
 | 
						|
 | 
						|
	var resp Group
 | 
						|
	err = c.doWithAuthToken(ctx, httpReq, &resp, authToken)
 | 
						|
	if err != nil {
 | 
						|
		return nil, err
 | 
						|
	}
 | 
						|
 | 
						|
	return &resp, nil
 | 
						|
}
 | 
						|
 | 
						|
/*/// Change Owner ///*/
 | 
						|
 | 
						|
/*
 | 
						|
ChangeGroupOwner - Change owner of requested groups.
 | 
						|
 | 
						|
This action is only available to the group creator.
 | 
						|
 | 
						|
Response is a result object which contain status field,
 | 
						|
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) {
 | 
						|
	URL := fmt.Sprintf(c.endpointBase + changeGroupOwnerEndpoint)
 | 
						|
 | 
						|
	var data = struct {
 | 
						|
		Requests []ChangeOwnerRequest `json:"requests"`
 | 
						|
	}{
 | 
						|
		[]ChangeOwnerRequest{reqs},
 | 
						|
	}
 | 
						|
 | 
						|
	jsonBytes, err := json.Marshal(&data)
 | 
						|
	if err != nil {
 | 
						|
		return ChangeOwnerResult{}, err
 | 
						|
	}
 | 
						|
 | 
						|
	httpReq, err := http.NewRequest("POST", URL, bytes.NewBuffer(jsonBytes))
 | 
						|
	if err != nil {
 | 
						|
		return ChangeOwnerResult{}, err
 | 
						|
	}
 | 
						|
 | 
						|
	var resp struct {
 | 
						|
		Results []ChangeOwnerResult `json:"results"`
 | 
						|
	}
 | 
						|
 | 
						|
	err = c.doWithAuthToken(ctx, httpReq, &resp, authToken)
 | 
						|
	if err != nil {
 | 
						|
		return ChangeOwnerResult{}, err
 | 
						|
	}
 | 
						|
 | 
						|
	if len(resp.Results) < 1 {
 | 
						|
		return ChangeOwnerResult{}, errors.New("failed to parse results")
 | 
						|
	}
 | 
						|
 | 
						|
	return resp.Results[0], nil
 | 
						|
}
 | 
						|
 | 
						|
type changeOwnerStatusCode string
 | 
						|
 | 
						|
// Change owner Status Codes
 | 
						|
const (
 | 
						|
	ChangeOwnerOk                changeOwnerStatusCode = "200"
 | 
						|
	ChangeOwnerRequesterNewOwner changeOwnerStatusCode = "400"
 | 
						|
	ChangeOwnerNotOwner          changeOwnerStatusCode = "403"
 | 
						|
	ChangeOwnerBadGroupOrOwner   changeOwnerStatusCode = "404"
 | 
						|
	ChangeOwnerBadRequest        changeOwnerStatusCode = "405"
 | 
						|
)
 | 
						|
 | 
						|
// String returns the description of the status code according to GroupMe
 | 
						|
func (c changeOwnerStatusCode) String() string {
 | 
						|
	return map[changeOwnerStatusCode]string{
 | 
						|
		ChangeOwnerOk:                "success",
 | 
						|
		ChangeOwnerRequesterNewOwner: "requester is also a new owner",
 | 
						|
		ChangeOwnerNotOwner:          "requester is not the owner of the group",
 | 
						|
		ChangeOwnerBadGroupOrOwner:   "group or new owner not found or new owner is not member of the group",
 | 
						|
		ChangeOwnerBadRequest:        "request object is missing required field or any of the required fields is not an ID",
 | 
						|
	}[c]
 | 
						|
}
 | 
						|
 | 
						|
// ChangeOwnerRequest defines the new owner of a group
 | 
						|
type ChangeOwnerRequest struct {
 | 
						|
	// Required
 | 
						|
	GroupID string `json:"group_id"`
 | 
						|
	// Required. UserId of the new owner of the group
 | 
						|
	// who must be an active member of the group
 | 
						|
	OwnerID string `json:"owner_id"`
 | 
						|
}
 | 
						|
 | 
						|
func (r ChangeOwnerRequest) String() string {
 | 
						|
	return marshal(&r)
 | 
						|
}
 | 
						|
 | 
						|
// ChangeOwnerResult holds the status of the group owner change
 | 
						|
type ChangeOwnerResult struct {
 | 
						|
	GroupID string `json:"group_id"`
 | 
						|
	// 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"`
 | 
						|
}
 | 
						|
 | 
						|
func (r ChangeOwnerResult) String() string {
 | 
						|
	return marshal(&r)
 | 
						|
}
 |