twilio-ruby 3.11.5 → 4.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.
Files changed (114) hide show
  1. checksums.yaml +13 -5
  2. data/.gitignore +1 -1
  3. data/.travis.yml +20 -9
  4. data/AUTHORS.md +32 -25
  5. data/CHANGES.md +203 -0
  6. data/Gemfile +8 -1
  7. data/{LICENSE → LICENSE.md} +4 -2
  8. data/Makefile +1 -2
  9. data/README.md +70 -39
  10. data/Rakefile +8 -10
  11. data/docs/faq.rst +3 -3
  12. data/docs/getting-started.rst +17 -12
  13. data/docs/index.rst +15 -0
  14. data/docs/usage/accounts.rst +6 -6
  15. data/docs/usage/addresses.rst +101 -0
  16. data/docs/usage/applications.rst +10 -10
  17. data/docs/usage/basics.rst +17 -4
  18. data/docs/usage/caller-ids.rst +4 -2
  19. data/docs/usage/conferences.rst +11 -11
  20. data/docs/usage/errors.rst +7 -7
  21. data/docs/usage/messages.rst +48 -20
  22. data/docs/usage/notifications.rst +6 -4
  23. data/docs/usage/phone-calls.rst +33 -14
  24. data/docs/usage/phone-numbers.rst +45 -31
  25. data/docs/usage/queues.rst +8 -8
  26. data/docs/usage/recordings.rst +12 -10
  27. data/docs/usage/sip.rst +15 -14
  28. data/docs/usage/taskrouter-tokens.rst +98 -0
  29. data/docs/usage/taskrouter.rst +226 -0
  30. data/docs/usage/token-generation.rst +19 -4
  31. data/docs/usage/transcriptions.rst +3 -2
  32. data/docs/usage/twiml.rst +7 -7
  33. data/docs/usage/validation.rst +39 -3
  34. data/examples/examples.rb +44 -20
  35. data/examples/print-call-log.rb +1 -1
  36. data/lib/rack/twilio_webhook_authentication.rb +47 -0
  37. data/lib/twilio-ruby/rest/accounts.rb +2 -1
  38. data/lib/twilio-ruby/rest/addresses/dependent_phone_numbers.rb +6 -0
  39. data/lib/twilio-ruby/rest/addresses.rb +12 -0
  40. data/lib/twilio-ruby/rest/base_client.rb +127 -0
  41. data/lib/twilio-ruby/rest/call_feedback.rb +28 -0
  42. data/lib/twilio-ruby/rest/call_feedback_summary.rb +13 -0
  43. data/lib/twilio-ruby/rest/calls.rb +10 -5
  44. data/lib/twilio-ruby/rest/client.rb +44 -109
  45. data/lib/twilio-ruby/rest/conferences/participants.rb +2 -2
  46. data/lib/twilio-ruby/rest/incoming_phone_numbers.rb +1 -1
  47. data/lib/twilio-ruby/rest/instance_resource.rb +2 -16
  48. data/lib/twilio-ruby/rest/list_resource.rb +20 -30
  49. data/lib/twilio-ruby/rest/lookups/phone_numbers.rb +17 -0
  50. data/lib/twilio-ruby/rest/lookups_client.rb +99 -0
  51. data/lib/twilio-ruby/rest/messages.rb +5 -0
  52. data/lib/twilio-ruby/rest/next_gen_list_resource.rb +36 -0
  53. data/lib/twilio-ruby/rest/outgoing_caller_ids.rb +1 -1
  54. data/lib/twilio-ruby/rest/queues/members.rb +1 -1
  55. data/lib/twilio-ruby/rest/sip.rb +1 -3
  56. data/lib/twilio-ruby/rest/sms/messages.rb +23 -0
  57. data/lib/twilio-ruby/rest/task_router/activities.rb +8 -0
  58. data/lib/twilio-ruby/rest/task_router/events.rb +8 -0
  59. data/lib/twilio-ruby/rest/task_router/reservations.rb +8 -0
  60. data/lib/twilio-ruby/rest/task_router/statistics.rb +26 -0
  61. data/lib/twilio-ruby/rest/task_router/task_queues.rb +17 -0
  62. data/lib/twilio-ruby/rest/task_router/task_queues_statistics.rb +15 -0
  63. data/lib/twilio-ruby/rest/task_router/tasks.rb +15 -0
  64. data/lib/twilio-ruby/rest/task_router/workers.rb +13 -0
  65. data/lib/twilio-ruby/rest/task_router/workers_statistics.rb +8 -0
  66. data/lib/twilio-ruby/rest/task_router/workflow_statistics.rb +7 -0
  67. data/lib/twilio-ruby/rest/task_router/workflows.rb +11 -0
  68. data/lib/twilio-ruby/rest/task_router/workspace_statistics.rb +7 -0
  69. data/lib/twilio-ruby/rest/task_router/workspaces.rb +17 -0
  70. data/lib/twilio-ruby/rest/task_router_client.rb +176 -0
  71. data/lib/twilio-ruby/rest/tokens.rb +7 -0
  72. data/lib/twilio-ruby/rest/usage/records.rb +2 -2
  73. data/lib/twilio-ruby/rest/utils.rb +35 -11
  74. data/lib/twilio-ruby/task_router/capability.rb +87 -0
  75. data/lib/twilio-ruby/task_router.rb +0 -0
  76. data/lib/twilio-ruby/twiml/response.rb +1 -0
  77. data/lib/twilio-ruby/util/capability.rb +10 -7
  78. data/lib/twilio-ruby/util/client_config.rb +29 -0
  79. data/lib/twilio-ruby/util/configuration.rb +7 -0
  80. data/lib/twilio-ruby/util/request_validator.rb +18 -3
  81. data/lib/twilio-ruby/version.rb +1 -1
  82. data/lib/twilio-ruby.rb +48 -0
  83. data/spec/rack/twilio_webhook_authentication_spec.rb +110 -0
  84. data/spec/rest/account_spec.rb +51 -20
  85. data/spec/rest/address_spec.rb +11 -0
  86. data/spec/rest/call_feedback_spec.rb +12 -0
  87. data/spec/rest/call_feedback_summary_spec.rb +9 -0
  88. data/spec/rest/call_spec.rb +8 -4
  89. data/spec/rest/client_spec.rb +209 -51
  90. data/spec/rest/conference_spec.rb +4 -2
  91. data/spec/rest/instance_resource_spec.rb +4 -4
  92. data/spec/rest/lookups/phone_number_spec.rb +8 -0
  93. data/spec/rest/message_spec.rb +2 -2
  94. data/spec/rest/numbers_spec.rb +25 -13
  95. data/spec/rest/queue_spec.rb +4 -2
  96. data/spec/rest/recording_spec.rb +4 -2
  97. data/spec/rest/sms/message_spec.rb +37 -0
  98. data/spec/rest/sms/messages_spec.rb +31 -0
  99. data/spec/rest/task_router/reservation_spec.rb +9 -0
  100. data/spec/rest/task_router/task_queue_spec.rb +9 -0
  101. data/spec/rest/token_spec.rb +7 -0
  102. data/spec/rest/utils_spec.rb +45 -0
  103. data/spec/spec_helper.rb +12 -3
  104. data/spec/support/fakeweb.rb +2 -0
  105. data/spec/task_router_spec.rb +114 -0
  106. data/spec/twilio_spec.rb +15 -0
  107. data/spec/util/capability_spec.rb +167 -118
  108. data/spec/util/client_config_spec.rb +21 -0
  109. data/spec/util/configuration_spec.rb +15 -0
  110. data/spec/util/request_validator_spec.rb +31 -3
  111. data/spec/util/url_encode_spec.rb +2 -2
  112. data/twilio-ruby.gemspec +28 -27
  113. metadata +93 -71
  114. data/CHANGES +0 -47
