-
Notifications
You must be signed in to change notification settings - Fork 135
/
phonenumbers.go
290 lines (242 loc) · 10.2 KB
/
phonenumbers.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
package gotwilio
import (
"context"
"encoding/json"
"net/http"
"net/url"
"github.com/google/go-querystring/query"
)
// PhoneNumberType defines whether a phone number is local, toll-free, or mobile.
type PhoneNumberType int
const (
PhoneNumberLocal PhoneNumberType = iota
PhoneNumberTollFree
PhoneNumberMobile
)
var numberTypeMapping = map[PhoneNumberType]string{
PhoneNumberLocal: "Local",
PhoneNumberTollFree: "TollFree",
PhoneNumberMobile: "Mobile",
}
func (t PhoneNumberType) String() string {
return numberTypeMapping[t]
}
// AvailablePhoneNumbersOptions are all of the options that can be passed to an GetAvailablePhoneNumber query.
type AvailablePhoneNumbersOptions struct {
AreaCode string `url:",omitempty"`
Contains string `url:",omitempty"`
SMSEnabled *bool `url:"SmsEnabled,omitempty"`
MMSEnabled *bool `url:"MmsEnabled,omitempty"`
VoiceEnabled *bool `url:",omitempty"`
FaxEnabled *bool `url:",omitempty"`
ExcludeAllAddressRequired *bool `url:",omitempty"`
ExcludeLocalAddressRequired *bool `url:",omitempty"`
ExcludeForeignAddressRequired *bool `url:",omitempty"`
Beta *bool `url:",omitempty"`
NearNumber string `url:",omitempty"`
NearLatLong string `url:",omitempty"`
Distance int `url:",omitempty"`
InPostalCode string `url:",omitempty"`
InRegion string `url:",omitempty"`
InRateCenter string `url:",omitempty"`
InLATA string `url:"InLata,omitempty"`
InLocality string `url:",omitempty"`
}
// ToQueryString converts the provided options to a query string to be used in the outbound HTTP request.
func (o AvailablePhoneNumbersOptions) ToQueryString() (url.Values, error) {
return query.Values(o)
}
// AvailablePhoneNumber represents a Twilio phone number available for purchase
// https://www.twilio.com/docs/phone-numbers/api/availablephonenumber-resource
type AvailablePhoneNumber struct {
FriendlyName string `json:"friendly_name"`
PhoneNumber string `json:"phone_number"`
LATA string `json:"lata"`
RateCenter string `json:"rate_center"`
Region string `json:"region"`
Locality string `json:"locality"`
Latitude float64 `json:"latitude"`
Longitude float64 `json:"longitude"`
PostalCode string `json:"postal_code"`
Beta bool `json:"beta"`
Capabilities struct {
MMS bool `json:"mms"`
SMS bool `json:"sms"`
Voice bool `json:"voice"`
} `json:"capabilities"`
}
// GetAvailablePhoneNumbers retrieves list of available phone numbers
func (twilio *Twilio) GetAvailablePhoneNumbers(numberType PhoneNumberType, country string, options AvailablePhoneNumbersOptions) ([]*AvailablePhoneNumber, *Exception, error) {
// build initial request
resourceName := country + "/" + numberType.String() + ".json"
req, err := http.NewRequest(http.MethodGet, twilio.buildUrl("AvailablePhoneNumbers/"+resourceName), nil)
if err != nil {
return nil, nil, err
}
// authenticate
req.SetBasicAuth(twilio.getBasicAuthCredentials())
// set query string
queryValues, err := query.Values(options)
if err != nil {
return nil, nil, err
}
req.URL.RawQuery = queryValues.Encode()
// perform request
res, err := twilio.do(req)
if err != nil {
return nil, nil, err
}
decoder := json.NewDecoder(res.Body)
if res.StatusCode != http.StatusOK {
exception := new(Exception)
err = decoder.Decode(exception)
return nil, exception, err
}
// decode response
availablePhoneNumberResponse := new(struct {
AvailablePhoneNumbers []*AvailablePhoneNumber `json:"available_phone_numbers"`
})
decoder.Decode(availablePhoneNumberResponse)
return availablePhoneNumberResponse.AvailablePhoneNumbers, nil, nil
}
// IncomingPhoneNumber represents a phone number resource owned by the calling account in Twilio
type IncomingPhoneNumber struct {
SID string `json:"sid"`
PhoneNumber string `url:",omitempty" json:"phone_number"`
AreaCode string `url:",omitempty"`
FriendlyName string `url:",omitempty" json:"friendly_name"`
SMSApplicationSID string `url:"SmsApplicationSid,omitempty" json:"sms_application_sid"`
SMSMethod string `url:"SmsMethod,omitempty" json:"sms_method"`
SMSURL string `url:"SmsUrl,omitempty" json:"sms_url"`
SMSFallbackMethod string `url:"SmsFallbackMethod,omitempty" json:"sms_fallback_method"`
SMSFallbackURL string `url:"SmsFallbackUrl,omitempty" json:"sms_fallback_url"`
StatusCallback string `url:",omitempty" json:"status_callback"`
StatusCallbackMethod string `url:",omitempty" json:"status_callback_method"`
VoiceApplicationSID string `url:"VoiceApplicationSid,omitempty"`
VoiceMethod string `url:",omitempty"`
VoiceURL string `url:"VoiceUrl,omitempty"`
VoiceFallbackMethod string `url:",omitempty"`
VoiceFallbackURL string `url:"VoiceFallbackUrl,omitempty"`
VoiceCallerIDLookup *bool `url:",omitempty"`
// Either "Active" or "Inactive"
EmergencyStatus string `url:",omitempty"`
EmergencyStatusSID string `url:"EmergencyStatusSid,omitempty"`
TrunkSID string `url:"TrunkSid,omitempty"`
IdentitySID string `url:"IdentitySid,omitempty"`
AddressSID string `url:"AddressSid,omitempty"`
// Either "fax" or "voice". Defaults to "voice"
VoiceReceiveMode string `url:",omitempty"`
}
type GetIncomingPhoneNumbersRequest struct {
Beta *bool `url:"Beta,omitempty"`
FriendlyName string `url:"FriendlyName,omitempty"`
PhoneNumber string `url:"PhoneNumber,omitempty"`
Origin string `url:"Origin,omitempty"`
}
type getIncomingPhoneNumbersResponse struct {
IncomingPhoneNumbers []*IncomingPhoneNumber `json:"incoming_phone_numbers"`
}
// GetIncomingPhoneNumbers reads multiple IncomingPhoneNumbers from the Twilio REST API, with optional filtering
// https://www.twilio.com/docs/phone-numbers/api/incomingphonenumber-resource#read-multiple-incomingphonenumber-resources
func (twilio *Twilio) GetIncomingPhoneNumbers(request GetIncomingPhoneNumbersRequest) ([]*IncomingPhoneNumber, *Exception, error) {
return twilio.GetIncomingPhoneNumbersWithContext(context.Background(), request)
}
func (twilio *Twilio) GetIncomingPhoneNumbersWithContext(ctx context.Context, request GetIncomingPhoneNumbersRequest) ([]*IncomingPhoneNumber, *Exception, error) {
// convert request to url.Values for encoding into querystring
form, err := query.Values(request)
if err != nil {
return nil, nil, err
}
// build URL with query string
endpoint := twilio.buildUrl("IncomingPhoneNumbers.json")
reqURL, err := url.Parse(endpoint)
if err != nil {
return nil, nil, err
}
reqURL.RawQuery = form.Encode()
res, err := twilio.get(ctx, reqURL.String())
if err != nil {
return nil, nil, err
}
decoder := json.NewDecoder(res.Body)
// handle NULL response
if res.StatusCode != http.StatusOK {
exception := new(Exception)
err = decoder.Decode(exception)
return nil, exception, err
}
response := new(getIncomingPhoneNumbersResponse)
err = decoder.Decode(&response)
return response.IncomingPhoneNumbers, nil, err
}
// CreateIncomingPhoneNumber creates an IncomingPhoneNumber resource via the Twilio REST API.
// https://www.twilio.com/docs/phone-numbers/api/incomingphonenumber-resource#create-an-incomingphonenumber-resource
func (twilio *Twilio) CreateIncomingPhoneNumber(options IncomingPhoneNumber) (*IncomingPhoneNumber, *Exception, error) {
return twilio.CreateIncomingPhoneNumberWithContext(context.Background(), options)
}
func (twilio *Twilio) CreateIncomingPhoneNumberWithContext(ctx context.Context, options IncomingPhoneNumber) (*IncomingPhoneNumber, *Exception, error) {
// convert options to HTTP form
form, err := query.Values(options)
if err != nil {
return nil, nil, err
}
res, err := twilio.post(ctx, form, twilio.buildUrl("IncomingPhoneNumbers.json"))
if err != nil {
return nil, nil, err
}
decoder := json.NewDecoder(res.Body)
// handle NULL response
if res.StatusCode != http.StatusCreated {
exception := new(Exception)
err = decoder.Decode(exception)
return nil, exception, err
}
incomingPhoneNumber := new(IncomingPhoneNumber)
err = decoder.Decode(incomingPhoneNumber)
return incomingPhoneNumber, nil, err
}
// UpdateIncomingPhoneNumber updates an IncomingPhoneNumber resource via the Twilio REST API.
// https://www.twilio.com/docs/phone-numbers/api/incomingphonenumber-resource#update-an-incomingphonenumber-resource
func (twilio *Twilio) UpdateIncomingPhoneNumber(sid string, options IncomingPhoneNumber) (*IncomingPhoneNumber, *Exception, error) {
return twilio.UpdateIncomingPhoneNumberWithContext(context.Background(), sid, options)
}
func (twilio *Twilio) UpdateIncomingPhoneNumberWithContext(ctx context.Context, sid string, options IncomingPhoneNumber) (*IncomingPhoneNumber, *Exception, error) {
// convert options to HTTP form
form, err := query.Values(options)
if err != nil {
return nil, nil, err
}
res, err := twilio.post(ctx, form, twilio.buildUrl("IncomingPhoneNumbers/"+sid+".json"))
if err != nil {
return nil, nil, err
}
decoder := json.NewDecoder(res.Body)
// handle NULL response
if res.StatusCode != http.StatusOK {
exception := new(Exception)
err = decoder.Decode(exception)
return nil, exception, err
}
incomingPhoneNumber := new(IncomingPhoneNumber)
err = decoder.Decode(incomingPhoneNumber)
return incomingPhoneNumber, nil, err
}
// DeleteIncomingPhoneNumber deletes an IncomingPhoneNumber resource via the Twilio REST API.
// https://www.twilio.com/docs/phone-numbers/api/incomingphonenumber-resource#delete-an-incomingphonenumber-resource
func (twilio *Twilio) DeleteIncomingPhoneNumber(sid string) (*Exception, error) {
return twilio.DeleteIncomingPhoneNumberWithContext(context.Background(), sid)
}
func (twilio *Twilio) DeleteIncomingPhoneNumberWithContext(ctx context.Context, sid string) (*Exception, error) {
resourceName := sid + ".json"
res, err := twilio.delete(ctx, twilio.buildUrl("IncomingPhoneNumbers/" + resourceName))
if err != nil {
return nil, err
}
if res.StatusCode != http.StatusNoContent {
exception := new(Exception)
decoder := json.NewDecoder(res.Body)
err = decoder.Decode(exception)
return exception, err
}
return nil, nil
}