twilio-ruby 3.11.5 → 3.12.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (62) hide show
  1. checksums.yaml +13 -5
  2. data/.gitignore +1 -1
  3. data/.travis.yml +20 -8
  4. data/AUTHORS.md +29 -25
  5. data/{CHANGES → CHANGES.md} +45 -1
  6. data/Gemfile +8 -1
  7. data/{LICENSE → LICENSE.md} +1 -1
  8. data/Makefile +1 -2
  9. data/README.md +57 -26
  10. data/Rakefile +8 -10
  11. data/docs/getting-started.rst +3 -3
  12. data/docs/usage/applications.rst +5 -5
  13. data/docs/usage/basics.rst +17 -4
  14. data/docs/usage/caller-ids.rst +2 -2
  15. data/docs/usage/conferences.rst +5 -5
  16. data/docs/usage/errors.rst +1 -1
  17. data/docs/usage/messages.rst +6 -6
  18. data/docs/usage/notifications.rst +2 -2
  19. data/docs/usage/phone-calls.rst +7 -7
  20. data/docs/usage/phone-numbers.rst +12 -12
  21. data/docs/usage/queues.rst +6 -6
  22. data/docs/usage/recordings.rst +5 -5
  23. data/docs/usage/sip.rst +5 -5
  24. data/docs/usage/token-generation.rst +18 -3
  25. data/docs/usage/transcriptions.rst +1 -1
  26. data/docs/usage/twiml.rst +1 -1
  27. data/docs/usage/validation.rst +27 -1
  28. data/examples/print-call-log.rb +1 -1
  29. data/lib/rack/twilio_webhook_authentication.rb +40 -0
  30. data/lib/twilio-ruby/rest/call_feedback.rb +28 -0
  31. data/lib/twilio-ruby/rest/call_feedback_summary.rb +13 -0
  32. data/lib/twilio-ruby/rest/calls.rb +6 -1
  33. data/lib/twilio-ruby/rest/client.rb +43 -5
  34. data/lib/twilio-ruby/rest/list_resource.rb +10 -4
  35. data/lib/twilio-ruby/rest/usage/records.rb +2 -2
  36. data/lib/twilio-ruby/twiml/response.rb +1 -0
  37. data/lib/twilio-ruby/util/capability.rb +6 -3
  38. data/lib/twilio-ruby/util/configuration.rb +7 -0
  39. data/lib/twilio-ruby/util/request_validator.rb +3 -2
  40. data/lib/twilio-ruby/version.rb +1 -1
  41. data/lib/twilio-ruby.rb +25 -0
  42. data/spec/rack/twilio_webhook_authentication_spec.rb +76 -0
  43. data/spec/rest/account_spec.rb +20 -20
  44. data/spec/rest/call_feedback_spec.rb +12 -0
  45. data/spec/rest/call_feedback_summary_spec.rb +9 -0
  46. data/spec/rest/call_spec.rb +4 -4
  47. data/spec/rest/client_spec.rb +114 -38
  48. data/spec/rest/conference_spec.rb +2 -2
  49. data/spec/rest/instance_resource_spec.rb +3 -3
  50. data/spec/rest/message_spec.rb +2 -2
  51. data/spec/rest/numbers_spec.rb +12 -12
  52. data/spec/rest/queue_spec.rb +2 -2
  53. data/spec/rest/recording_spec.rb +2 -2
  54. data/spec/spec_helper.rb +12 -3
  55. data/spec/support/fakeweb.rb +2 -0
  56. data/spec/twilio_spec.rb +15 -0
  57. data/spec/util/capability_spec.rb +167 -118
  58. data/spec/util/configuration_spec.rb +13 -0
  59. data/spec/util/request_validator_spec.rb +31 -3
  60. data/spec/util/url_encode_spec.rb +1 -1
  61. data/twilio-ruby.gemspec +28 -27
  62. metadata +46 -71
@@ -25,7 +25,7 @@ outputs valid `TwiML <http://www.twilio.com/docs/api/twiml/>`_.
25
25
  auth_token = "YYYYYYYYYYYYYYYYYY"
26
26
 
27
27
  @client = Twilio::REST::Client.new account_sid, auth_token