data/lib/twilio-ruby.rb CHANGED
@@ -5,20 +5,28 @@ require 'multi_json'
5
5
  require 'cgi'
6
6
  require 'openssl'
7
7
  require 'base64'
8
+ require 'forwardable'
8
9
  require 'jwt'
9
10
 
10
11
  require 'twilio-ruby/version' unless defined?(Twilio::VERSION)
11
12
  require 'twilio-ruby/util'
13
+ require 'twilio-ruby/util/client_config'
14
+ require 'twilio-ruby/util/configuration'
12
15
  require 'twilio-ruby/util/request_validator'
13
16
  require 'twilio-ruby/util/capability'
14
17
  require 'twilio-ruby/twiml/response'
18
+ require 'twilio-ruby/task_router'
19
+ require 'twilio-ruby/task_router/capability'
15
20
  require 'twilio-ruby/rest/errors'
16
21
  require 'twilio-ruby/rest/utils'
17
22
  require 'twilio-ruby/rest/list_resource'
23
+ require 'twilio-ruby/rest/next_gen_list_resource'
18
24
  require 'twilio-ruby/rest/instance_resource'
19
25
  require 'twilio-ruby/rest/sandbox'
20
26
  require 'twilio-ruby/rest/accounts'
21
27
  require 'twilio-ruby/rest/calls'
