Skip to content

Commit

Permalink
Merge pull request #122 from vallerion/sync-sdk
Browse files Browse the repository at this point in the history
Update SDK to actual API Reference
  • Loading branch information
vallerion authored Jul 6, 2022
2 parents bdf6d9d + 953f5e2 commit d432f52
Show file tree
Hide file tree
Showing 74 changed files with 1,877 additions and 668 deletions.
12 changes: 6 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ MessageBird's REST API for Go
=============================
This repository contains the open source Go client for MessageBird's REST API. Documentation can be found at: https://developers.messagebird.com.

[![Build Status](https://travis-ci.org/messagebird/go-rest-api.svg?branch=master)](https://travis-ci.org/messagebird/go-rest-api) [![PkgGoDev](https://pkg.go.dev/badge/github.com/messagebird/go-rest-api/v8)](https://pkg.go.dev/github.com/messagebird/go-rest-api/v8)
[![Build Status](https://travis-ci.org/messagebird/go-rest-api.svg?branch=master)](https://travis-ci.org/messagebird/go-rest-api) [![PkgGoDev](https://pkg.go.dev/badge/github.com/messagebird/go-rest-api/v9)](https://pkg.go.dev/github.com/messagebird/go-rest-api/v9)

Requirements
------------
Expand All @@ -15,15 +15,15 @@ Installation
The easiest way to use the MessageBird API in your Go project is to install it using *go get*:

```
$ go get github.com/messagebird/go-rest-api/v8
$ go get github.com/messagebird/go-rest-api/v9
```

Examples
--------
Here is a quick example on how to get started. Assuming the **go get** installation worked, you can import the messagebird package like this:

```go
import "github.com/messagebird/go-rest-api/v8"
import "github.com/messagebird/go-rest-api/v9"
```

Then, create an instance of **messagebird.Client**. It can be used to access the MessageBird APIs.
Expand Down Expand Up @@ -69,8 +69,8 @@ For this reason, errors returned by the `voice` package are of type `voice.Error
An example of "simple" error handling is shown in the example above. Let's look how we can gain more in-depth insight in what exactly went wrong:

```go
import "github.com/messagebird/go-rest-api/v8"
import "github.com/messagebird/go-rest-api/v8/sms"
import "github.com/messagebird/go-rest-api/v9"
import "github.com/messagebird/go-rest-api/v9/sms"

// ...

Expand All @@ -91,7 +91,7 @@ if err != nil {
`voice.ErrorResponse` is very similar, except that it holds `voice.Error` structs - those contain only `Code` and `Message` (not description!) fields:

```go
import "github.com/messagebird/go-rest-api/v8/voice"
import "github.com/messagebird/go-rest-api/v9/voice"

// ...

Expand Down
11 changes: 9 additions & 2 deletions UPGRADING.md
Original file line number Diff line number Diff line change
Expand Up @@ -109,8 +109,15 @@ As v7 introduces support for using the Verify API with email recipients, the `Ve
Added [missed fields](https://github.com/messagebird/go-rest-api/pull/119/commits/f9331269238f1518dd35d798a0fbf251bb04bb62) in SMS API.
Updated `sms.Delete` method so now in return only error or nil as result.

## `v8.0.0` -> `v8.1.0`
### Update Conversations API
## `v8.0.0` -> `v9.0.0`
### General
* New `PaginationRequest` instead of many in APIs.
* Interface `messagebird.MessageBirdClient` instead of `messagebird.Client` and new `MockClient` for better testing.
* List structures now have a plural ending instead of using word "List". Example: `ContactList` -> `Contacts`.
* `conversations.ConversationStatus` replaced by `conversations.Status`.
* `number.NumberPattern` replaced by `number.SearchPattern`.
* Added [Partner Accounts API](https://developers.messagebird.com/api/partner/).
### Conversations API
* Replaced `conversations.CreateMessage` with `conversations.Reply` which send a new message to an existing conversation.
* Replaced `conversations.ListMessages` with `conversations.ListConversationMessages` which fetch messages in indicated conversation.
* Added `conversations.SendMessage` to send a message to a specific recipient in a specific platform.
Expand Down
33 changes: 33 additions & 0 deletions api.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package messagebird

import (
"net/url"
"strconv"
)

// PaginationRequest can be used to set pagination options in List().
type PaginationRequest struct {
Limit, Offset int
}

func (cpr *PaginationRequest) QueryParams() string {
if cpr == nil {
return ""
}

query := url.Values{}
if cpr.Limit > 0 {
query.Set("limit", strconv.Itoa(cpr.Limit))
}
if cpr.Offset >= 0 {
query.Set("offset", strconv.Itoa(cpr.Offset))
}

return query.Encode()
}

// DefaultPagination provides reasonable values for List requests.
var DefaultPagination = &PaginationRequest{
Limit: 20,
Offset: 0,
}
4 changes: 2 additions & 2 deletions balance/balance.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package balance
import (
"net/http"

messagebird "github.com/messagebird/go-rest-api/v8"
messagebird "github.com/messagebird/go-rest-api/v9"
)

// Balance describes your balance information.
Expand All @@ -17,7 +17,7 @@ const path = "balance"

// Read returns the balance information for the account that is associated with
// the access key.
func Read(c *messagebird.Client) (*Balance, error) {
func Read(c messagebird.Client) (*Balance, error) {
balance := &Balance{}
if err := c.Request(balance, http.MethodGet, path, nil); err != nil {
return nil, err
Expand Down
4 changes: 2 additions & 2 deletions balance/balance_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ import (
"net/http"
"testing"

messagebird "github.com/messagebird/go-rest-api/v8"
"github.com/messagebird/go-rest-api/v8/internal/mbtest"
messagebird "github.com/messagebird/go-rest-api/v9"
"github.com/messagebird/go-rest-api/v9/internal/mbtest"
"github.com/stretchr/testify/assert"
)

Expand Down
49 changes: 25 additions & 24 deletions client.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,16 +25,13 @@ import (

const (
// ClientVersion is used in User-Agent request header to provide server with API level.
ClientVersion = "8.1.0"
ClientVersion = "9.0.0"

// Endpoint points you to MessageBird REST API.
Endpoint = "https://rest.messagebird.com"

// httpClientTimeout is used to limit http.Client waiting time.
httpClientTimeout = 15 * time.Second

// voiceHost is the host name for the Voice API.
voiceHost = "voice.messagebird.com"
)

var (
Expand All @@ -45,13 +42,13 @@ var (
// A Feature can be enabled
type Feature int

type MessageBirdClient interface {
type Client interface {
Request(v interface{}, method, path string, data interface{}) error
}

// Client is used to access API with a given key.
// DefaultClient is used to access API with a given key.
// Uses standard lib HTTP client internally, so should be reused instead of created as needed and it is safe for concurrent use.
type Client struct {
type DefaultClient struct {
AccessKey string // The API access key.
HTTPClient *http.Client // The HTTP client to send requests on.
DebugLog *log.Logger // Optional logger for debugging purposes.
Expand All @@ -68,26 +65,25 @@ const (
// errorReader reads the provided byte slice into an appropriate error.
type errorReader func([]byte) error

var voiceErrorReader errorReader
var customErrorReader errorReader

// SetErrorReader takes an errorReader that must parse raw JSON errors
func SetErrorReader(r errorReader) {
customErrorReader = r
}

// New creates a new MessageBird client object.
func New(accessKey string) *Client {
return &Client{
func New(accessKey string) *DefaultClient {
return &DefaultClient{
AccessKey: accessKey,
HTTPClient: &http.Client{
Timeout: httpClientTimeout,
},
}
}

// SetVoiceErrorReader takes an errorReader that must parse raw JSON errors
// returned from the Voice API.
func SetVoiceErrorReader(r errorReader) {
voiceErrorReader = r
}

// Request is for internal use only and unstable.
func (c *Client) Request(v interface{}, method, path string, data interface{}) error {
func (c *DefaultClient) Request(v interface{}, method, path string, data interface{}) error {
if !strings.HasPrefix(path, "https://") && !strings.HasPrefix(path, "http://") {
path = fmt.Sprintf("%s/%s", Endpoint, path)
}
Expand Down Expand Up @@ -156,17 +152,22 @@ func (c *Client) Request(v interface{}, method, path string, data interface{}) e
return ErrUnexpectedResponse
default:
// Anything else than a 200/201/204/500 should be a JSON error.
if uri.Host == voiceHost && voiceErrorReader != nil {
return voiceErrorReader(responseBody)
if customErrorReader != nil {
return customErrorReader(responseBody)
}

var errorResponse ErrorResponse
if err := json.Unmarshal(responseBody, &errorResponse); err != nil {
return err
}
return defaultErrorReader(responseBody)
}
}

return errorResponse
func defaultErrorReader(b []byte) error {
var errorResponse ErrorResponse

if err := json.Unmarshal(b, &errorResponse); err != nil {
return fmt.Errorf("failed to unmarshal response json %s, error: %v", string(b), err)
}

return errorResponse
}

// prepareRequestBody takes untyped data and attempts constructing a meaningful
Expand Down
84 changes: 18 additions & 66 deletions contact/contact.go
Original file line number Diff line number Diff line change
@@ -1,16 +1,15 @@
package contact

import (
"errors"
"fmt"
"net/http"
"net/url"
"strconv"
"time"

messagebird "github.com/messagebird/go-rest-api/v8"
messagebird "github.com/messagebird/go-rest-api/v9"
)

// path represents the path to the Contacts resource.
const path = "contacts"

// Contact gets returned by the API.
type Contact struct {
ID string
Expand All @@ -36,20 +35,15 @@ type Contact struct {
UpdatedDatetime *time.Time
}

type ContactList struct {
type Contacts struct {
Limit, Offset int
Count, TotalCount int
Items []Contact
}

// ListOptions can be used to set pagination options in List().
type ListOptions struct {
Limit, Offset int
}

// Request represents a contact for write operations, e.g. for creating a new
// CreateRequest represents a contact for write operations, e.g. for creating a new
// contact or updating an existing one.
type Request struct {
type CreateRequest struct {
MSISDN string `json:"msisdn,omitempty"`
FirstName string `json:"firstName,omitempty"`
LastName string `json:"lastName,omitempty"`
Expand All @@ -59,20 +53,12 @@ type Request struct {
Custom4 string `json:"custom4,omitempty"`
}

// path represents the path to the Contacts resource.
const path = "contacts"

// DefaultListOptions provides reasonable values for List().
var DefaultListOptions = &ListOptions{
Limit: 20,
Offset: 0,
type ViewRequest struct {
MSISDN string `json:"msisdn,omitempty"`
Name string `json:"firstName,omitempty"`
}

func Create(c *messagebird.Client, contactRequest *Request) (*Contact, error) {
if err := validateCreate(contactRequest); err != nil {
return nil, err
}

func Create(c messagebird.Client, contactRequest *CreateRequest) (*Contact, error) {
contact := &Contact{}
if err := c.Request(contact, http.MethodPost, path, contactRequest); err != nil {
return nil, err
Expand All @@ -81,61 +67,27 @@ func Create(c *messagebird.Client, contactRequest *Request) (*Contact, error) {
return contact, nil
}

func validateCreate(contactRequest *Request) error {
if contactRequest.MSISDN == "" {
return errors.New("msisdn is required")
}

return nil
}

// Delete attempts deleting the contact with the provided ID. If nil is returned,
// the resource was deleted successfully.
func Delete(c *messagebird.Client, id string) error {
if id == "" {
return errors.New("id is required")
}

func Delete(c messagebird.Client, id string) error {
return c.Request(nil, http.MethodDelete, path+"/"+id, nil)
}

// List retrieves a paginated list of contacts, based on the options provided.
// It's worth noting DefaultListOptions.
func List(c *messagebird.Client, options *ListOptions) (*ContactList, error) {
query, err := listQuery(options)
if err != nil {
return nil, err
}

contactList := &ContactList{}
if err = c.Request(contactList, http.MethodGet, path+"?"+query, nil); err != nil {
func List(c messagebird.Client, options *messagebird.PaginationRequest) (*Contacts, error) {
contactList := &Contacts{}
if err := c.Request(contactList, http.MethodGet, path+"?"+options.QueryParams(), nil); err != nil {
return nil, err
}

return contactList, nil
}

func listQuery(options *ListOptions) (string, error) {
if options.Limit < 10 {
return "", fmt.Errorf("minimum limit is 10, got %d", options.Limit)
}

if options.Offset < 0 {
return "", fmt.Errorf("offset can not be negative")
}

values := &url.Values{}

values.Set("limit", strconv.Itoa(options.Limit))
values.Set("offset", strconv.Itoa(options.Offset))

return values.Encode(), nil
}

// Read retrieves the information of an existing contact.
func Read(c *messagebird.Client, id string) (*Contact, error) {
func Read(c messagebird.Client, id string, req *ViewRequest) (*Contact, error) {
contact := &Contact{}
if err := c.Request(contact, http.MethodGet, path+"/"+id, nil); err != nil {
if err := c.Request(contact, http.MethodGet, path+"/"+id, req); err != nil {
return nil, err
}

Expand All @@ -144,7 +96,7 @@ func Read(c *messagebird.Client, id string) (*Contact, error) {

// Update updates the record referenced by id with any values set in contactRequest.
// Do not set any values that should not be updated.
func Update(c *messagebird.Client, id string, contactRequest *Request) (*Contact, error) {
func Update(c messagebird.Client, id string, contactRequest *CreateRequest) (*Contact, error) {
contact := &Contact{}
if err := c.Request(contact, http.MethodPatch, path+"/"+id, contactRequest); err != nil {
return nil, err
Expand Down
Loading

0 comments on commit d432f52

Please sign in to comment.