28
- @call = @client.account.calls.create({:to => "9991231234",
28
+ @call = @client.calls.create({:to => "9991231234",
29
29
  :from => "9991231234",
30
30
  :url => "http://foo.com/call.xml"})
31
31
  puts @call.length
@@ -48,7 +48,7 @@ you can use the client to retrieve that record.
48
48
 
49
49
  @client = Twilio::REST::Client.new account_sid, auth_token
50
50
  sid = "CA12341234"
51
- @call = @client.account.calls.get(sid)
51
+ @call = @client.calls.get(sid)
52
52
 
53
53
 
54
54
  Accessing Specific Call Resources
@@ -69,7 +69,7 @@ just like the :class:`Calls` resource itself.
69
69
 
70
70
  @client = Twilio::REST::Client.new account_sid, auth_token
71
71
  sid = "CA12341234"
72
- @call = @client.account.calls.get(sid)
72
+ @call = @client.calls.get(sid)
73
73
 
74
74
  puts @call.notifications.list()
75
75
  puts @call.recordings.list()
@@ -109,7 +109,7 @@ redirect them as necessary
109
109
  auth_token = "YYYYYYYYYYYYYYYYYY"
110
110
 
111
111
  @client = Twilio::REST::Client.new account_sid, auth_token
112
- @calls = @client.account.calls.list({:status => "in-progress"})
112
+ @calls = @client.calls.list({:status => "in-progress"})
113
113
 
114
114
  @calls.each do |call|
115
115
  call.redirect_to("http://twimlets.com/holdmusic?Bucket=com.twilio.music.ambient")
@@ -127,7 +127,7 @@ Ending all live calls is also possible
127
127
  auth_token = "YYYYYYYYYYYYYYYYYY"
128
128
 
129
129
  @client = Twilio::REST::Client.new account_sid, auth_token
130
- @calls = @client.account.calls.list({:status => "in-progress"})
130
+ @calls = @client.calls.list({:status => "in-progress"})
131
131
 
132
132
  @calls.each do |call|
133
133
  call.hangup()
@@ -148,7 +148,7 @@ resource to update the record without having to use :meth:`get` first.
148
148
 
149
149
  @client = Twilio::REST::Client.new account_sid, auth_token
150
150
  sid = "CA12341234"
151
- @client.account.calls.get(sid).redirect_to("http://twimlets.com/holdmusic?Bucket=com.twilio.music.ambient")
151
+ @client.calls.get(sid).redirect_to("http://twimlets.com/holdmusic?Bucket=com.twilio.music.ambient")
152
152
 
153
153
  Hanging up the call also works.
154
154
 
@@ -162,5 +162,5 @@ Hanging up the call also works.
162
162
 
163
163
  @client = Twilio::REST::Client.new account_sid, auth_token
164
164
  sid = "CA12341234"
165
- @client.account.calls.get(sid).hangup()
165
+ @client.calls.get(sid).hangup()
166
166
 
@@ -27,7 +27,7 @@ Once we find one, we'll purchase it for our account.
27
27
  auth_token = "YYYYYYYYYYYYYYYYYY"
28
28
 
29
29
  @client = Twilio::REST::Client.new account_sid, auth_token
30
- numbers = @client.account.available_phone_numbers.list(:area_code=>"530")
30
+ numbers = @client.available_phone_numbers.list(:area_code=>"530")
31
31
 
32
32
  if numbers:
33
33
  numbers[0].purchase()
@@ -51,13 +51,13 @@ You can search for numbers for a given type.
51
51
  .. code-block:: ruby
52
52
 
53
53
  # local
54
- numbers = @client.account.available_phone_numbers.local.list()
54
+ numbers = @client.available_phone_numbers.local.list()
55
55
 
56
56
  # toll free
57
- numbers = @client.account.available_phone_numbers.toll_free.list()
57
+ numbers = @client.available_phone_numbers.toll_free.list()
58
58
 
59
59
  # mobile
60
- numbers = @client.account.available_phone_numbers.mobile.list()
60
+ numbers = @client.available_phone_numbers.mobile.list()
61
61
 
62
62
  Numbers Containing Words
63
63
  ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -67,13 +67,13 @@ The following example will find any phone number with "FOO" in it.
67
67
 
68
68
  .. code-block:: ruby
69
69
 
70
- numbers = @client.account.available_phone_numbers.list(:contains=>"FOO")
70
+ numbers = @client.available_phone_numbers.list(:contains=>"FOO")
71
71
 
72
72
  You can use the ''*'' wildcard to match any character. The following example finds any phone number that matches the pattern ''D*D''.
73
73
 
74
74
  .. code-block:: ruby
75
75
 
76
- numbers = @client.account.available_phone_numbers.list(:contains=>"D*D")
76
+ numbers = @client.available_phone_numbers.list(:contains=>"D*D")
77
77
 
78
78
 
79
79
  International Numbers
@@ -85,7 +85,7 @@ international numbers.
85
85
 
86
86
  .. code-block:: ruby
87
87
 
88
- numbers = @client.account.available_phone_numbers.list(:country=>"FR")
88
+ numbers = @client.available_phone_numbers.list(:country=>"FR")
89
89
 
90
90
 
91
91
  :meth:`PhoneNumbers.search` method has plenty of other options to augment your search :
@@ -115,7 +115,7 @@ If you've found a phone number you want, you can purchase the number.
115
115
  auth_token = "YYYYYYYYYYYYYYYYYY"
116
116
 
117
117
  @client = Twilio::REST::Client.new account_sid, auth_token
118
- @number = @client.account.phone_numbers.purchase({:phone_number => "+15305431234"})
118
+ @number = @client.available_phone_numbers.purchase({:phone_number => "+15305431234"})
119
119
 
120
120
  However, it's easier to purchase numbers after finding them using search (as
121
121
  shown in the first example).
@@ -138,9 +138,9 @@ listed in the `IncomingPhoneNumbers Resource documentation
138
138
  auth_token = "YYYYYYYYYYYYYYYYYY"
139
139
 
140
140
  @client = Twilio::REST::Client.new account_sid, auth_token
141
- @client.account.phone_numbers.list(api_version="2010-04-01").each do |number|
142
- number.update({:voice_url => "http://twimlets.com/holdmusic?" +
143
- "Bucket=com.twilio.music.ambient",
141
+ @client.available_phone_numbers.list(api_version="2010-04-01").each do |number|
142
+ number.update({:voice_url => "http://twimlets.com/holdmusic?" +
143
+ "Bucket=com.twilio.music.ambient",
144
144
  :status_callback => "http://example.com/callback"})
145
145
 
146
146
 
@@ -161,7 +161,7 @@ An :class:`Application` encapsulates all necessary URLs for use with phone numbe
161
161
 
162
162
  phone_sid = "PNXXXXXXXXXXXXXXXXX"
163
163
 
164
- @number = @client.account.phone_numbers.get(phone_sid)
164
+ @number = @client.available_phone_numbers.get(phone_sid)
165
165
  @number.update(:sms_application_sid => "APXXXXXXXXXXXXXXXXXX")
166
166
 
167
167
  See :doc:`/usage/applications` for instructions on updating and maintaining Applications.
@@ -22,8 +22,8 @@ Listing Queues
22
22
  auth_token = "YYYYYYYYYYYYYYYYYY"
23
23
 
24
24
  @client = Twilio::REST::Client.new account_sid, auth_token
25
- @queues = @client.account.queues.list()
26
-
25
+ @queues = @client.queues.list()
26
+
27
27
  @queues.each do |queue|
28
28
  puts queue.sid
29
29
  end
@@ -44,7 +44,7 @@ represents all current calls in the queue.
44
44
  auth_token = "YYYYYYYYYYYYYYYYYY"
45
45
 
46
46
  @client = Twilio::REST::Client.new account_sid, auth_token
47
- @queue = @client.account.queues.get("QU123")
47
+ @queue = @client.queues.get("QU123")
48
48
 
49
49
  @queue.members.list().each do |member|
50
50
  print member.call_sid
@@ -74,8 +74,8 @@ first call in the queue.
74
74
 
75
75
  queue_sid = "QUAAAAAAAAAAAAA"
76
76
  call_sid = "CAXXXXXXXXXXXXXX"
77
-
78
- @members = @client.account.queues.get(queue_sid).members
77
+
78
+ @members = @client.queues.get(queue_sid).members
79
79
 
80
80
  # Get the first call in the queue
81
81
  puts members.front.date_enqueued
@@ -106,7 +106,7 @@ default values are 'Front' and 'GET'
106
106
 
107
107
  queue_sid = "QUAAAAAAAAAAAAA"
108
108
 
109
- @members = @client.account.queues.get(queue_sid).members
109
+ @members = @client.queues.get(queue_sid).members
110
110
 
111
111
  # Dequeue the first call in the queue
112
112
  puts @members.dequeue('http://www.twilio.com/welcome/call')
@@ -14,7 +14,7 @@ Audio Formats
14
14
 
15
15
  Each :class:`Recording` has a few special methods. To get the url
16
16
  for the wav format of this recording, use :meth:`Recording.wav`. For the
17
- mp3 format, use :meth:`Recording.mp3`. To make requests for either of
17
+ mp3 format, use :meth:`Recording.mp3`. To make requests for either of
18
18
  these formats use the same method with a '!' appended. These methods
19
19
  both take a block to be executed as soon as the response returns.
20
20
 
@@ -35,7 +35,7 @@ for each :class:`Recording`.
35
35
 
36
36
  @client = Twilio::REST::Client.new account_sid, auth_token
37
37
 
38
- @client.account.recordings.list().each do |recording|
38
+ @client.recordings.list().each do |recording|
39
39
  puts recording.duration
40
40
 
41
41
  You can filter recordings by CallSid by passing the Sid as :attr:`call`.
@@ -52,7 +52,7 @@ The following will only show recordings made before January 1, 2011.
52
52
  auth_token = "YYYYYYYYYYYYYYYYYY"
53
53
 
54
54
  @client = Twilio::REST::Client.new account_sid, auth_token
55
- @client.account.recordings.list(before=date(2011,1,1)).each do |recording|:
55
+ @client.recordings.list(before=date(2011,1,1)).each do |recording|:
56
56
  puts recording.duration
57
57
 
58
58
 
@@ -70,7 +70,7 @@ The :class:`Recordings` resource allows you to delete unnecessary recordings.
70
70
  auth_token = "YYYYYYYYYYYYYYYYYY"
71
71
 
72
72
  @client = Twilio::REST::Client.new account_sid, auth_token
73
- @client.account.recordings.get("RC123").delete()
73
+ @client.recordings.get("RC123").delete()
74
74
 
75
75
 
76
76
  Accessing Related Transcptions
@@ -89,7 +89,7 @@ with this recording.
89
89
  auth_token = "YYYYYYYYYYYYYYYYYY"
90
90
 
91
91
  @client = Twilio::REST::Client.new account_sid, auth_token
92
- @recording = @client.account.recordings.get("RC123")
92
+ @recording = @client.recordings.get("RC123")
93
93
 
94
94
  @recording.transcriptions.list().each do |transcription|
95
95
  puts transcription.transcription_text
data/docs/usage/sip.rst CHANGED
@@ -26,7 +26,7 @@ under sip.twilio.com.
26
26
 
27
27
  @client = Twilio::REST::Client.new account_sid, auth_token
28
28
 
29
- @domain = @client.account.sip.domains.create(
29
+ @domain = @client.sip.domains.create(
30
30
  {:friendly_name => "The Office Domain",
31
31
  :voice_url => "http://example.com/voice",
32
32
  :domain_name => "dunder-mifflin-scranton.sip.twilio.com",}
@@ -38,7 +38,7 @@ Creating a new IpAccessControlList
38
38
 
39
39
  To control access to your new domain, you'll need to explicitly grant access
40
40
  to individual ip addresses. To do this, you'll first need to create an
41
- :class:`IpAccessControlList` to hold the ip addresses you wish to allow.
41
+ :class:`IpAccessControlList` to hold the ip addresses you wish to allow.
42
42
 
43
43
  .. code-block:: ruby
44
44
 
@@ -50,7 +50,7 @@ to individual ip addresses. To do this, you'll first need to create an
50
50
 
51
51
  @client = Twilio::REST::Client.new account_sid, auth_token
52
52
 
53
- @ip_acl = @client.account.sip.ip_access_control_lists.create(
53
+ @ip_acl = @client.sip.ip_access_control_lists.create(
54
54
  {:friendly_name => "The Office IpAccessControlList",}
55
55
  )
56
56
  puts @ip_acl.sid
@@ -70,7 +70,7 @@ Now it's time to add an :class:`IpAddress` to your new :class:`IpAccessControlLi
70
70
 
71
71
  @client = Twilio::REST::Client.new account_sid, auth_token
72
72
 
73
- @ip_address = @client.account.sip.ip_access_control_lists.get(
73
+ @ip_address = @client.sip.ip_access_control_lists.get(
74
74
  "AL456", # IpAccessControlList sid
75
75
  ).ip_addresses.create(
76
76
  {:friendly_name => "Dwights's Computer",
@@ -94,7 +94,7 @@ associate them. To do this, create an :class:`IpAccessControlListMapping`.
94
94
 
95
95
  @client = Twilio::REST::Client.new account_sid, auth_token
96
96
 
97
- @ip_acl_mapping = @client.account.sip.domains.get(
97
+ @ip_acl_mapping = @client.sip.domains.get(
98
98
  "SD456", # SIP Domain sid
99
99
  ).ip_access_control_list_mappings.create(
100
100
  {:ip_access_control_list_sid => "AL789"})
@@ -17,11 +17,11 @@ security and authorization. The `Capability Token documentation
17
17
  <http://www.twilio.com/docs/tokens>`_ explains in depth the purpose and
18
18
  features of these tokens.
19
19
 
20
- :class:`TwilioCapability` is responsible for the creation of these capability
21
- tokens. You'll need your Twilio AccountSid and AuthToken.
20
+ :class:`Twilio::Util::Capability` is responsible for the creation of these
21
+ capability tokens. You'll need your Twilio AccountSid and AuthToken.
22
22
 
23
23
  .. code-block:: ruby
24
-
24
+
25
25
  require 'twilio-ruby'
26
26
 
27
27
  # Find these values at twilio.com/user/account
@@ -30,6 +30,21 @@ tokens. You'll need your Twilio AccountSid and AuthToken.
30
30
 
31
31
  @capability = Twilio::Util::Capability.new account_sid, auth_token
32
32
 
33
+ You can also configure capability tokens using the top level configure method,
34
+ like so:
35
+
36
+ .. code-block:: ruby
37
+
38
+ require 'twilio-ruby'
39
+
40
+ Twilio.configure do |config|
41
+ config.account_sid = "ACXXXXXXXXXXXXXXXXX"
42
+ config.auth_token = "YYYYYYYYYYYYYYYYYY"
43
+ end
44
+
45
+ @capability = Twilio::Util::Capability.new
46
+
47
+
33
48
 
34
49
  Allow Incoming Connections
35
50
  ==============================
@@ -26,6 +26,6 @@ The following code will print out the length of each :class:`Transcription`.
26
26
  auth_token = "YYYYYYYYYYYYYYYYYY"
27
27
 
28
28
  @client = Twilio::REST::Client.new account_sid, auth_token
29
- @client.account.transcriptions.list().each do |transcription|
29
+ @client.transcriptions.list().each do |transcription|
30
30
  puts transcription.duration
31
31
 
data/docs/usage/twiml.rst CHANGED
@@ -53,7 +53,7 @@ Any example of nesting nouns in verbs
53
53
 
54
54
  Twilio::TwiML::Response.new do |r|
55
55
  r.Say "hello"
56
- r.Gather :finish_on_key => 4 do |g|
56
+ r.Gather :finishOnKey => 4 do |g|
57
57
  g.Say "world"
58
58
  end
59
59
  end.text
@@ -53,7 +53,6 @@ actually from Twilio.
53
53
  puts "NOT VALID. It might have been spoofed!"
54
54
  end
55
55
 
56
-
57
56
  Trailing Slashes
58
57
  ==================
59
58
 
@@ -69,3 +68,30 @@ https://mycompany.com/twilio and you may have built the hash using
69
68
  https://mycompany.com/twilio/. More information can be found in our
70
69
  documentation on validating requests.
71
70
 
71
+ Rack Middleware
72
+ ===============
73
+
74
+ If you are serving up your site using a Rack based framework, such as Sinatra or
75
+ Rails, you can use the Rack middleware that is included in the gem to protect
76
+ from spoofing attempts.
77
+
78
+ To use the middleware, you need to set it up with your Twilio Auth Token and a
79
+ set of paths to watch. For example, here is how you would use the middleware in
80
+ a Sinatra application:
81
+
82
+ .. code-block:: ruby
83
+
84
+ require 'sinatra'
85
+ require 'twilio-ruby'
86
+
87
+ auth_token = 'YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY'
88
+
89
+ use Rack::TwilioWebhookAuthentication, auth_token, /\/messages/
90
+
91
+ post '/messages' do
92
+ # response with TwiML
93
+ end
94
+
95
+ Now, any POST request to /messages in your application that doesn't validate as
96
+ a Twilio request, will automatically respond with a 403 status code and your
97
+ action will not be hit.
@@ -13,7 +13,7 @@ auth_token = '62ea81de3a5b414154eb263595357c69'
13
13
  # set up a client
14
14
  client = Twilio::REST::Client.new(account_sid, auth_token)
15
15
 
16
- calls = client.account.calls.list
16
+ calls = client.calls.list
17
17
 
18
18
  begin
19
19
  calls.each do |call|
@@ -0,0 +1,40 @@
1
+ module Rack
2
+ # Middleware that authenticates webhooks from Twilio using the request
3
+ # validator.
4
+ #
5
+ # The middleware takes an auth token with which to set up the request
6
+ # validator and any number of paths. When a path matches the incoming request
7
+ # path, the request will be checked for authentication.
8
+ #
9
+ # Example:
10
+ #
11
+ # require 'rack'
12
+ # use Rack::TwilioWebhookAuthentication, ENV['AUTH_TOKEN'], /\/messages/
13
+ #
14
+ # The above appends this middleware to the stack, using an auth token saved in
15
+ # the ENV and only against paths that match /\/messages/. If the request
16
+ # validates then it gets passed on to the action as normal. If the request
17
+ # doesn't validate then the middleware responds immediately with a 403 status.
18
+
19
+ class TwilioWebhookAuthentication
20
+ def initialize(app, auth_token, *paths)
21
+ @app = app
22
+ @auth_token = auth_token
23
+ @path_regex = Regexp.union(paths)
24
+ end
25
+
26
+ def call(env)
27
+ return @app.call(env) unless env["PATH_INFO"].match(@path_regex)
28
+ validator = Twilio::Util::RequestValidator.new(@auth_token)
29
+ request = Rack::Request.new(env)
30
+ original_url = request.url
31
+ params = request.post? ? request.POST : {}
32
+ signature = env['HTTP_X_TWILIO_SIGNATURE']
33
+ if validator.validate(original_url, params, signature)
34
+ @app.call(env)
35
+ else
36
+ [403, {'Content-Type' => 'text/plain'}, ["Twilio Request Validation Failed."]]
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,28 @@
1
+ module Twilio
2
+ module REST
3
+ class Feedback < ListResource;
4
+
5
+ ##
6
+ # Get this feedback object.
7
+ #
8
+ # Overridden because GETS to /Feedback
9
+ # returns an instance, not a list.
10
+ def get(params={}, full_path=false)
11
+ raise "Can't fetch feedback without a REST Client" unless @client
12
+ response = @client.get @path, params, full_path
13
+ path = full_path ? @path.split('.')[0] : @path
14
+ @instance_class.new path, @client, response
15
+ end
16
+
17
+ ##
18
+ # Creates a new Feedback object.
19
+ def create(params={})
20
+ raise "Can't create feedback without a REST Client" unless @client
21
+ response = @client.post @path, params
22
+ @instance_class.new @path, @client, response
23
+ end
24
+ end
25
+
26
+ class FeedbackInstance < InstanceResource; end
27
+ end
28
+ end
@@ -0,0 +1,13 @@
1
+ module Twilio
2
+ module REST
3
+ class FeedbackSummary < ListResource
4
+ def initialize(path, client)
5
+ @path, @client = path, client
6
+ @instance_class = Twilio::REST::FeedbackSummaryInstance
7
+ @list_key, @instance_id_key = 'feedback_summary', 'sid'
8
+ end
9
+ end
10
+
11
+ class FeedbackSummaryInstance < InstanceResource; end
12
+ end
13
+ end
@@ -1,6 +1,11 @@
1
1
  module Twilio
2
2
  module REST
3
3
  class Calls < ListResource
4
+ def initialize(path, client)
5
+ super
6
+ resource :feedback_summary
7
+ end
8
+
4
9
  def make(from, to, url)
5
10
  create :from => from, :to => to, :url => url
6
11
  end
@@ -9,7 +14,7 @@ module Twilio
9
14
  class Call < InstanceResource
10
15
  def initialize(path, client, params={})
11
16
  super path, client, params
12
- resource :recordings, :notifications
17
+ resource :recordings, :notifications, :feedback
13
18
  end
14
19
 
15
20
  def redirect_to(url)
@@ -28,6 +28,12 @@ module Twilio
28
28
  #
29
29
  # @client.account.calls
30
30
  #
31
+ # For convenience, the resources of the default account are also available
32
+ # on the client object. So the following call is equivalent to the example
33
+ # above
34
+ #
35
+ # @client.calls
36
+ #
31
37
  # represents an account's call list.
32
38
  #
33
39
  # ==== @client.accounts
@@ -48,7 +54,11 @@ module Twilio
48
54
  API_VERSION = '2010-04-01'
49
55
 
50
56
  # 1.8.7 doesn't have the RUBY_ENGINE constant.
51
- engine = !defined?(RUBY_ENGINE) || RUBY_ENGINE == 'ruby'
57
+ if defined?(RUBY_ENGINE)
58
+ engine = RUBY_ENGINE
59
+ else
60
+ engine = 'ruby'
61
+ end
52
62
 
53
63
  HTTP_HEADERS = {
54
64
  'Accept' => 'application/json',
@@ -75,7 +85,8 @@ module Twilio
75
85
 
76
86
  ##
77
87
  # Instantiate a new HTTP client to talk to Twilio. The parameters
78
- # +account_sid+ and +auth_token+ are required and used to generate the
88
+ # +account_sid+ and +auth_token+ are required, unless you have configured
89
+ # them already using the block configure syntax, and used to generate the
79
90
  # HTTP basic auth header in each request. The +options+ parameter is a
80
91
  # hash of connection configuration options. the following keys are
81
92
  # supported:
@@ -138,9 +149,16 @@ module Twilio
138
149
  #
139
150
  # The number of times to retry a request that has failed before throwing
140
151
  # an exception. Defaults to one.
141
- def initialize(account_sid, auth_token, options={})
142
- @account_sid, @auth_token = account_sid.strip, auth_token.strip
152
+ def initialize(*args)
153
+ options = args.last.is_a?(Hash) ? args.pop : {}
143
154
  @config = DEFAULTS.merge! options
155
+
156
+ @account_sid = args[0] || Twilio.account_sid
157
+ @auth_token = args[1] || Twilio.auth_token
158
+ if @account_sid.nil? || @auth_token.nil?
159
+ raise ArgumentError, 'Account SID and auth token are required'
160
+ end
161
+
144
162
  set_up_connection
145
163
  set_up_subresources
146
164
  end
@@ -169,6 +187,26 @@ module Twilio
169
187
  end
170
188
  end
171
189
 
190
+ ##
191
+ # Delegate account methods from the client. This saves having to call
192
+ # <tt>client.account</tt> every time for resources on the default
193
+ # account.
194
+ def method_missing(method_name, *args, &block)
195
+ if account.respond_to?(method_name)
196
+ account.send(method_name, *args, &block)
197
+ else
198
+ super
199
+ end
200
+ end
201
+
202
+ def respond_to?(method_name, include_private=false)
203
+ if account.respond_to?(method_name, include_private)
204
+ true
205
+ else
206
+ super
207
+ end
208
+ end
209
+
172
210
  private
173
211
 
174
212
  ##
@@ -182,7 +220,7 @@ module Twilio
182
220
  @connection.open_timeout = @config[:timeout]
183
221
  @connection.read_timeout = @config[:timeout]
184
222
  end
185
-
223
+
186
224
  ##
187
225
  # Set up the ssl properties of the <tt>@connection</tt> Net::HTTP object.
188
226
  # This is a private method documented for completeness.
@@ -3,9 +3,12 @@ module Twilio
3
3
  class ListResource
4
4
  include Utils
5
5
 
6
-
7
6
  def initialize(path, client)
8
- custom_names = {"Media" => "MediaInstance", "IpAddresses" => "IpAddress"}
7
+ custom_names = {
8
+ 'Media' => 'MediaInstance',
9
+ 'IpAddresses' => 'IpAddress',
10
+ 'Feedback' => 'FeedbackInstance',
11
+ }
9
12
  @path, @client = path, client
10
13
  resource_name = self.class.name.split('::')[-1]
11
14
  instance_name = custom_names.fetch(resource_name, resource_name.chop)
@@ -13,7 +16,7 @@ module Twilio
13
16
  # The next line grabs the enclosing module. Necessary for resources
14
17
  # contained in their own submodule like /SMS/Messages
15
18
  parent_module = self.class.to_s.split('::')[-2]
16
- full_module_path = parent_module == "REST" ? (Twilio::REST) : (Twilio::REST.const_get parent_module)
19
+ full_module_path = parent_module == 'REST' ? (Twilio::REST) : (Twilio::REST.const_get parent_module)
17
20
 
18
21
  @instance_class = full_module_path.const_get instance_name
19
22
  @list_key, @instance_id_key = detwilify(resource_name), 'sid'
@@ -94,7 +97,10 @@ module Twilio
94
97
  end
95
98
 
96
99
  def resource(*resources)
97
- custom_resource_names = {:sms => 'SMS', :sip => 'SIP'}
100
+ custom_resource_names = {
101
+ :sms => 'SMS',
102
+ :sip => 'SIP',
103
+ }
98
104
  resources.each do |r|
99
105
  resource = twilify r
100
106
  relative_path = custom_resource_names.fetch(r, resource)
@@ -2,8 +2,8 @@ module Twilio
2
2
  module REST
3
3
  class Records < ListResource
4
4
 
5
- SUBRESOURCES = [:daily, :monthly, :yearly, :all_time, :today, :yesterday,
6
- :this_month, :last_month]
5
+ SUBRESOURCES = [:daily, :monthly, :yearly, :all_time, :today,
6
+ :yesterday, :this_month, :last_month]
7
7
 
8
8
  def initialize(path, client)
9
9
  super
@@ -3,6 +3,7 @@ module Twilio
3
3
  class Response
4
4
 
5
5
  attr_reader :text
6
+ alias_method :to_xml , :text
6
7
 
7
8
  def initialize(&block)
8
9
  xml = Builder::XmlMarkup.new
@@ -4,9 +4,12 @@ module Twilio
4
4
 
5
5
  include Twilio::Util
6
6
 
7
- def initialize(account_sid, auth_token)
8
- @account_sid = account_sid
9
- @auth_token = auth_token
7
+ def initialize(account_sid = nil, auth_token = nil)
8
+ @account_sid = account_sid || Twilio.account_sid
9
+ @auth_token = auth_token || Twilio.auth_token
10
+ if @account_sid.nil? || @auth_token.nil?
11
+ raise ArgumentError, 'Account SID and auth token are required'
12
+ end
10
13
  @capabilities = []
11
14
  end
12
15
 
@@ -0,0 +1,7 @@
1
+ module Twilio
2
+ module Util
3
+ class Configuration
4
+ attr_accessor :account_sid, :auth_token
5
+ end
6
+ end
7
+ end
@@ -2,8 +2,9 @@ module Twilio
2
2
  module Util
3
3
  class RequestValidator
4
4
 
5
- def initialize(auth_token)
6
- @auth_token = auth_token
5
+ def initialize(auth_token = nil)
6
+ @auth_token = auth_token || Twilio.auth_token
7
+ raise ArgumentError, 'Auth token is required' if @auth_token.nil?
7
8
  end
8
9
 
9
10
  def validate(url, params, signature)
@@ -1,3 +1,3 @@
1
1
  module Twilio
2
- VERSION = '3.11.5'
2
+ VERSION = '3.12.3'
3
3
  end