28
+ require 'twilio-ruby/rest/call_feedback'
29
+ require 'twilio-ruby/rest/call_feedback_summary'
22
30
  require 'twilio-ruby/rest/sms'
23
31
  require 'twilio-ruby/rest/sms/short_codes'
24
32
  require 'twilio-ruby/rest/sms/messages'
@@ -30,6 +38,20 @@ require 'twilio-ruby/rest/sip/credential_lists'
30
38
  require 'twilio-ruby/rest/sip/credential_lists/credentials'
31
39
  require 'twilio-ruby/rest/sip/ip_access_control_lists'
32
40
  require 'twilio-ruby/rest/sip/ip_access_control_lists/ip_addresses'
41
+ require 'twilio-ruby/rest/task_router/statistics'
42
+ require 'twilio-ruby/rest/task_router/activities'
43
+ require 'twilio-ruby/rest/task_router/events'
44
+ require 'twilio-ruby/rest/task_router/reservations'
45
+ require 'twilio-ruby/rest/task_router/task_queues'
46
+ require 'twilio-ruby/rest/task_router/task_queues_statistics'
47
+ require 'twilio-ruby/rest/task_router/tasks'
48
+ require 'twilio-ruby/rest/task_router/workers'
49
+ require 'twilio-ruby/rest/task_router/workers_statistics'
50
+ require 'twilio-ruby/rest/task_router/workflow_statistics'
51
+ require 'twilio-ruby/rest/task_router/workflows'
52
+ require 'twilio-ruby/rest/task_router/workspaces'
53
+ require 'twilio-ruby/rest/task_router/workspace_statistics'
54
+ require 'twilio-ruby/rest/lookups/phone_numbers'
33
55
  require 'twilio-ruby/rest/media'
34
56
  require 'twilio-ruby/rest/messages'
35
57
  require 'twilio-ruby/rest/applications'
@@ -54,5 +76,31 @@ require 'twilio-ruby/rest/usage/records'
54
76
  require 'twilio-ruby/rest/usage/triggers'
55
77
  require 'twilio-ruby/rest/recordings'
56
78
  require 'twilio-ruby/rest/transcriptions'
79
+ require 'twilio-ruby/rest/tokens'
57
80
  require 'twilio-ruby/rest/notifications'
81
+ require 'twilio-ruby/rest/addresses'
82
+ require 'twilio-ruby/rest/addresses/dependent_phone_numbers'
58
83
  require 'twilio-ruby/rest/client'
