Skip to content

Commit de3b425

Browse files
author
marcel corso gonzalez
authored
Merge branch 'master' into export-links-field
2 parents 1445727 + 1dbb310 commit de3b425

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

55 files changed

+2481
-56
lines changed

.travis.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
language: go
2-
32
go:
3+
- 1.7
44
- 1.8
5+
- 1.9
56
- stable
67
- master
7-
88
matrix:
99
allow_failures:
1010
- go: master

README.md

Lines changed: 75 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ This repository contains the open source Go client for MessageBird's REST API. D
77
Requirements
88
------------
99
- [Sign up](https://www.messagebird.com/en/signup) for a free MessageBird account
10-
- Create a new access key in the developers sections
10+
- Create a new access key in the [dashboard](https://dashboard.messagebird.com/en-us/developers/access).
1111
- An application written in Go to make use of this API
1212

1313
Installation
@@ -26,51 +26,104 @@ Here is a quick example on how to get started. Assuming the **go get** installat
2626
import "github.com/messagebird/go-rest-api"
2727
```
2828

29-
Then, create an instance of **messagebird.Client**:
29+
Then, create an instance of **messagebird.Client**. It can be used to access the MessageBird APIs.
3030

3131
```go
32-
client := messagebird.New("test_gshuPaZoeEG6ovbc8M79w0QyM")
33-
```
32+
// Access keys can be managed through our dashboard.
33+
accessKey := "your-access-key"
3434

35-
Now you can query the API for information or send data. For example, if we want to request our balance information you'd do something like this:
35+
// Create a client.
36+
client := messagebird.New(accessKey)
3637

37-
```go
38-
// Request the balance information, returned as a Balance object.
38+
// Request the balance information, returned as a balance.Balance object.
3939
balance, err := balance.Read(client)
4040
if err != nil {
41-
switch errResp := err.(type) {
42-
case messagebird.ErrorResponse:
43-
for _, mbError := range errResp.Errors {
44-
fmt.Printf("Error: %#v\n", mbError)
45-
}
46-
}
47-
41+
// Handle error.
4842
return
4943
}
5044

51-
fmt.Println(" payment :", balance.Payment)
52-
fmt.Println(" type :", balance.Type)
53-
fmt.Println(" amount :", balance.Amount)
45+
// Display the results.
46+
fmt.Println("Payment: ", balance.Payment)
47+
fmt.Println("Type:", balance.Type)
48+
fmt.Println("Amount:", balance.Amount)
5449
```
5550

5651
This will give you something like:
57-
```shell
52+
53+
```bash
5854
$ go run example.go
59-
payment : prepaid
60-
type : credits
61-
amount : 9
55+
Payment: prepaid
56+
Type: credits
57+
Amount: 9
6258
```
6359

6460
Please see the other examples for a complete overview of all the available API calls.
6561

62+
Errors
63+
------
64+
When something goes wrong, our APIs can return more than a single error. They are therefore returned by the client as "error responses" that contain a slice of errors.
65+
66+
It is important to notice that the Voice API returns errors with a format that slightly differs from other APIs.
67+
For this reason, errors returned by the `voice` package are of type `voice.ErrorResponse`. It contains `voice.Error` structs. All other packages return `messagebird.ErrorResponse` structs that contain a slice of `messagebird.Error`.
68+
69+
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:
70+
71+
```go
72+
import "github.com/messagebird/go-rest-api"
73+
import "github.com/messagebird/go-rest-api/sms"
74+
75+
// ...
76+
77+
_, err := sms.Read(client, "some-id")
78+
if err != nil {
79+
mbErr, ok := err.(messagebird.ErrorResponse)
80+
if !ok {
81+
// A non-MessageBird error occurred (no connection, perhaps?)
82+
return err
83+
}
84+
85+
fmt.Println("Code:", mbErr.Errors[0].Code)
86+
fmt.Println("Description:", mbErr.Errors[0].Description)
87+
fmt.Println("Parameter:", mbErr.Errors[0].Parameter)
88+
}
89+
```
90+
91+
`voice.ErrorResponse` is very similar, except that it holds `voice.Error` structs - those contain only `Code` and `Message` (not description!) fields:
92+
93+
```go
94+
import "github.com/messagebird/go-rest-api/voice"
95+
96+
// ...
97+
98+
_, err := voice.CallFlowByID(client, "some-id")
99+
if err != nil {
100+
vErr, ok := err.(voice.ErrorResponse)
101+
if !ok {
102+
// A non-MessageBird (Voice) error occurred (no connection, perhaps?)
103+
return err
104+
}
105+
106+
fmt.Println("Code:", vErr.Errors[0].Code)
107+
fmt.Println("Message:", vErr.Errors[0].Message)
108+
}
109+
```
110+
111+
Conversations WhatsApp Sandbox
112+
-------------
113+
To use the whatsapp sandbox you need to enable the `FeatureConversationsAPIWhatsAppSandbox` feature.
114+
115+
```go
116+
client.EnableFeatures(messagebird.FeatureConversationsAPIWhatsAppSandbox)
117+
```
118+
66119
Documentation
67120
-------------
68121
Complete documentation, instructions, and examples are available at:
69122
[https://developers.messagebird.com](https://developers.messagebird.com).
70123

71124
Upgrading
72125
---------
73-
If you're upgrading from older versions, please read the [Messagebird `go-rest-api` uprading guide](UPGRADING.md).
126+
If you're upgrading from older versions, please read the [Messagebird `go-rest-api` upgrading guide](UPGRADING.md).
74127

75128
License
76129
-------

client.go

Lines changed: 58 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,31 +20,45 @@ import (
2020
"net/url"
2121
"runtime"
2222
"strings"
23+
"sync"
2324
"time"
2425
)
2526

2627
const (
2728
// ClientVersion is used in User-Agent request header to provide server with API level.
28-
ClientVersion = "5.1.1"
29+
ClientVersion = "5.4.0"
2930

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

3334
// httpClientTimeout is used to limit http.Client waiting time.
3435
httpClientTimeout = 15 * time.Second
36+
37+
// voiceHost is the host name for the Voice API.
38+
voiceHost = "voice.messagebird.com"
3539
)
3640

3741
var (
3842
// ErrUnexpectedResponse is used when there was an internal server error and nothing can be done at this point.
3943
ErrUnexpectedResponse = errors.New("The MessageBird API is currently unavailable")
4044
)
4145

46+
// A Feature can be enabled
47+
type Feature int
48+
49+
const (
50+
// FeatureConversationsAPIWhatsAppSandbox Enables the WhatsApp sandbox for conversations API.
51+
FeatureConversationsAPIWhatsAppSandbox Feature = iota
52+
)
53+
4254
// Client is used to access API with a given key.
4355
// Uses standard lib HTTP client internally, so should be reused instead of created as needed and it is safe for concurrent use.
4456
type Client struct {
45-
AccessKey string // The API access key
46-
HTTPClient *http.Client // The HTTP client to send requests on
47-
DebugLog *log.Logger // Optional logger for debugging purposes
57+
AccessKey string // The API access key.
58+
HTTPClient *http.Client // The HTTP client to send requests on.
59+
DebugLog *log.Logger // Optional logger for debugging purposes.
60+
features map[Feature]bool // Enabled features.
61+
featuresMutex sync.RWMutex // Mutex for accessing feature map.
4862
}
4963

5064
type contentType string
@@ -55,14 +69,50 @@ const (
5569
contentTypeFormURLEncoded contentType = "application/x-www-form-urlencoded"
5670
)
5771

72+
// errorReader reads the provided byte slice into an appropriate error.
73+
type errorReader func([]byte) error
74+
75+
var voiceErrorReader errorReader
76+
5877
// New creates a new MessageBird client object.
5978
func New(accessKey string) *Client {
6079
return &Client{
6180
AccessKey: accessKey,
6281
HTTPClient: &http.Client{
6382
Timeout: httpClientTimeout,
6483
},
84+
features: make(map[Feature]bool),
85+
}
86+
}
87+
88+
// SetVoiceErrorReader takes an errorReader that must parse raw JSON errors
89+
// returned from the Voice API.
90+
func SetVoiceErrorReader(r errorReader) {
91+
voiceErrorReader = r
92+
}
93+
94+
// EnableFeatures enables a feature.
95+
func (c *Client) EnableFeatures(feature Feature) {
96+
c.featuresMutex.Lock()
97+
defer c.featuresMutex.Unlock()
98+
c.features[feature] = true
99+
}
100+
101+
// DisableFeatures disables a feature.
102+
func (c *Client) DisableFeatures(feature Feature) {
103+
c.featuresMutex.Lock()
104+
defer c.featuresMutex.Unlock()
105+
c.features[feature] = false
106+
}
107+
108+
// IsFeatureEnabled checks if a feature is enabled.
109+
func (c *Client) IsFeatureEnabled(feature Feature) bool {
110+
c.featuresMutex.RLock()
111+
defer c.featuresMutex.RUnlock()
112+
if enabled, ok := c.features[feature]; ok {
113+
return enabled
65114
}
115+
return false
66116
}
67117

68118
// Request is for internal use only and unstable.
@@ -135,6 +185,10 @@ func (c *Client) Request(v interface{}, method, path string, data interface{}) e
135185
return ErrUnexpectedResponse
136186
default:
137187
// Anything else than a 200/201/204/500 should be a JSON error.
188+
if uri.Host == voiceHost && voiceErrorReader != nil {
189+
return voiceErrorReader(responseBody)
190+
}
191+
138192
var errorResponse ErrorResponse
139193
if err := json.Unmarshal(responseBody, &errorResponse); err != nil {
140194
return err

contact/contact.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,8 @@ type Contact struct {
3232
TotalCount int
3333
HRef string
3434
}
35-
CreatedDatetime time.Time
36-
UpdatedDatetime time.Time
35+
CreatedDatetime *time.Time
36+
UpdatedDatetime *time.Time
3737
}
3838

3939
type ContactList struct {

0 commit comments

Comments
 (0)