twilio-rb 1.0beta2 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.md +205 -134
- data/lib/railtie.rb +3 -1
- data/lib/twilio/account.rb +13 -16
- data/lib/twilio/application.rb +14 -0
- data/lib/twilio/association_proxy.rb +22 -0
- data/lib/twilio/associations.rb +14 -0
- data/lib/twilio/call.rb +9 -11
- data/lib/twilio/capability.rb +51 -0
- data/lib/twilio/config.rb +12 -3
- data/lib/twilio/finder.rb +22 -12
- data/lib/twilio/incoming_phone_number.rb +4 -5
- data/lib/twilio/notification.rb +1 -2
- data/lib/twilio/outgoing_caller_id.rb +1 -3
- data/lib/twilio/participant.rb +2 -0
- data/lib/twilio/persistable.rb +22 -14
- data/lib/twilio/request_filter.rb +25 -0
- data/lib/twilio/resource.rb +21 -5
- data/lib/twilio/short_code.rb +23 -0
- data/lib/twilio/sms.rb +5 -2
- data/lib/twilio-rb.rb +23 -0
- data/lib/twilio.rb +2 -22
- metadata +115 -85
data/README.md
CHANGED
@@ -1,7 +1,6 @@
|
|
1
|
-
|
2
1
|
# Twilio.rb
|
3
2
|
|
4
|
-
Interact with the Twilio API in a nice Ruby way.
|
3
|
+
Interact with the Twilio API in a nice Ruby way.
|
5
4
|
|
6
5
|
Twilio.rb is the only library that encapsulates Twilio resources as Ruby objects, has 100% test coverage, and supports the whole API.
|
7
6
|
|
@@ -9,7 +8,7 @@ It offers an ActiveRecord style API, i.e. one that most Ruby developers are fami
|
|
9
8
|
|
10
9
|
## Installation
|
11
10
|
|
12
|
-
The library has been packaged as a gem and is available from rubygems.org. The version that this readme pertains to is
|
11
|
+
The library has been packaged as a gem and is available from rubygems.org. The version that this readme pertains to is 2.0.0.
|
13
12
|
|
14
13
|
<pre>gem install twilio-rb --pre</pre>
|
15
14
|
|
@@ -19,49 +18,146 @@ Please use the Github issue tracker to report any issues or bugs you uncover.
|
|
19
18
|
|
20
19
|
Require the library in your script as
|
21
20
|
|
22
|
-
<pre>require 'twilio'</pre>
|
21
|
+
<pre>require 'twilio-rb'</pre>
|
23
22
|
|
24
23
|
or using bundler:
|
25
24
|
|
26
|
-
<pre>gem 'twilio-rb'
|
25
|
+
<pre>gem 'twilio-rb'</pre>
|
27
26
|
|
28
27
|
## Configuration
|
29
28
|
|
30
|
-
Configuration for this library is
|
29
|
+
Configuration for this library is achieved with `Twilio::Config.setup`. One needs to setup with an Account SID and an Auth Token, e.g.
|
31
30
|
|
32
31
|
<pre># This should be in an initializer or similar
|
33
|
-
Twilio::Config.setup
|
34
|
-
account_sid
|
35
|
-
auth_token
|
32
|
+
Twilio::Config.setup \
|
33
|
+
:account_sid => 'AC0000000000000000000000000000',
|
34
|
+
:auth_token => '000000000000000000000000000000'
|
36
35
|
end</pre>
|
37
36
|
|
38
37
|
Any method that calls the Twilio API will raise `Twilio::ConfigurationError` if either Account SID or Auth Token are not configured.
|
39
38
|
|
40
39
|
# Getting started
|
41
40
|
|
41
|
+
## Summary
|
42
|
+
|
43
|
+
Twilio resources are represented as Ruby objects. List resources are represnted by classes, e.g. `Twilio::SMS` and operations on list resources are performed using class methods, e.g. `Twilio::SMS.create`. Resource instances are represented by instances of those classes, and operations on those resource instances are perfomed using instance methods.
|
44
|
+
|
45
|
+
Resources that can be created via the API, using the HTTP POST verb can be done so in the library using the `.create` class method, e.g.
|
46
|
+
|
47
|
+
<pre>Twilio::Call.create :to => '+16465551234', :from => '+19175550000',
|
48
|
+
:url => "http://example.com/call_handler"</pre>
|
49
|
+
|
50
|
+
Resources that can be removed via the API, using the HTTP DELETE verb can be done so in the library using the `#destroy` instance method, e.g.
|
51
|
+
|
52
|
+
<pre>
|
53
|
+
# Delete all log entries
|
54
|
+
Twilio::Notification.all.each &:destroy
|
55
|
+
</pre>
|
56
|
+
|
57
|
+
Object representations instantiated by the library respond to all methods that match attributes on its corresponding resource. The method names are those of the parameters in snake case (underscored), i.e. as they are returned in the JSON representation.
|
58
|
+
|
59
|
+
The Twilio API documentation itself is the canonical reference for which resources have what properties, and which of those can be updated by the API. Please refer to the Twilio REST API documentation for thos information.
|
60
|
+
|
61
|
+
## Accessing resource instances
|
62
|
+
|
63
|
+
Resource instances can be accessed ad hoc passsing the resource sid to the `.find` class method on the resource class, e.g.
|
64
|
+
|
65
|
+
<pre>call = Twilio::Call.find 'CAe1644a7eed5088b159577c5802d8be38'</pre>
|
66
|
+
|
67
|
+
This will return an instance of the resource class, in this case `Twilio::Call`, with the attributes of the resource. These attributes are accessed using dynamically defined getter methods, where the method name is the attribute name underscored, i.e. as they are returned in a JSON response from the API.
|
68
|
+
|
69
|
+
Sometimes these method name might collide with native Ruby methods, one such example is the `method` parameter colliding with `Object#method`. Native Ruby methods are never overridden by the library as they are lazily defined using `method_missing`. To access these otherwise unreachable attributes, there is another syntax for accessing resource attributes:
|
70
|
+
|
71
|
+
<pre>
|
72
|
+
call = Twilio::Call.find 'CAe1644a7eed5088b159577c5802d8be38'
|
73
|
+
call[:method] # With a symbol or
|
74
|
+
call['method'] # or with a string. Access is indifferent.
|
75
|
+
</pre>
|
76
|
+
|
77
|
+
## Querying list resources
|
78
|
+
|
79
|
+
List resources can be accessed ad hoc by calling the `.all` class method on the resource class, e.g.
|
80
|
+
|
81
|
+
<pre>calls = Twilio::Call.all</pre>
|
82
|
+
|
83
|
+
This will return a collection of objects, each a representation of the corresponding resource.
|
84
|
+
|
85
|
+
### Using filter parameters to refine a query
|
86
|
+
|
87
|
+
The `.all` class method will ask Twilio for all resource instances on that list resource, this can easily result in a useless response if there are numerous resource instances on a given resource. The `.all` class method accepts a hash of options for parameters to filter the response, e.g.
|
88
|
+
|
89
|
+
<pre>Twilio::Call.all :to => '+19175550000', :status => 'complete'</pre>
|
90
|
+
|
91
|
+
Twilio does some fancy stuff to implement date ranges, consider the API request:
|
92
|
+
|
93
|
+
<pre>GET /2010-04-01/Accounts/AC5ef87.../Calls?StartTime>=2009-07-06&EndTime<=2009-07-10</pre>
|
94
|
+
|
95
|
+
This will return all calls started after midnight July 06th 2009 and completed before July 10th 2009. Any call started and ended within that time range matches those criteria and will be returned. To make the same reqest using this library:
|
96
|
+
|
97
|
+
<pre>
|
98
|
+
require 'date'
|
99
|
+
start_date, end_date = Date.parse('2009-07-06'), Date.parse('2009-07-10')
|
100
|
+
|
101
|
+
Twilio::Call.all :started_after => start_date, :ended_before => end_date
|
102
|
+
</pre>
|
103
|
+
|
104
|
+
All option parameters pertaining to dates accept a string or any object that returns a RFC 2822 date when `#to_s` is called on it, e.g. an instance of `Date`. If a date parameter is not a rnage but absolute, one can of course use the normal option, e.g.
|
105
|
+
|
106
|
+
<pre>Twilio::Call.all :start_time => start_date</pre>
|
107
|
+
|
108
|
+
The key names for these Date filters are inconsistent across resources, in the library they are:
|
109
|
+
|
110
|
+
<pre>
|
111
|
+
Twilio::SMS.all :created_before => date, :created_after => date, :sent_before => date, :sent_after # :"created_#{when}" and :"sent_#{when}" are synonomous
|
112
|
+
Twilio::Notification.all :created_before => date, :created_after => date
|
113
|
+
Twilio::Call.all :started_before => date, :started_after => date, :ended_before => date, :ended_after => date
|
114
|
+
</pre>
|
115
|
+
|
116
|
+
### Pagination
|
117
|
+
|
118
|
+
The Twilio API paginates API responses and by default it will return 30 objects in one response, this can be overridden to return up to a maximum of 1000 per response using the `:page_size` option, If more than 1000 resources instances exist, the `:page` option is available, e.g.
|
119
|
+
|
120
|
+
<pre>Twilio::Call.all :started_after => start_date, :ended_before => end_date, :page_size => 1000, :page => 7</pre>
|
121
|
+
|
122
|
+
To determine how many resources exist, the `.count` class method exists, which accepts the same options as `.all` in order to constrain the query e.g.
|
123
|
+
|
124
|
+
<pre>Twilio::Call.count :started_after => start_date, :ended_before => end_date</pre>
|
125
|
+
|
126
|
+
It returns an integer corresponding to how many resource instances exist with those conditions.
|
127
|
+
|
128
|
+
## Updating resource attributes
|
129
|
+
|
130
|
+
Certain resources have attributes that can be updated with the REST API. Instances of those resources can be updated using either a setter method with a name that corresponds to the attribute, or by using the `#update_attributes`.
|
131
|
+
|
132
|
+
<pre>
|
133
|
+
call = Twilio::Call.all(:status => 'in-progress').first
|
134
|
+
|
135
|
+
call.url = 'http://example.com/in_ur_apiz_hijackin_ur_callz.xml'
|
136
|
+
call.update_attributes :url => 'http://example.com/in_ur_apiz_hijackin_ur_callz.xml'
|
137
|
+
</pre>
|
138
|
+
|
139
|
+
These are both equivalent, i.e. they immediately make an API request and update the state of the object with the API response. The first one in fact uses the second one internally and is just a shortcut. Use the second when there is more than one attribute to be updated in the same HTTP request.
|
140
|
+
|
42
141
|
## Making a telephone call
|
43
142
|
|
44
143
|
The API used to make a telephone call is similar to interacting with an ActiveRecord model object.
|
45
|
-
<pre>Twilio::Call.create :to => '+16465551234', :from => '+19175550000',
|
144
|
+
<pre>Twilio::Call.create :to => '+16465551234', :from => '+19175550000',
|
46
145
|
:url => "http://example.com/call_handler"</pre>
|
47
146
|
|
48
147
|
The parameter keys should be given as underscored symbols. They will be converted internally to camelized strings prior to an API call being made.
|
49
148
|
|
50
|
-
Please see the Twilio REST API documentation for an up to date list of supported parameters.
|
149
|
+
Please see the Twilio REST API documentation for an up to date list of supported parameters.
|
51
150
|
|
52
151
|
If the request was successful, an instance of `Twilio::Call` wil be returned
|
53
152
|
|
54
153
|
### Modifying a live telephone call
|
55
154
|
|
56
|
-
|
155
|
+
As well as the the aforementioned setter methods, once a call has been been created it can be modified with the following convenience methods:
|
57
156
|
|
58
157
|
`Twilio::Call#cancel!` will terminate the call if its state is `queued` or `ringing`
|
59
158
|
`Twilio::Call#complete!` will terminate the call even if its state is `in-progress`
|
60
159
|
`Twilio::Call#url=` will immediately redirect the call to a new handler URL
|
61
160
|
|
62
|
-
`Twilio::Call#cancel!` and `Twilio::Call#complete!` will raise `Twilio::InvalidStateError` if the call has not been "saved".
|
63
|
-
`Twilio::Call#url=` will updated its state with the new URL ready for when `Twilio::Call#save` is called.
|
64
|
-
|
65
161
|
## Finding an existing telephone call
|
66
162
|
|
67
163
|
To retrieve an earlier created call, there is the `Twilio::Call.find` method, which accepts a call SID, e.g.
|
@@ -73,7 +169,7 @@ This returns an instance of `Twilio::Call` if a call with the given SID was foun
|
|
73
169
|
## Sending an SMS message
|
74
170
|
|
75
171
|
The API used to send an SMS message is similar to interacting with an ActiveRecord model object.
|
76
|
-
<pre>Twilio::SMS.create :to => '+16465551234', :from => '+19175550000',
|
172
|
+
<pre>Twilio::SMS.create :to => '+16465551234', :from => '+19175550000',
|
77
173
|
:body => "Hey baby, how was your day? x"</pre>
|
78
174
|
|
79
175
|
The parameter keys should be given as underscored symbols. They will be converted internally to camelized strings prior to an API call being made.
|
@@ -82,7 +178,7 @@ Please see the Twilio REST API documentation for an up to date list of supported
|
|
82
178
|
|
83
179
|
If the request was successful, an instance of `Twilio::SMS` wil be returned
|
84
180
|
|
85
|
-
## Finding an existing
|
181
|
+
## Finding an existing SMS message
|
86
182
|
|
87
183
|
To retrieve an earlier created SMS message, there is the `Twilio::SMS.find` method, which accepts a SMS message SID, e.g.
|
88
184
|
|
@@ -90,13 +186,95 @@ To retrieve an earlier created SMS message, there is the `Twilio::SMS.find` meth
|
|
90
186
|
|
91
187
|
This returns an instance of `Twilio::SMS` if a SMS message with the given SID was found, otherwise nil is returned
|
92
188
|
|
189
|
+
# Twilio Client
|
190
|
+
|
191
|
+
To generate capability tokens for use with Twilio Client you can use `Twilio::CapabilityToken.create`
|
192
|
+
|
193
|
+
<pre>
|
194
|
+
Twilio::CapabilityToken.create \
|
195
|
+
allow_incoming: 'unique_identifier_for_this_user',
|
196
|
+
allow_outgoing: 'your_application_sid'
|
197
|
+
</pre>
|
198
|
+
|
199
|
+
You can create capability tokens on arbitrary accounts, e.g. subaccounts. Just pass in those details:
|
200
|
+
|
201
|
+
<pre>
|
202
|
+
Twilio::CapabilityToken.create \
|
203
|
+
account_sid: 'AC00000000000000000000000',
|
204
|
+
auth_token: 'XXXXXXXXXXXXXXXXXXXXXXXXX',
|
205
|
+
allow_incoming: 'unique_identifier_for_this_user',
|
206
|
+
allow_outgoing: 'your_application_sid'
|
207
|
+
</pre>
|
208
|
+
|
209
|
+
You can also pass arbitrary parameters into your outgoing privilege, these are sent from Twilio as HTTP request params when it hits your app endpoint for TwiML.
|
210
|
+
|
211
|
+
<pre>
|
212
|
+
Twilio::CapabilityToken.create allow_outgoing: ['your_application_sid', { :foo => 'bar' }]
|
213
|
+
</pre>
|
214
|
+
|
215
|
+
By default tokens expire exactly one hour from the time they are generated. You can choose your own token ttl like so:
|
216
|
+
|
217
|
+
<pre>
|
218
|
+
Twilio::CapabilityToken.create \
|
219
|
+
allow_incoming: 'unique_identifier_for_this_user',
|
220
|
+
allow_outgoing: 'your_application_sid',
|
221
|
+
expires: 10.minutes.from_now
|
222
|
+
</pre>
|
223
|
+
|
224
|
+
# Associations
|
225
|
+
|
226
|
+
Certain resources themselves have subresources, e.g. a call can have many recordings. It would be very convenient to access these via an association proxy, so instead of:
|
227
|
+
|
228
|
+
<pre>
|
229
|
+
calls = Twilio::Call.all
|
230
|
+
recordings = Twilio::Recording.all :call_sid => calls.last.sid
|
231
|
+
</pre>
|
232
|
+
|
233
|
+
You might prefer:
|
234
|
+
|
235
|
+
<pre>
|
236
|
+
calls = Twilio::Call.all
|
237
|
+
recordings = calls.recordings.all
|
238
|
+
</pre>
|
239
|
+
|
240
|
+
twilio-rb now supports these association proxies
|
241
|
+
|
242
|
+
# Subaccounts
|
243
|
+
|
244
|
+
The Twilio REST API supports subaccounts that is discrete accounts owned by a master account. twilio-rb supports this too.o
|
245
|
+
|
246
|
+
## Subaccount creation
|
247
|
+
|
248
|
+
You can create new subaccounts by using `Twilio::Account.create`
|
249
|
+
|
250
|
+
## Performing actions on resources belonging to subaccounts
|
251
|
+
|
252
|
+
There are three ways to perform an operation on an account other than the master account: you can pass in the subaccount sid
|
253
|
+
|
254
|
+
<pre>Twilio::SMS.create :to => '+19175551234' :from => '+16465550000',
|
255
|
+
:body => 'This will be billed to a subaccount, sucka!' :account => 'ACXXXXXXXXXXXXXXXXXXXXXXXX'</pre>
|
256
|
+
|
257
|
+
You can also pass in an object that responds to sid, i.e. an instance of Twilio::Account
|
258
|
+
|
259
|
+
<pre>Twilio::SMS.create :to => '+19175551234' :from => '+16465550000',
|
260
|
+
:body => 'This TOO will be billed to a subaccount, sucka!' :account => my_subaccount_object</pre>
|
261
|
+
|
262
|
+
By using an association proxy. By chaining the list resource methods, e.g. find, create, etc, on the association proxy, they are scoped to that account
|
263
|
+
|
264
|
+
<pre>
|
265
|
+
bobs_account = Twilio::Account.find :friendly_name => "Bob's subaccount"
|
266
|
+
|
267
|
+
# This will send a SMS message on Bob's subaccount
|
268
|
+
bobs_account.sms.create :to => '+16465551234', :from => '+19175550000', :body => "Bob is paying for this text. What a guy!"
|
269
|
+
</pre>
|
270
|
+
|
93
271
|
# Building TwiML documents
|
94
272
|
|
95
273
|
A TwiML document is an XML document. The best way to build XML in Ruby is with Builder, and so it follows that we should use builder for TwiML. `Twilio::TwiML.build` behaves like builder except element names are capitalised for you and attributes are camelized for you as well. This is so you may continue to write beautiful code.
|
96
274
|
|
97
275
|
The following Ruby code:
|
98
276
|
|
99
|
-
<pre>Twilio::TwiML.build do |res|
|
277
|
+
<pre>Twilio::TwiML.build do |res|
|
100
278
|
res.say 'Hey man! Listen to this!', :voice => 'man'
|
101
279
|
res.play 'http://foo.com/cowbell.mp3'
|
102
280
|
res.say 'What did you think of that?!', :voice => 'man'
|
@@ -151,109 +329,6 @@ res.say 'Damn this library is so ill dude!'
|
|
151
329
|
|
152
330
|
It's now easier than ever to integrate Twilio in your Rails app cleanly and easily.
|
153
331
|
|
154
|
-
# Basics
|
155
|
-
|
156
|
-
Each super-resource, e.g. Calls, OutgoingCallerIds, etc has a Ruby object in the Twilio namespace representing it, Twilio::Call, Twilio::OutgoingCallerId, etc.
|
157
|
-
|
158
|
-
## Summary
|
159
|
-
|
160
|
-
Resources that can be created via the API, using the HTTP POST verb can be done so in the library using the `.create` class method, e.g.
|
161
|
-
|
162
|
-
<pre>Twilio::Call.create :to => '+16465551234', :from => '+19175550000',
|
163
|
-
:url => "http://example.com/call_handler"</pre>
|
164
|
-
|
165
|
-
Resources that can be removed via the API, using the HTTP DELETE verb can be done so in the library using the `#destroy` instance method, e.g.
|
166
|
-
|
167
|
-
<pre>
|
168
|
-
# Delete all log entries
|
169
|
-
Twilio::Notification.all.each &:destroy
|
170
|
-
</pre>
|
171
|
-
|
172
|
-
Object representations instantiated by the library respond to all methods that match attributes on its corresponding resource. The method names are those of the parameters in snake case (underscored), i.e. as they are returned in the JSON representation.
|
173
|
-
|
174
|
-
The Twilio API documentation itself is the canonical reference for which resources have what properties, and which of those can be updated by the API. Please refer to the Twilio REST API documentation for thos information.
|
175
|
-
|
176
|
-
## Accessing resource instances
|
177
|
-
|
178
|
-
Resource instances can be accessed ad hoc passsing the resource sid to the `.find` class method on the resource class, e.g.
|
179
|
-
|
180
|
-
<pre>call = Twilio::Call.find 'CAe1644a7eed5088b159577c5802d8be38'</pre>
|
181
|
-
|
182
|
-
This will return an instance of the resource class, in this case `Twilio::Call`, with the attributes of the resource. These attributes are accessed using dynamically defined getter methods, where the method name is the attribute name underscored, i.e. as they are returned in a JSON response from the API.
|
183
|
-
|
184
|
-
Sometimes these method name might collide with native Ruby methods, one such example is the `method` parameter colliding with `Object#method`. Native Ruby methods are never overridden by the library as they are lazily defined using `method_missing`. To access these otherwise unreachable attributes, there is another syntax for accessing resource attributes:
|
185
|
-
|
186
|
-
|
187
|
-
<pre>
|
188
|
-
call = Twilio::Call.find 'CAe1644a7eed5088b159577c5802d8be38'
|
189
|
-
call[:method] # With a symbol or
|
190
|
-
call['method'] # or with a string. Access is indifferent.
|
191
|
-
</pre>
|
192
|
-
|
193
|
-
## Querying list resources
|
194
|
-
|
195
|
-
List resources can be accessed ad hoc by calling the `.all` class method on the resource class, e.g.
|
196
|
-
|
197
|
-
<pre>calls = Twilio::Call.all</pre>
|
198
|
-
|
199
|
-
This will return a collection of objects, each a representation of the corresponding resource.
|
200
|
-
|
201
|
-
### Using filter parameters to refine a query
|
202
|
-
|
203
|
-
The `.all` class method will ask Twilio for all resource instances on that list resource, this can easily result in a useless response if there are numerous resource instances on a given resource. The `.all` class method accepts a hash of options for parameters to filter the response, e.g.
|
204
|
-
|
205
|
-
<pre>Twilio::Call.all :to => '+19175550000', :status => 'complete'</pre>
|
206
|
-
|
207
|
-
Twilio does some fancy stuff to implement date ranges, consider the API request:
|
208
|
-
|
209
|
-
<pre>GET /2010-04-01/Accounts/AC5ef87.../Calls?StartTime>=2009-07-06&EndTime<=2009-07-10</pre>
|
210
|
-
|
211
|
-
This will return all calls started after midnight July 06th 2009 and completed before July 10th 2009. Any call started and ended within that time range matches those criteria and will be returned. To make the same reqest using this library:
|
212
|
-
|
213
|
-
<pre>
|
214
|
-
require 'date'
|
215
|
-
start_date, end_date = Date.parse('2009-07-06'), Date.parse('2009-07-10')
|
216
|
-
|
217
|
-
Twilio::Call.all :started_after => start_date, :ended_before => end_date
|
218
|
-
</pre>
|
219
|
-
|
220
|
-
All option parameters pertaining to dates accept a string or any object that returns a RFC 2822 date when `#to_s` is called on it, e.g. an instance of `Date`. If a date parameter is not a rnage but absolute, one can of course use the normal option, e.g.
|
221
|
-
|
222
|
-
<pre>Twilio::Call.all :start_time => start_date</pre>
|
223
|
-
|
224
|
-
The key names for these Date filters are inconsistent across resources, in the library they are:
|
225
|
-
|
226
|
-
<pre>
|
227
|
-
Twilio::SMS.all :created_before => date, :created_after => date, :sent_before => date, :sent_after # :"created_#{when}" and :"sent_#{when}" are synonomous
|
228
|
-
Twilio::Notification.all :created_before => date, :created_after => date
|
229
|
-
Twilio::Call.all :started_before => date, :started_after => date, :ended_before => date, :ended_after => date
|
230
|
-
</pre>
|
231
|
-
|
232
|
-
### Pagination
|
233
|
-
|
234
|
-
The Twilio API paginates API responses and by default it will return 30 objects in one response, this can be overridden to return up to a maximum of 1000 per response using the `:page_size` option, If more than 1000 resources instances exist, the `:page` option is available, e.g.
|
235
|
-
|
236
|
-
<pre>Twilio::Call.all :started_after => start_date, :ended_before => end_date, :page_size => 1000, :page => 7</pre>
|
237
|
-
|
238
|
-
To determine how many resources exist, the `.count` class method exists, which accepts the same options as `.all` in order to constrain the query e.g.
|
239
|
-
|
240
|
-
<pre>Twilio::Call.count :started_after => start_date, :ended_before => end_date</pre>
|
241
|
-
|
242
|
-
It returns an integer corresponding to how many resource instances exist with those conditions.
|
243
|
-
|
244
|
-
## Updating resource attributes
|
245
|
-
|
246
|
-
Certain resources have attributes that can be updated with the REST API. Instances of those resources can be updated using either a setter method with a name that corresponds to the attribute, or by using the `#update_attributes`.
|
247
|
-
|
248
|
-
<pre>
|
249
|
-
call = Twilio::Call.all(:status => 'in-progress').first
|
250
|
-
|
251
|
-
call.url = 'http://example.com/in_ur_apiz_hijackin_ur_callz.xml'
|
252
|
-
call.update_attributes :url => 'http://example.com/in_ur_apiz_hijackin_ur_callz.xml'
|
253
|
-
</pre>
|
254
|
-
|
255
|
-
These are both equivalent, i.e. they immediately make an API request and update the state of the object with the API response. The first one in fact uses the second one internally and is just a shortcut. Use the second when there is more than one attribute to be updated in the same HTTP request.
|
256
|
-
|
257
332
|
## Manipulating conference participants
|
258
333
|
|
259
334
|
The participants list resource is a subresource of a conference resource instance:
|
@@ -272,26 +347,17 @@ Participants can be removed from the conference using the '#destroy instance met
|
|
272
347
|
|
273
348
|
# Singleton resources
|
274
349
|
|
275
|
-
The Twilio API in its current incarnation has
|
350
|
+
The Twilio API in its current incarnation has one singleton (scoped per account) resource, correspondingly there is Twilio::Sandbox singleton objects.
|
276
351
|
|
277
352
|
To access properties of a singleton object the property name should be called as a method on the object itself, e.g.
|
278
353
|
|
279
|
-
<pre>Twilio::
|
354
|
+
<pre>Twilio::Sandobox.friendly_name</pre>
|
280
355
|
|
281
356
|
The first time a method is invoked on the object an API call is made to retrieve the data. The methods themselves are not defined until they are called, i.e. lazy evaluation. This strategy means that addtional properties added to subsequent versions of the API should not break the library.
|
282
357
|
|
283
358
|
To reload the data when needed `Twilio::Account.reload!` will make another API call and update its own internal state.
|
284
359
|
|
285
|
-
|
286
|
-
|
287
|
-
The only account property that can be modified via the REST API is the friendly name, e.g.
|
288
|
-
|
289
|
-
<pre>Twilio::Account.friendly_name = "I'm so vain, I had to change my name!"</pre>
|
290
|
-
<pre>Twilio::Account.update_attributes :friendly_name => "I'm so vain, I had to change my name!"</pre>
|
291
|
-
|
292
|
-
This will update the API immediately with a POST request.
|
293
|
-
|
294
|
-
Twilio::Sandbox supports more options. Please refer to the Twilio REST API documentation for an up to date list of properties.
|
360
|
+
Please refer to the Twilio REST API documentation for an up to date list of properties that the sandbox resource implements
|
295
361
|
|
296
362
|
# Searching for and purchasing available phone numbers
|
297
363
|
|
@@ -311,6 +377,11 @@ Twilio::IncomingPhoneNumber.create :phone_number => numbers.first.phone_number,
|
|
311
377
|
|
312
378
|
# Recordings
|
313
379
|
|
314
|
-
A recording resource instance has an extra instance method: `#mp3` this returns a publicly accessible URL for the MP3 representation of the resource instance.
|
380
|
+
A recording resource instance has an extra instance method: `#mp3` this returns a publicly accessible URL for the MP3 representation of the resource instance.
|
315
381
|
|
382
|
+
# Contributors
|
316
383
|
|
384
|
+
* Stevie Graham
|
385
|
+
* TJ Singleton
|
386
|
+
* Christopher Durtschi
|
387
|
+
* Dan Imrie-Situnayake
|
data/lib/railtie.rb
CHANGED
@@ -11,7 +11,7 @@ module Twilio
|
|
11
11
|
def compile(template)
|
12
12
|
<<-EOS
|
13
13
|
controller.content_type = 'text/xml'
|
14
|
-
Twilio::TwiML.build {|res| #{template.source} }
|
14
|
+
Twilio::TwiML.build { |res| #{template.source} }
|
15
15
|
EOS
|
16
16
|
end
|
17
17
|
end
|
@@ -19,6 +19,8 @@ module Twilio
|
|
19
19
|
end
|
20
20
|
end
|
21
21
|
|
22
|
+
ActionController::Base.class_eval { before_filter Twilio::RequestFilter }
|
23
|
+
|
22
24
|
::ActionView::Template.register_template_handler(:voice, ActionView::Template::Handlers::TwiML)
|
23
25
|
::Mime::Type.register_alias 'text/xml', :voice
|
24
26
|
end
|
data/lib/twilio/account.rb
CHANGED
@@ -1,25 +1,22 @@
|
|
1
1
|
module Twilio
|
2
|
-
|
2
|
+
class Account
|
3
3
|
include Twilio::Resource
|
4
|
-
|
4
|
+
include Twilio::Persistable
|
5
|
+
extend Twilio::Associations
|
6
|
+
extend Twilio::Finder
|
5
7
|
|
6
|
-
|
7
|
-
@attributes.empty? ? reload! : @attributes
|
8
|
-
end
|
8
|
+
mutable_attributes :friendly_name, :status
|
9
9
|
|
10
|
-
|
11
|
-
|
12
|
-
end
|
10
|
+
has_many :calls, :sms, :recordings, :conferences, :incoming_phone_numbers,
|
11
|
+
:notifications, :outgoing_caller_ids, :transcriptions
|
13
12
|
|
14
|
-
|
15
|
-
|
13
|
+
class << self
|
14
|
+
private
|
15
|
+
def resource_path(account_sid)
|
16
|
+
"/Accounts"
|
17
|
+
end
|
16
18
|
end
|
17
19
|
|
18
|
-
private
|
19
|
-
def path
|
20
|
-
"/Accounts/#{Twilio::ACCOUNT_SID}.json"
|
21
|
-
end
|
22
|
-
|
23
|
-
extend self
|
24
20
|
end
|
25
21
|
end
|
22
|
+
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module Twilio
|
2
|
+
class Application
|
3
|
+
extend Twilio::Finder
|
4
|
+
include Twilio::Resource
|
5
|
+
include Twilio::Persistable
|
6
|
+
include Twilio::Deletable
|
7
|
+
|
8
|
+
mutable_attributes :friendly_name, :api_version, :voice_url, :voice_method, :voice_fallback_url,
|
9
|
+
:voice_fallback_method, :status_callback, :status_callback_method, :sms_url, :sms_method,
|
10
|
+
:sms_fallback_url, :sms_fallback_method
|
11
|
+
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'active_support/core_ext/string'
|
2
|
+
|
3
|
+
module Twilio
|
4
|
+
class AssociationProxy
|
5
|
+
instance_methods.each { |meth| undef_method meth unless meth.to_s =~ /^__/ }
|
6
|
+
def initialize(delegator, target)
|
7
|
+
@delegator, @target = delegator, target
|
8
|
+
@delegator_name = @delegator.class.name.demodulize.downcase
|
9
|
+
end
|
10
|
+
|
11
|
+
def inspect
|
12
|
+
@target.all :"#{@delegator_name}_sid" => @delegator.sid
|
13
|
+
end
|
14
|
+
|
15
|
+
def method_missing(meth, *args, &blk)
|
16
|
+
options = args.empty? ? args.<<({})[-1] : args[-1]
|
17
|
+
options.update :"#{@delegator_name}_sid" => @delegator.sid
|
18
|
+
@target.__send__ meth, *args, &blk
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'active_support/core_ext/string'
|
2
|
+
|
3
|
+
module Twilio
|
4
|
+
module Associations
|
5
|
+
def has_many(*collection)
|
6
|
+
collection.each do |objects|
|
7
|
+
define_method(objects) do
|
8
|
+
klass = Twilio.const_get objects.to_s.singularize.camelize
|
9
|
+
Twilio::AssociationProxy.new self, klass
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
data/lib/twilio/call.rb
CHANGED
@@ -2,7 +2,12 @@ module Twilio
|
|
2
2
|
class Call
|
3
3
|
include Twilio::Resource
|
4
4
|
include Twilio::Persistable
|
5
|
-
extend
|
5
|
+
extend Twilio::Finder
|
6
|
+
extend Twilio::Associations
|
7
|
+
|
8
|
+
has_many :recordings
|
9
|
+
|
10
|
+
mutable_attributes :url, :method, :status
|
6
11
|
|
7
12
|
class << self
|
8
13
|
alias old_create create
|
@@ -17,11 +22,10 @@ module Twilio
|
|
17
22
|
private
|
18
23
|
def prepare_params(opts) # :nodoc:
|
19
24
|
pairs = opts.map do |k,v|
|
20
|
-
if
|
21
|
-
k = k.to_s
|
25
|
+
if %w(started_before started_after ended_before ended_after).include? k
|
22
26
|
# Fancy schmancy-ness to handle Twilio <= URI operator for dates
|
23
27
|
comparator = k =~ /before$/ ? '<=' : '>='
|
24
|
-
delineator = k =~ /started/ ? 'Start' : 'End'
|
28
|
+
delineator = k =~ /started/ ? 'Start' : 'End'
|
25
29
|
CGI.escape(delineator << "Time" << comparator << v.to_s)
|
26
30
|
else
|
27
31
|
"#{k.to_s.camelize}=#{CGI.escape v.to_s}"
|
@@ -40,11 +44,5 @@ module Twilio
|
|
40
44
|
update_attributes :status => 'completed'
|
41
45
|
end
|
42
46
|
|
43
|
-
# Update Handler URL
|
44
|
-
def url=(url)
|
45
|
-
# If this attribute exists it is assumed the API call to create a call has been made, so we need to tell Twilio.
|
46
|
-
update_attributes :url => url if self[:status]
|
47
|
-
self[:url] = url
|
48
|
-
end
|
49
47
|
end
|
50
|
-
end
|
48
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module Twilio
|
2
|
+
module CapabilityToken
|
3
|
+
def create(opts={})
|
4
|
+
opts.stringify_keys!
|
5
|
+
account_sid, auth_token = *credentials_for(opts)
|
6
|
+
payload = {
|
7
|
+
:exp => (opts.delete('expires') || 1.hour.from_now).to_i,
|
8
|
+
:scope => opts.map { |k,v| send k, v, opts }.join(' '),
|
9
|
+
:iss => account_sid
|
10
|
+
}
|
11
|
+
JWT.encode payload, auth_token
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
def credentials_for(opts)
|
17
|
+
if opts['account_sid'] && opts['auth_token']
|
18
|
+
[opts.delete('account_sid'), opts.delete('auth_token')]
|
19
|
+
else
|
20
|
+
[Twilio::ACCOUNT_SID, Twilio::AUTH_TOKEN]
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def allow_incoming(client_id, opts)
|
25
|
+
token_for 'client', 'incoming', { 'clientName' => client_id }
|
26
|
+
end
|
27
|
+
|
28
|
+
def allow_outgoing(payload, opts)
|
29
|
+
p = {}
|
30
|
+
if payload.respond_to? :each
|
31
|
+
p['appSid'] = payload.shift
|
32
|
+
p['appParams'] = uri_encode payload.pop
|
33
|
+
else # it's a string
|
34
|
+
p['appSid'] = payload
|
35
|
+
end
|
36
|
+
p['clientName'] = opts['allow_incoming'] if opts['allow_incoming']
|
37
|
+
token_for 'client', 'outgoing', p
|
38
|
+
end
|
39
|
+
|
40
|
+
def uri_encode(hash)
|
41
|
+
hash.map { |k,v| "#{CGI.escape k.to_s}=#{CGI.escape v}" }.join '&'
|
42
|
+
end
|
43
|
+
|
44
|
+
def token_for(service, privilege, params = {})
|
45
|
+
token = "scope:#{service}:#{privilege}"
|
46
|
+
token << "?#{uri_encode params}" if params.any?
|
47
|
+
end
|
48
|
+
|
49
|
+
extend self
|
50
|
+
end
|
51
|
+
end
|
data/lib/twilio/config.rb
CHANGED
@@ -1,7 +1,16 @@
|
|
1
1
|
module Twilio
|
2
2
|
module Config
|
3
|
-
def setup &blk
|
4
|
-
|
3
|
+
def setup(opts={}, &blk)
|
4
|
+
if block_given?
|
5
|
+
instance_eval &blk
|
6
|
+
warn 'The block syntax for configuration is deprecated. Use an options hash instead, e.g. Twilio::Config.setup account_sid: "AC00000000000000000000000", auth_token: "xxxxxxxxxxxxxxxxxxx"'
|
7
|
+
else
|
8
|
+
opts.map do |k,v|
|
9
|
+
const = k.to_s.upcase
|
10
|
+
Twilio.const_set(const, v) unless Twilio.const_defined? const
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
5
14
|
end
|
6
15
|
|
7
16
|
def method_missing(meth, *args, &blk)
|
@@ -11,4 +20,4 @@ module Twilio
|
|
11
20
|
|
12
21
|
extend self
|
13
22
|
end
|
14
|
-
end
|
23
|
+
end
|
data/lib/twilio/finder.rb
CHANGED
@@ -1,7 +1,10 @@
|
|
1
1
|
module Twilio
|
2
2
|
module Finder
|
3
|
-
def find(id)
|
4
|
-
|
3
|
+
def find(id, opts={})
|
4
|
+
opts = opts.with_indifferent_access
|
5
|
+
# Support subaccounts by optionally passing in an account_sid or account object
|
6
|
+
account_sid = opts.delete('account_sid') || opts.delete('account').try(:sid) || Twilio::ACCOUNT_SID
|
7
|
+
res = get "#{resource_path(account_sid)}/#{id}.json"
|
5
8
|
hash = res.parsed_response
|
6
9
|
if (200..299).include? res.code
|
7
10
|
hash['api_version'] = hash['api_version'].to_s # api_version parsed as a date by http_party
|
@@ -10,27 +13,34 @@ module Twilio
|
|
10
13
|
end
|
11
14
|
|
12
15
|
def count(opts={})
|
13
|
-
|
14
|
-
|
16
|
+
opts = opts.with_indifferent_access
|
17
|
+
# Support subaccounts by optionally passing in an account_sid or account object
|
18
|
+
account_sid = opts.delete('account_sid') || opts.delete('account').try(:sid) || Twilio::ACCOUNT_SID
|
19
|
+
params = prepare_params opts if opts.any?
|
20
|
+
get("#{resource_path(account_sid)}.json#{params}").parsed_response['total']
|
15
21
|
end
|
16
22
|
|
17
23
|
def all(opts={})
|
18
|
-
|
19
|
-
|
24
|
+
opts = opts.with_indifferent_access
|
25
|
+
# Support subaccounts by optionally passing in an account_sid or account object
|
26
|
+
account_sid = opts.delete('account_sid') || opts.delete('account').try(:sid) || Twilio::ACCOUNT_SID
|
27
|
+
params = prepare_params opts if opts.any?
|
28
|
+
handle_response get "#{resource_path(account_sid)}.json#{params}"
|
20
29
|
end
|
21
30
|
|
22
31
|
private
|
23
32
|
|
24
|
-
def
|
25
|
-
|
26
|
-
|
27
|
-
|
33
|
+
def resource_path(account_sid)
|
34
|
+
"/Accounts/#{account_sid}/#{resource_name}"
|
35
|
+
end
|
36
|
+
|
37
|
+
def resource_name
|
38
|
+
name.demodulize.pluralize
|
28
39
|
end
|
29
40
|
|
30
41
|
def prepare_params(opts) # :nodoc:
|
31
42
|
pairs = opts.map do |k,v|
|
32
|
-
if
|
33
|
-
k = k.to_s
|
43
|
+
if %w(updated_before created_before updated_after created_after).include? k
|
34
44
|
# Fancy schmancy-ness to handle Twilio <= URI operator for dates
|
35
45
|
comparator = k =~ /before$/ ? '<=' : '>='
|
36
46
|
CGI.escape("Date" << k.gsub(/\_\w+$/, '').capitalize << comparator << v.to_s)
|
@@ -5,10 +5,9 @@ module Twilio
|
|
5
5
|
include Twilio::Persistable
|
6
6
|
include Twilio::Deletable
|
7
7
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
end
|
8
|
+
mutable_attributes :friendly_name, :api_version, :voice_url, :voice_method,
|
9
|
+
:voice_fallback_url, :voice_fallback_method, :status_callback, :status_callback_method,
|
10
|
+
:sms_url, :sms_method, :sms_method, :sms_fallback_url, :sms_fallback_method, :voice_caller_id_lookup
|
11
|
+
|
13
12
|
end
|
14
13
|
end
|
data/lib/twilio/notification.rb
CHANGED
@@ -8,8 +8,7 @@ module Twilio
|
|
8
8
|
private
|
9
9
|
def prepare_params(opts) # :nodoc:
|
10
10
|
pairs = opts.map do |k,v|
|
11
|
-
if
|
12
|
-
k = k.to_s
|
11
|
+
if %w(created_before created_after).include? k
|
13
12
|
# Fancy schmancy-ness to handle Twilio <= URI operator for dates
|
14
13
|
comparator = k =~ /before$/ ? '<=' : '>='
|
15
14
|
CGI.escape("MessageDate" << comparator << v.to_s)
|
data/lib/twilio/participant.rb
CHANGED
data/lib/twilio/persistable.rb
CHANGED
@@ -2,23 +2,31 @@ module Twilio
|
|
2
2
|
module Persistable
|
3
3
|
|
4
4
|
def self.included(base)
|
5
|
-
base.
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
5
|
+
base.instance_eval do
|
6
|
+
def create(attrs={})
|
7
|
+
attrs = attrs.with_indifferent_access
|
8
|
+
# Support subaccounts by optionally passing in an account_sid or account object
|
9
|
+
account_sid = attrs.delete('account_sid') || attrs.delete('account').try(:sid) || Twilio::ACCOUNT_SID
|
10
|
+
|
11
|
+
res = post "#{resource_path(account_sid)}.json", :body => Hash[attrs.map { |k,v| [k.to_s.camelize, v]}]
|
12
|
+
|
13
|
+
if (400..599).include? res.code
|
14
|
+
raise Twilio::APIError.new "Error ##{res.parsed_response['code']}: #{res.parsed_response['message']}"
|
15
|
+
else
|
16
|
+
res.parsed_response['api_version'] = res.parsed_response['api_version'].to_s
|
17
|
+
new res.parsed_response
|
18
18
|
end
|
19
19
|
end
|
20
|
+
|
21
|
+
private
|
22
|
+
def resource_path(account_sid)
|
23
|
+
"/Accounts/#{account_sid}/#{resource_name}"
|
24
|
+
end
|
25
|
+
|
26
|
+
def resource_name
|
27
|
+
name.demodulize.pluralize
|
28
|
+
end
|
20
29
|
end
|
21
30
|
end
|
22
|
-
|
23
31
|
end
|
24
32
|
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'base64'
|
2
|
+
require 'openssl'
|
3
|
+
require 'digest/sha1'
|
4
|
+
|
5
|
+
module Twilio
|
6
|
+
module RequestFilter
|
7
|
+
def filter(controller)
|
8
|
+
request = controller.request
|
9
|
+
if request.format.voice? && request.ssl?
|
10
|
+
controller.head(:forbidden) if expected_signature_for(request) != request.env['X-Twilio-Signature']
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
def expected_signature_for(request)
|
16
|
+
string_to_sign = request.url + request.params.sort.join
|
17
|
+
digest = OpenSSL::Digest::Digest.new 'sha1'
|
18
|
+
hash = OpenSSL::HMAC.digest digest, Twilio::AUTH_TOKEN, string_to_sign
|
19
|
+
|
20
|
+
Base64.encode64(hash).strip
|
21
|
+
end
|
22
|
+
|
23
|
+
extend self
|
24
|
+
end
|
25
|
+
end
|
data/lib/twilio/resource.rb
CHANGED
@@ -7,6 +7,10 @@ module Twilio
|
|
7
7
|
@attributes = attrs.with_indifferent_access
|
8
8
|
end
|
9
9
|
|
10
|
+
def inspect
|
11
|
+
"#<#{self.class} #{@attributes.map { |k,v| "#{k}: #{v.inspect}" }.join ', '}>"
|
12
|
+
end
|
13
|
+
|
10
14
|
def [](key)
|
11
15
|
attributes[key]
|
12
16
|
end
|
@@ -22,6 +26,10 @@ module Twilio
|
|
22
26
|
end
|
23
27
|
|
24
28
|
private
|
29
|
+
def resource_name
|
30
|
+
klass.name.demodulize.pluralize
|
31
|
+
end
|
32
|
+
|
25
33
|
def klass
|
26
34
|
self.class == Module ? self : self.class
|
27
35
|
end
|
@@ -34,8 +42,8 @@ module Twilio
|
|
34
42
|
end
|
35
43
|
end
|
36
44
|
|
37
|
-
def path
|
38
|
-
|
45
|
+
def path
|
46
|
+
uri[11,uri.length]
|
39
47
|
end
|
40
48
|
|
41
49
|
def handle_response(res) # :nodoc:
|
@@ -55,7 +63,7 @@ module Twilio
|
|
55
63
|
elsif meth =~ /^#{meth}\?$/i
|
56
64
|
add_predicate meth
|
57
65
|
send meth
|
58
|
-
elsif attributes.keys.include? meth
|
66
|
+
elsif attributes.keys.include? meth
|
59
67
|
add_attr_reader meth
|
60
68
|
send meth
|
61
69
|
else
|
@@ -95,12 +103,20 @@ module Twilio
|
|
95
103
|
|
96
104
|
class << base
|
97
105
|
# decorate http methods with authentication
|
98
|
-
%w<post get put delete>.each do |meth|
|
99
|
-
define_method(meth) do |*args| # splatted args necessary hack since <= 1.8.7 does not support optional block args
|
106
|
+
%w<post get put delete>.each do |meth|
|
107
|
+
define_method(meth) do |*args| # splatted args necessary hack since <= 1.8.7 does not support optional block args
|
100
108
|
opts = args[1] || {}
|
101
109
|
super args.first, opts.merge(:basic_auth => { :username => Twilio::ACCOUNT_SID, :password => Twilio::AUTH_TOKEN })
|
102
110
|
end
|
103
111
|
end
|
112
|
+
|
113
|
+
def mutable_attributes(*attrs)
|
114
|
+
attrs.each do |attr|
|
115
|
+
define_method "#{attr}=" do |arg|
|
116
|
+
update_attributes attr => arg
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
104
120
|
end
|
105
121
|
end
|
106
122
|
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Twilio
|
2
|
+
class ShortCode
|
3
|
+
include Twilio::Resource
|
4
|
+
extend Twilio::Finder
|
5
|
+
|
6
|
+
class << self
|
7
|
+
private
|
8
|
+
|
9
|
+
def resource_name
|
10
|
+
"SMS/ShortCodes"
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
mutable_attributes :friendly_name, :api_version, :sms_url, :sms_method,
|
15
|
+
:sms_fallback_url, :sms_fallback_method
|
16
|
+
|
17
|
+
private
|
18
|
+
def resource_name
|
19
|
+
"SMS/ShortCodes"
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
end
|
data/lib/twilio/sms.rb
CHANGED
@@ -6,10 +6,13 @@ module Twilio
|
|
6
6
|
|
7
7
|
class << self
|
8
8
|
private
|
9
|
+
def resource_name
|
10
|
+
"SMS/Messages"
|
11
|
+
end
|
12
|
+
|
9
13
|
def prepare_params(opts) # :nodoc:
|
10
14
|
pairs = opts.map do |k,v|
|
11
|
-
if
|
12
|
-
k = k.to_s
|
15
|
+
if %w(created_before created_after sent_before sent_after).include? k
|
13
16
|
# Fancy schmancy-ness to handle Twilio <= URI operator for dates
|
14
17
|
comparator = k =~ /before$/ ? '<=' : '>='
|
15
18
|
URI.encode("DateSent" << comparator << v.to_s)
|
data/lib/twilio-rb.rb
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
%w<rubygems active_support active_support/inflector cgi jwt yajl yajl/json_gem httparty builder>.each { |lib| require lib }
|
2
|
+
%w<resource finder persistable deletable associations association_proxy>.each { |lib| require File.join(File.dirname(__FILE__), 'twilio', "#{lib}.rb") }
|
3
|
+
|
4
|
+
module Twilio
|
5
|
+
API_ENDPOINT = 'https://api.twilio.com/2010-04-01'
|
6
|
+
APIError = Class.new StandardError
|
7
|
+
ConfigurationError = Class.new StandardError
|
8
|
+
InvalidStateError = Class.new StandardError
|
9
|
+
|
10
|
+
class << self
|
11
|
+
def const_missing(const_name)
|
12
|
+
if [:ACCOUNT_SID, :AUTH_TOKEN].include? const_name
|
13
|
+
raise Twilio::ConfigurationError.new "Cannot complete request. Please set #{const_name.to_s.downcase} with Twilio::Config.setup first!"
|
14
|
+
else
|
15
|
+
super
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
Dir[File.join(File.dirname(__FILE__), 'twilio', '*.rb')].each { |lib| require lib }
|
22
|
+
|
23
|
+
require File.join(File.dirname(__FILE__), 'railtie.rb') if Object.const_defined?(:Rails) && Rails.version =~ /^3/
|
data/lib/twilio.rb
CHANGED
@@ -1,23 +1,3 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
require File.dirname(__FILE__) +'/twilio-rb.rb'
|
2
|
+
warn 'require "twilio" is deprecated and will be removed in a future release. Use require "twilio-rb" instead.'
|
3
3
|
|
4
|
-
module Twilio
|
5
|
-
API_ENDPOINT = 'https://api.twilio.com/2010-04-01'
|
6
|
-
APIError = Class.new StandardError
|
7
|
-
ConfigurationError = Class.new StandardError
|
8
|
-
InvalidStateError = Class.new StandardError
|
9
|
-
|
10
|
-
class << self
|
11
|
-
def const_missing(const_name)
|
12
|
-
if [:ACCOUNT_SID, :AUTH_TOKEN].include? const_name
|
13
|
-
raise Twilio::ConfigurationError.new "Cannot complete request. Please set #{const_name.to_s.downcase} with Twilio::Config.setup first!"
|
14
|
-
else
|
15
|
-
super
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
Dir[File.join(File.dirname(__FILE__), 'twilio', '*.rb')].each { |lib| require lib }
|
22
|
-
|
23
|
-
require File.join(File.dirname(__FILE__), 'railtie.rb') if Object.const_defined?(:Rails) && Rails.version =~ /^3/
|
metadata
CHANGED
@@ -1,120 +1,152 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: twilio-rb
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
5
|
-
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 2.0.0
|
5
|
+
prerelease:
|
6
6
|
platform: ruby
|
7
|
-
authors:
|
7
|
+
authors:
|
8
8
|
- Stevie Graham
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
dependencies:
|
16
|
-
- !ruby/object:Gem::Dependency
|
12
|
+
date: 2011-09-20 00:00:00.000000000Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
17
15
|
name: activesupport
|
18
|
-
|
19
|
-
requirement: &id001 !ruby/object:Gem::Requirement
|
16
|
+
requirement: &70298512157240 !ruby/object:Gem::Requirement
|
20
17
|
none: false
|
21
|
-
requirements:
|
22
|
-
- -
|
23
|
-
- !ruby/object:Gem::Version
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
24
21
|
version: 3.0.0
|
25
22
|
type: :runtime
|
26
|
-
version_requirements: *id001
|
27
|
-
- !ruby/object:Gem::Dependency
|
28
|
-
name: i18n
|
29
23
|
prerelease: false
|
30
|
-
|
24
|
+
version_requirements: *70298512157240
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: i18n
|
27
|
+
requirement: &70298512130420 !ruby/object:Gem::Requirement
|
31
28
|
none: false
|
32
|
-
requirements:
|
29
|
+
requirements:
|
33
30
|
- - ~>
|
34
|
-
- !ruby/object:Gem::Version
|
35
|
-
version: 0.5
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '0.5'
|
36
33
|
type: :runtime
|
37
|
-
version_requirements: *id002
|
38
|
-
- !ruby/object:Gem::Dependency
|
39
|
-
name: yajl-ruby
|
40
34
|
prerelease: false
|
41
|
-
|
35
|
+
version_requirements: *70298512130420
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: yajl-ruby
|
38
|
+
requirement: &70298512129800 !ruby/object:Gem::Requirement
|
42
39
|
none: false
|
43
|
-
requirements:
|
44
|
-
- -
|
45
|
-
- !ruby/object:Gem::Version
|
40
|
+
requirements:
|
41
|
+
- - ! '>='
|
42
|
+
- !ruby/object:Gem::Version
|
46
43
|
version: 0.7.7
|
47
44
|
type: :runtime
|
48
|
-
version_requirements: *id003
|
49
|
-
- !ruby/object:Gem::Dependency
|
50
|
-
name: httparty
|
51
45
|
prerelease: false
|
52
|
-
|
46
|
+
version_requirements: *70298512129800
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: httparty
|
49
|
+
requirement: &70298512129220 !ruby/object:Gem::Requirement
|
53
50
|
none: false
|
54
|
-
requirements:
|
55
|
-
- -
|
56
|
-
- !ruby/object:Gem::Version
|
51
|
+
requirements:
|
52
|
+
- - ! '>='
|
53
|
+
- !ruby/object:Gem::Version
|
57
54
|
version: 0.6.1
|
58
55
|
type: :runtime
|
59
|
-
|
60
|
-
|
56
|
+
prerelease: false
|
57
|
+
version_requirements: *70298512129220
|
58
|
+
- !ruby/object:Gem::Dependency
|
61
59
|
name: builder
|
60
|
+
requirement: &70298512128620 !ruby/object:Gem::Requirement
|
61
|
+
none: false
|
62
|
+
requirements:
|
63
|
+
- - ! '>='
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
version: 3.0.0
|
66
|
+
type: :runtime
|
62
67
|
prerelease: false
|
63
|
-
|
68
|
+
version_requirements: *70298512128620
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: jwt
|
71
|
+
requirement: &70298512127920 !ruby/object:Gem::Requirement
|
64
72
|
none: false
|
65
|
-
requirements:
|
66
|
-
- -
|
67
|
-
- !ruby/object:Gem::Version
|
68
|
-
version:
|
73
|
+
requirements:
|
74
|
+
- - ! '>='
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: 0.1.3
|
69
77
|
type: :runtime
|
70
|
-
version_requirements: *id005
|
71
|
-
- !ruby/object:Gem::Dependency
|
72
|
-
name: webmock
|
73
78
|
prerelease: false
|
74
|
-
|
79
|
+
version_requirements: *70298512127920
|
80
|
+
- !ruby/object:Gem::Dependency
|
81
|
+
name: webmock
|
82
|
+
requirement: &70298512127380 !ruby/object:Gem::Requirement
|
75
83
|
none: false
|
76
|
-
requirements:
|
77
|
-
- -
|
78
|
-
- !ruby/object:Gem::Version
|
84
|
+
requirements:
|
85
|
+
- - ! '>='
|
86
|
+
- !ruby/object:Gem::Version
|
79
87
|
version: 1.6.1
|
80
88
|
type: :development
|
81
|
-
version_requirements: *id006
|
82
|
-
- !ruby/object:Gem::Dependency
|
83
|
-
name: rspec
|
84
89
|
prerelease: false
|
85
|
-
|
90
|
+
version_requirements: *70298512127380
|
91
|
+
- !ruby/object:Gem::Dependency
|
92
|
+
name: rspec
|
93
|
+
requirement: &70298512126660 !ruby/object:Gem::Requirement
|
86
94
|
none: false
|
87
|
-
requirements:
|
88
|
-
- -
|
89
|
-
- !ruby/object:Gem::Version
|
95
|
+
requirements:
|
96
|
+
- - ! '>='
|
97
|
+
- !ruby/object:Gem::Version
|
90
98
|
version: 2.2.0
|
91
99
|
type: :development
|
92
|
-
version_requirements: *id007
|
93
|
-
- !ruby/object:Gem::Dependency
|
94
|
-
name: mocha
|
95
100
|
prerelease: false
|
96
|
-
|
101
|
+
version_requirements: *70298512126660
|
102
|
+
- !ruby/object:Gem::Dependency
|
103
|
+
name: mocha
|
104
|
+
requirement: &70298512126060 !ruby/object:Gem::Requirement
|
97
105
|
none: false
|
98
|
-
requirements:
|
99
|
-
- -
|
100
|
-
- !ruby/object:Gem::Version
|
106
|
+
requirements:
|
107
|
+
- - ! '>='
|
108
|
+
- !ruby/object:Gem::Version
|
101
109
|
version: 0.9.10
|
102
110
|
type: :development
|
103
|
-
|
111
|
+
prerelease: false
|
112
|
+
version_requirements: *70298512126060
|
113
|
+
- !ruby/object:Gem::Dependency
|
114
|
+
name: timecop
|
115
|
+
requirement: &70298512125460 !ruby/object:Gem::Requirement
|
116
|
+
none: false
|
117
|
+
requirements:
|
118
|
+
- - ! '>='
|
119
|
+
- !ruby/object:Gem::Version
|
120
|
+
version: 0.3.5
|
121
|
+
type: :development
|
122
|
+
prerelease: false
|
123
|
+
version_requirements: *70298512125460
|
124
|
+
- !ruby/object:Gem::Dependency
|
125
|
+
name: rake
|
126
|
+
requirement: &70298512124880 !ruby/object:Gem::Requirement
|
127
|
+
none: false
|
128
|
+
requirements:
|
129
|
+
- - =
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: 0.8.7
|
132
|
+
type: :development
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: *70298512124880
|
104
135
|
description: A nice Ruby wrapper for the Twilio REST API
|
105
136
|
email: sjtgraham@mac.com
|
106
137
|
executables: []
|
107
|
-
|
108
138
|
extensions: []
|
109
|
-
|
110
139
|
extra_rdoc_files: []
|
111
|
-
|
112
|
-
files:
|
140
|
+
files:
|
113
141
|
- README.md
|
114
142
|
- lib/railtie.rb
|
115
143
|
- lib/twilio/account.rb
|
144
|
+
- lib/twilio/application.rb
|
145
|
+
- lib/twilio/association_proxy.rb
|
146
|
+
- lib/twilio/associations.rb
|
116
147
|
- lib/twilio/available_phone_number.rb
|
117
148
|
- lib/twilio/call.rb
|
149
|
+
- lib/twilio/capability.rb
|
118
150
|
- lib/twilio/conference.rb
|
119
151
|
- lib/twilio/config.rb
|
120
152
|
- lib/twilio/deletable.rb
|
@@ -125,39 +157,37 @@ files:
|
|
125
157
|
- lib/twilio/participant.rb
|
126
158
|
- lib/twilio/persistable.rb
|
127
159
|
- lib/twilio/recording.rb
|
160
|
+
- lib/twilio/request_filter.rb
|
128
161
|
- lib/twilio/resource.rb
|
129
162
|
- lib/twilio/sandbox.rb
|
163
|
+
- lib/twilio/short_code.rb
|
130
164
|
- lib/twilio/sms.rb
|
131
165
|
- lib/twilio/transcription.rb
|
132
166
|
- lib/twilio/twiml.rb
|
167
|
+
- lib/twilio-rb.rb
|
133
168
|
- lib/twilio.rb
|
134
|
-
has_rdoc: true
|
135
169
|
homepage: http://github.com/stevegraham/twilio-rb
|
136
170
|
licenses: []
|
137
|
-
|
138
171
|
post_install_message:
|
139
172
|
rdoc_options: []
|
140
|
-
|
141
|
-
require_paths:
|
173
|
+
require_paths:
|
142
174
|
- lib
|
143
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
175
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
144
176
|
none: false
|
145
|
-
requirements:
|
146
|
-
- -
|
147
|
-
- !ruby/object:Gem::Version
|
177
|
+
requirements:
|
178
|
+
- - ! '>='
|
179
|
+
- !ruby/object:Gem::Version
|
148
180
|
version: 1.8.7
|
149
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
181
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
150
182
|
none: false
|
151
|
-
requirements:
|
152
|
-
- -
|
153
|
-
- !ruby/object:Gem::Version
|
154
|
-
version:
|
183
|
+
requirements:
|
184
|
+
- - ! '>='
|
185
|
+
- !ruby/object:Gem::Version
|
186
|
+
version: '0'
|
155
187
|
requirements: []
|
156
|
-
|
157
188
|
rubyforge_project:
|
158
|
-
rubygems_version: 1.
|
189
|
+
rubygems_version: 1.8.6
|
159
190
|
signing_key:
|
160
191
|
specification_version: 3
|
161
192
|
summary: Interact with the Twilio API in a nice Ruby way.
|
162
193
|
test_files: []
|
163
|
-
|