84
+ require 'twilio-ruby/rest/task_router_client'
85
+ require 'twilio-ruby/rest/lookups_client'
86
+ require 'rack/twilio_webhook_authentication'
87
+
88
+ module Twilio
89
+ extend SingleForwardable
90
+
91
+ def_delegators :configuration, :account_sid, :auth_token
92
+
93
+ ##
94
+ # Pre-configure with account SID and auth token so that you don't need to
95
+ # pass them to various initializers each time.
96
+ def self.configure(&block)
97
+ yield configuration
98
+ end
99
+
100
+ ##
101
+ # Returns an existing or instantiates a new configuration object.
102
+ def self.configuration
103
+ @configuration ||= Util::Configuration.new
104
+ end
105
+ private_class_method :configuration
106
+ end
@@ -0,0 +1,110 @@
1
+ require 'spec_helper'
2
+ require 'rack/mock'
3
+
4
+ describe Rack::TwilioWebhookAuthentication do
5
+ before do
6
+ @app = lambda {|env| [200, {'Content-Type' => 'text/plain'}, ['Hello']] }
7
+ end
8
+
9
+ describe 'new' do
10
+ it 'should initialize with an app, auth token and a path' do
11
+ expect {
12
+ Rack::TwilioWebhookAuthentication.new(@app, 'ABC', /\/voice/)
13
+ }.not_to raise_error
14
+ end
15
+
16
+ it 'should initialize with an app, auth token and paths' do
17
+ expect {
18
+ Rack::TwilioWebhookAuthentication.new(@app, 'ABC', /\/voice/, /\/sms/)
19
+ }.not_to raise_error
20
+ end
21
+
22
+ it 'should initialize with an app, dynamic token and paths' do
23
+ expect {
24
+ Rack::TwilioWebhookAuthentication.new(@app, nil, /\/voice/, /\/sms/)
25
+ }.not_to raise_error
26
+ end
27
+ end
28
+
29
+ describe 'calling against one path with dynamic auth token' do
30
+ it 'should allow a request through if it validates' do
31
+ auth_token = 'qwerty'
32
+ account_sid = 12345
33
+ expect_any_instance_of(Rack::Request).to receive(:post?).and_return(true)
34
+ expect_any_instance_of(Rack::Request).to receive(:POST).and_return({'AccountSid' => account_sid})
35
+ @middleware = Rack::TwilioWebhookAuthentication.new(@app, nil, /\/voice/) { |asid| auth_token}
36
+ request_validator = double('RequestValidator')
37
+ expect(Twilio::Util::RequestValidator).to receive(:new).with(auth_token).and_return(request_validator)
38
+ expect(request_validator).to receive(:validate).and_return(true)
39
+ request = Rack::MockRequest.env_for('/voice')
40
+ status, headers, body = @middleware.call(request)
41
+ expect(status).to be(200)
42
+ end
43
+ end
44
+
45
+ describe 'calling against one path' do
46
+ before do
47
+ @middleware = Rack::TwilioWebhookAuthentication.new(
48
+ @app, 'ABC', /\/voice/
49
+ )
50
+ end
51
+
52
+ it 'should not intercept when the path doesn\'t match' do
53
+ expect(Twilio::Util::RequestValidator).to_not receive(:validate)
54
+ request = Rack::MockRequest.env_for('/sms')
55
+ status, headers, body = @middleware.call(request)
56
+ expect(status).to be(200)
57
+ end
58
+
59
+ it 'should allow a request through if it validates' do
60
+ expect_any_instance_of(Twilio::Util::RequestValidator).to(
61
+ receive(:validate).and_return(true)
62
+ )
63
+ request = Rack::MockRequest.env_for('/voice')
64
+ status, headers, body = @middleware.call(request)
65
+ expect(status).to be(200)
66
+ end
67
+
68
+ it 'should short circuit a request to 403 if it does not validate' do
69
+ expect_any_instance_of(Twilio::Util::RequestValidator).to(
70
+ receive(:validate).and_return(false)
71
+ )
72
+ request = Rack::MockRequest.env_for('/voice')
73
+ status, headers, body = @middleware.call(request)
74
+ expect(status).to be(403)
75
+ end
76
+ end
77
+
78
+ describe 'calling against many paths' do
79
+ before do
80
+ @middleware = Rack::TwilioWebhookAuthentication.new(
81
+ @app, 'ABC', /\/voice/, /\/sms/
82
+ )
83
+ end
84
+
85
+ it 'should not intercept when the path doesn\'t match' do
86
+ expect(Twilio::Util::RequestValidator).to_not receive(:validate)
87
+ request = Rack::MockRequest.env_for('icesms')
88
+ status, headers, body = @middleware.call(request)
89
+ expect(status).to be(200)
90
+ end
91
+
92
+ it 'shold allow a request through if it validates' do
93
+ expect_any_instance_of(Twilio::Util::RequestValidator).to(
94
+ receive(:validate).and_return(true)
95
+ )
96
+ request = Rack::MockRequest.env_for('/sms')
97
+ status, headers, body = @middleware.call(request)
98
+ expect(status).to be(200)
99
+ end
100
+
101
+ it 'should short circuit a request to 403 if it does not validate' do
102
+ expect_any_instance_of(Twilio::Util::RequestValidator).to(
103
+ receive(:validate).and_return(false)
104
+ )
105
+ request = Rack::MockRequest.env_for('/sms')
106
+ status, headers, body = @middleware.call(request)
107
+ expect(status).to be(403)
108
+ end
109
+ end
110
+ end
@@ -7,52 +7,83 @@ describe Twilio::REST::Account do
7
7
  end
8
8
 
9
9
  it 'sets up incoming phone numbers resources object' do
10
- @account.should respond_to(:incoming_phone_numbers)
11
- @account.incoming_phone_numbers.instance_variable_get('@path').should == 'someUri/IncomingPhoneNumbers'
10
+ expect(@account).to respond_to(:incoming_phone_numbers)
11
+ expect(@account.incoming_phone_numbers.instance_variable_get('@path')).to(
12
+ eq('someUri/IncomingPhoneNumbers')
13
+ )
12
14
  end
13
15
 
14
16
  it 'sets up an available phone numbers resources object' do
15
- @account.should respond_to(:available_phone_numbers)
16
- @account.available_phone_numbers.instance_variable_get('@path').should == 'someUri/AvailablePhoneNumbers'
17
+ expect(@account).to respond_to(:available_phone_numbers)
18
+ expect(@account.available_phone_numbers.instance_variable_get('@path')).to(
19
+ eq('someUri/AvailablePhoneNumbers')
20
+ )
17
21
  end
18
22
 
19
23
  it 'sets up an outgoing caller ids resources object' do
20
- @account.should respond_to(:outgoing_caller_ids)
21
- @account.outgoing_caller_ids.instance_variable_get('@path').should == 'someUri/OutgoingCallerIds'
24
+ expect(@account).to respond_to(:outgoing_caller_ids)
25
+ expect(@account.outgoing_caller_ids.instance_variable_get('@path')).to eq(
26
+ 'someUri/OutgoingCallerIds'
27
+ )
22
28
  end
23
29
 
24
30
  it 'sets up a calls resources object' do
25
- @account.should respond_to(:calls)
26
- @account.calls.instance_variable_get('@path').should == 'someUri/Calls'
31
+ expect(@account).to respond_to(:calls)
32
+ expect(@account.calls.instance_variable_get('@path')).to eq('someUri/Calls')
27
33
  end
28
34
 
29
35
  it 'sets up a conferences resources object' do
30
- @account.should respond_to(:conferences)
31
- @account.conferences.instance_variable_get('@path').should == 'someUri/Conferences'
36
+ expect(@account).to respond_to(:conferences)
37
+ expect(@account.conferences.instance_variable_get('@path')).to eq(
38
+ 'someUri/Conferences'
39
+ )
32
40
  end
33
41
 
34
42
  it 'sets up a queues resources object' do
35
- @account.should respond_to(:queues)
36
- @account.queues.instance_variable_get('@path').should == 'someUri/Queues'
43
+ expect(@account).to respond_to(:queues)
44
+ expect(@account.queues.instance_variable_get('@path')).to eq(
45
+ 'someUri/Queues'
46
+ )
37
47
  end
38
48
 
39
49
  it 'sets up a sms resource object' do
40
- @account.should respond_to(:sms)
41
- @account.sms.instance_variable_get('@path').should == 'someUri/SMS'
50
+ expect(@account).to respond_to(:sms)
51
+ expect(@account.sms.instance_variable_get('@path')).to eq('someUri/SMS')
42
52
  end
43
53
 
44
54
  it 'sets up a recordings resources object' do
45
- @account.should respond_to(:recordings)
46
- @account.recordings.instance_variable_get('@path').should == 'someUri/Recordings'
55
+ expect(@account).to respond_to(:recordings)
56
+ expect(@account.recordings.instance_variable_get('@path')).to eq(
57
+ 'someUri/Recordings'
58
+ )
47
59
  end
48
60
 
49
61
  it 'sets up a transcriptions resources object' do
50
- @account.should respond_to(:transcriptions)
51
- @account.transcriptions.instance_variable_get('@path').should == 'someUri/Transcriptions'
62
+ expect(@account).to respond_to(:transcriptions)
63
+ expect(@account.transcriptions.instance_variable_get('@path')).to eq(
64
+ 'someUri/Transcriptions'
65
+ )
52
66
  end
53
67
 
54
68
  it 'sets up a notifications resources object' do
55
- @account.should respond_to(:notifications)
56
- @account.notifications.instance_variable_get('@path').should == 'someUri/Notifications'
69
+ expect(@account).to respond_to(:notifications)
70
+ expect(@account.notifications.instance_variable_get('@path')).to eq(
71
+ 'someUri/Notifications'
72
+ )
57
73
  end
74
+
75
+ it 'sets up a tokens resources object' do
76
+ expect(@account).to respond_to(:tokens)
77
+ expect(@account.tokens.instance_variable_get('@path')).to eq(
78
+ 'someUri/Tokens'
79
+ )
80
+ end
81
+
82
+ it 'sets up an addresses resources object' do
83
+ expect(@account).to respond_to(:addresses)
84
+ expect(@account.addresses.instance_variable_get('@path')).to eq(
85
+ 'someUri/Addresses'
86
+ )
87
+ end
88
+
58
89
  end
@@ -0,0 +1,11 @@
1
+ require 'spec_helper'
2
+
3
+ describe Twilio::REST::Address do
4
+ it 'should set up a dependent phone numbers resources object' do
5
+ address = Twilio::REST::Address.new('someUri', 'someClient')
6
+ expect(address).to respond_to(:dependent_phone_numbers)
7
+ expect(address.dependent_phone_numbers.instance_variable_get('@path')).to eq(
8
+ 'someUri/DependentPhoneNumbers'
9
+ )
10
+ end
11
+ end
@@ -0,0 +1,12 @@
1
+ require 'spec_helper'
2
+
3
+ describe Twilio::REST::Feedback do
4
+ before do
5
+ @call = Twilio::REST::Call.new('someUri', 'someClient')
6
+ end
7
+
8
+ it 'sets up a feedback resources object' do
9
+ expect(@call).to respond_to(:feedback)
10
+ expect(@call.feedback.instance_variable_get('@path')).to eq('someUri/Feedback')
11
+ end
12
+ end
@@ -0,0 +1,9 @@
1
+ require 'spec_helper'
2
+
3
+ describe Twilio::REST::FeedbackSummary do
4
+ it 'creates a feedback summary object' do
5
+ calls = Twilio::REST::Calls.new('someUri', 'someClient')
6
+ expect(calls).to respond_to(:feedback_summary)
7
+ expect(calls.feedback_summary.instance_variable_get('@path')).to eq('someUri/FeedbackSummary')
8
+ end
9
+ end
@@ -7,12 +7,16 @@ describe Twilio::REST::Call do
7
7
  end
8
8
 
9
9
  it 'sets up a recordings resources object' do
10
- @call.should respond_to(:recordings)
11
- @call.recordings.instance_variable_get('@path').should == 'someUri/Recordings'
10
+ expect(@call).to respond_to(:recordings)
11
+ expect(@call.recordings.instance_variable_get('@path')).to eq(
12
+ 'someUri/Recordings'
13
+ )
12
14
  end
13
15
 
14
16
  it 'sets up a notifications resources object' do
15
- @call.should respond_to(:notifications)
16
- @call.notifications.instance_variable_get('@path').should == 'someUri/Notifications'
17
+ expect(@call).to respond_to(:notifications)
18
+ expect(@call.notifications.instance_variable_get('@path')).to eq(
19
+ 'someUri/Notifications'
20
+ )
17
21
  end
18
22
  end