restcomm-ruby 1.2.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 (149) hide show
  1. data/AUTHORS.md +38 -0
  2. data/CHANGES.md +171 -0
  3. data/Gemfile +11 -0
  4. data/LICENSE +662 -0
  5. data/LICENSE.md +19 -0
  6. data/Makefile +12 -0
  7. data/README.md +155 -0
  8. data/Rakefile +10 -0
  9. data/conf/cacert.pem +3376 -0
  10. data/docs/Makefile +130 -0
  11. data/docs/_themes/LICENSE +45 -0
  12. data/docs/_themes/README.rst +25 -0
  13. data/docs/_themes/flask_theme_support.py +86 -0
  14. data/docs/_themes/kr/layout.html +32 -0
  15. data/docs/_themes/kr/relations.html +19 -0
  16. data/docs/_themes/kr/static/flasky.css_t +469 -0
  17. data/docs/_themes/kr/static/small_flask.css +70 -0
  18. data/docs/_themes/kr/theme.conf +7 -0
  19. data/docs/_themes/kr_small/layout.html +22 -0
  20. data/docs/_themes/kr_small/static/flasky.css_t +287 -0
  21. data/docs/_themes/kr_small/theme.conf +10 -0
  22. data/docs/changelog.rst +1 -0
  23. data/docs/conf.py +266 -0
  24. data/docs/faq.rst +42 -0
  25. data/docs/getting-started.rst +100 -0
  26. data/docs/index.rst +109 -0
  27. data/docs/make.bat +170 -0
  28. data/docs/src/pip-delete-this-directory.txt +5 -0
  29. data/docs/usage/accounts.rst +96 -0
  30. data/docs/usage/addresses.rst +102 -0
  31. data/docs/usage/applications.rst +111 -0
  32. data/docs/usage/basics.rst +120 -0
  33. data/docs/usage/caller-ids.rst +47 -0
  34. data/docs/usage/conferences.rst +112 -0
  35. data/docs/usage/errors.rst +31 -0
  36. data/docs/usage/messages.rst +142 -0
  37. data/docs/usage/notifications.rst +72 -0
  38. data/docs/usage/phone-calls.rst +193 -0
  39. data/docs/usage/phone-numbers.rst +192 -0
  40. data/docs/usage/queues.rst +117 -0
  41. data/docs/usage/recordings.rst +102 -0
  42. data/docs/usage/sip.rst +108 -0
  43. data/docs/usage/token-generation.rst +96 -0
  44. data/docs/usage/transcriptions.rst +34 -0
  45. data/docs/usage/twiml.rst +69 -0
  46. data/docs/usage/validation.rst +107 -0
  47. data/examples/examples.rb +200 -0
  48. data/examples/print-call-log.rb +25 -0
  49. data/lib/rack/restcomm_webhook_authentication.rb +47 -0
  50. data/lib/restcomm-ruby.rb +103 -0
  51. data/lib/restcomm-ruby/rest/accounts.rb +17 -0
  52. data/lib/restcomm-ruby/rest/addresses.rb +12 -0
  53. data/lib/restcomm-ruby/rest/addresses/dependent_phone_numbers.rb +6 -0
  54. data/lib/restcomm-ruby/rest/applications.rb +6 -0
  55. data/lib/restcomm-ruby/rest/authorized_connect_apps.rb +6 -0
  56. data/lib/restcomm-ruby/rest/available_phone_numbers.rb +13 -0
  57. data/lib/restcomm-ruby/rest/available_phone_numbers/country.rb +10 -0
  58. data/lib/restcomm-ruby/rest/available_phone_numbers/local.rb +11 -0
  59. data/lib/restcomm-ruby/rest/available_phone_numbers/mobile.rb +11 -0
  60. data/lib/restcomm-ruby/rest/available_phone_numbers/toll_free.rb +11 -0
  61. data/lib/restcomm-ruby/rest/call_feedback.rb +28 -0
  62. data/lib/restcomm-ruby/rest/call_feedback_summary.rb +13 -0
  63. data/lib/restcomm-ruby/rest/calls.rb +37 -0
  64. data/lib/restcomm-ruby/rest/client.rb +555 -0
  65. data/lib/restcomm-ruby/rest/conferences.rb +12 -0
  66. data/lib/restcomm-ruby/rest/conferences/participants.rb +23 -0
  67. data/lib/restcomm-ruby/rest/connect_apps.rb +6 -0
  68. data/lib/restcomm-ruby/rest/errors.rb +14 -0
  69. data/lib/restcomm-ruby/rest/incoming_phone_numbers.rb +17 -0
  70. data/lib/restcomm-ruby/rest/incoming_phone_numbers/local.rb +13 -0
  71. data/lib/restcomm-ruby/rest/incoming_phone_numbers/mobile.rb +13 -0
  72. data/lib/restcomm-ruby/rest/incoming_phone_numbers/toll_free.rb +13 -0
  73. data/lib/restcomm-ruby/rest/instance_resource.rb +88 -0
  74. data/lib/restcomm-ruby/rest/list_resource.rb +132 -0
  75. data/lib/restcomm-ruby/rest/media.rb +14 -0
  76. data/lib/restcomm-ruby/rest/messages.rb +23 -0
  77. data/lib/restcomm-ruby/rest/next_gen_list_resource.rb +29 -0
  78. data/lib/restcomm-ruby/rest/notifications.rb +6 -0
  79. data/lib/restcomm-ruby/rest/outgoing_caller_ids.rb +25 -0
  80. data/lib/restcomm-ruby/rest/queues.rb +12 -0
  81. data/lib/restcomm-ruby/rest/queues/members.rb +29 -0
  82. data/lib/restcomm-ruby/rest/recordings.rb +35 -0
  83. data/lib/restcomm-ruby/rest/sandbox.rb +5 -0
  84. data/lib/restcomm-ruby/rest/sip.rb +10 -0
  85. data/lib/restcomm-ruby/rest/sip/credential_lists.rb +11 -0
  86. data/lib/restcomm-ruby/rest/sip/credential_lists/credentials.rb +6 -0
  87. data/lib/restcomm-ruby/rest/sip/domains.rb +12 -0
  88. data/lib/restcomm-ruby/rest/sip/domains/credential_list_mappings.rb +6 -0
  89. data/lib/restcomm-ruby/rest/sip/domains/ip_access_control_list_mappings.rb +6 -0
  90. data/lib/restcomm-ruby/rest/sip/ip_access_control_lists.rb +11 -0
  91. data/lib/restcomm-ruby/rest/sip/ip_access_control_lists/ip_addresses.rb +6 -0
  92. data/lib/restcomm-ruby/rest/sms.rb +11 -0
  93. data/lib/restcomm-ruby/rest/sms/messages.rb +39 -0
  94. data/lib/restcomm-ruby/rest/sms/short_codes.rb +8 -0
  95. data/lib/restcomm-ruby/rest/task_router/activities.rb +8 -0
  96. data/lib/restcomm-ruby/rest/task_router/events.rb +8 -0
  97. data/lib/restcomm-ruby/rest/task_router/reservations.rb +8 -0
  98. data/lib/restcomm-ruby/rest/task_router/task_queues.rb +8 -0
  99. data/lib/restcomm-ruby/rest/task_router/task_queues_statistics.rb +15 -0
  100. data/lib/restcomm-ruby/rest/task_router/tasks.rb +15 -0
  101. data/lib/restcomm-ruby/rest/task_router/workers.rb +8 -0
  102. data/lib/restcomm-ruby/rest/task_router/workers_statistics.rb +8 -0
  103. data/lib/restcomm-ruby/rest/task_router/workflow_statistics.rb +7 -0
  104. data/lib/restcomm-ruby/rest/task_router/workflows.rb +8 -0
  105. data/lib/restcomm-ruby/rest/task_router/workspace_statistics.rb +7 -0
  106. data/lib/restcomm-ruby/rest/task_router/workspaces.rb +15 -0
  107. data/lib/restcomm-ruby/rest/tokens.rb +7 -0
  108. data/lib/restcomm-ruby/rest/transcriptions.rb +6 -0
  109. data/lib/restcomm-ruby/rest/usage.rb +10 -0
  110. data/lib/restcomm-ruby/rest/usage/records.rb +21 -0
  111. data/lib/restcomm-ruby/rest/usage/triggers.rb +12 -0
  112. data/lib/restcomm-ruby/rest/utils.rb +49 -0
  113. data/lib/restcomm-ruby/task_router.rb +0 -0
  114. data/lib/restcomm-ruby/task_router/capability.rb +87 -0
  115. data/lib/restcomm-ruby/twiml/response.rb +16 -0
  116. data/lib/restcomm-ruby/util.rb +15 -0
  117. data/lib/restcomm-ruby/util/capability.rb +64 -0
  118. data/lib/restcomm-ruby/util/configuration.rb +7 -0
  119. data/lib/restcomm-ruby/util/request_validator.rb +37 -0
  120. data/lib/restcomm-ruby/version.rb +3 -0
  121. data/restcomm-ruby.gemspec +34 -0
  122. data/spec/rack/twilio_webhook_authentication_spec.rb +110 -0
  123. data/spec/rest/account_spec.rb +89 -0
  124. data/spec/rest/address_spec.rb +11 -0
  125. data/spec/rest/call_feedback_spec.rb +12 -0
  126. data/spec/rest/call_feedback_summary_spec.rb +9 -0
  127. data/spec/rest/call_spec.rb +22 -0
  128. data/spec/rest/client_spec.rb +258 -0
  129. data/spec/rest/conference_spec.rb +11 -0
  130. data/spec/rest/instance_resource_spec.rb +15 -0
  131. data/spec/rest/message_spec.rb +12 -0
  132. data/spec/rest/numbers_spec.rb +58 -0
  133. data/spec/rest/queue_spec.rb +11 -0
  134. data/spec/rest/recording_spec.rb +11 -0
  135. data/spec/rest/sms/message_spec.rb +37 -0
  136. data/spec/rest/sms/messages_spec.rb +36 -0
  137. data/spec/rest/task_router/reservation_spec.rb +9 -0
  138. data/spec/rest/task_router/task_queue_spec.rb +9 -0
  139. data/spec/rest/token_spec.rb +7 -0
  140. data/spec/rest/utils_spec.rb +45 -0
  141. data/spec/spec_helper.rb +15 -0
  142. data/spec/support/fakeweb.rb +2 -0
  143. data/spec/task_router_spec.rb +114 -0
  144. data/spec/twilio_spec.rb +15 -0
  145. data/spec/util/capability_spec.rb +186 -0
  146. data/spec/util/configuration_spec.rb +13 -0
  147. data/spec/util/request_validator_spec.rb +93 -0
  148. data/spec/util/url_encode_spec.rb +12 -0
  149. metadata +298 -0
@@ -0,0 +1,103 @@
1
+ require 'net/http'
2
+ require 'net/https'
3
+ require 'builder'
4
+ require 'json'
5
+ require 'rubygems'
6
+ require 'multi_json'
7
+ require 'cgi'
8
+ require 'openssl'
9
+ require 'base64'
10
+ require 'forwardable'
11
+ require 'jwt'
12
+
13
+ require 'restcomm-ruby/version' unless defined?(Restcomm::VERSION)
14
+ require 'restcomm-ruby/util'
15
+ require 'restcomm-ruby/util/configuration'
16
+ require 'restcomm-ruby/util/request_validator'
17
+ require 'restcomm-ruby/util/capability'
18
+ require 'restcomm-ruby/twiml/response'
19
+ require 'restcomm-ruby/task_router'
20
+ require 'restcomm-ruby/task_router/capability'
21
+ require 'restcomm-ruby/rest/errors'
22
+ require 'restcomm-ruby/rest/utils'
23
+ require 'restcomm-ruby/rest/list_resource'
24
+ require 'restcomm-ruby/rest/next_gen_list_resource'
25
+ require 'restcomm-ruby/rest/instance_resource'
26
+ require 'restcomm-ruby/rest/sandbox'
27
+ require 'restcomm-ruby/rest/accounts'
28
+ require 'restcomm-ruby/rest/calls'
29
+ require 'restcomm-ruby/rest/call_feedback'
30
+ require 'restcomm-ruby/rest/call_feedback_summary'
31
+ require 'restcomm-ruby/rest/sms'
32
+ require 'restcomm-ruby/rest/sms/short_codes'
33
+ require 'restcomm-ruby/rest/sms/messages'
34
+ require 'restcomm-ruby/rest/sip'
35
+ require 'restcomm-ruby/rest/sip/domains'
36
+ require 'restcomm-ruby/rest/sip/domains/ip_access_control_list_mappings'
37
+ require 'restcomm-ruby/rest/sip/domains/credential_list_mappings'
38
+ require 'restcomm-ruby/rest/sip/credential_lists'
39
+ require 'restcomm-ruby/rest/sip/credential_lists/credentials'
40
+ require 'restcomm-ruby/rest/sip/ip_access_control_lists'
41
+ require 'restcomm-ruby/rest/sip/ip_access_control_lists/ip_addresses'
42
+ require 'restcomm-ruby/rest/task_router/activities'
43
+ require 'restcomm-ruby/rest/task_router/events'
44
+ require 'restcomm-ruby/rest/task_router/reservations'
45
+ require 'restcomm-ruby/rest/task_router/task_queues'
46
+ require 'restcomm-ruby/rest/task_router/task_queues_statistics'
47
+ require 'restcomm-ruby/rest/task_router/tasks'
48
+ require 'restcomm-ruby/rest/task_router/workers'
49
+ require 'restcomm-ruby/rest/task_router/workers_statistics'
50
+ require 'restcomm-ruby/rest/task_router/workflow_statistics'
51
+ require 'restcomm-ruby/rest/task_router/workflows'
52
+ require 'restcomm-ruby/rest/task_router/workspaces'
53
+ require 'restcomm-ruby/rest/task_router/workspace_statistics'
54
+ require 'restcomm-ruby/rest/media'
55
+ require 'restcomm-ruby/rest/messages'
56
+ require 'restcomm-ruby/rest/applications'
57
+ require 'restcomm-ruby/rest/connect_apps'
58
+ require 'restcomm-ruby/rest/authorized_connect_apps'
59
+ require 'restcomm-ruby/rest/outgoing_caller_ids'
60
+ require 'restcomm-ruby/rest/incoming_phone_numbers'
61
+ require 'restcomm-ruby/rest/incoming_phone_numbers/local'
62
+ require 'restcomm-ruby/rest/incoming_phone_numbers/toll_free'
63
+ require 'restcomm-ruby/rest/incoming_phone_numbers/mobile'
64
+ require 'restcomm-ruby/rest/available_phone_numbers'
65
+ require 'restcomm-ruby/rest/available_phone_numbers/country'
66
+ require 'restcomm-ruby/rest/available_phone_numbers/local'
67
+ require 'restcomm-ruby/rest/available_phone_numbers/mobile'
68
+ require 'restcomm-ruby/rest/available_phone_numbers/toll_free'
69
+ require 'restcomm-ruby/rest/conferences'
70
+ require 'restcomm-ruby/rest/conferences/participants'
71
+ require 'restcomm-ruby/rest/queues'
72
+ require 'restcomm-ruby/rest/queues/members'
73
+ require 'restcomm-ruby/rest/usage'
74
+ require 'restcomm-ruby/rest/usage/records'
75
+ require 'restcomm-ruby/rest/usage/triggers'
76
+ require 'restcomm-ruby/rest/recordings'
77
+ require 'restcomm-ruby/rest/transcriptions'
78
+ require 'restcomm-ruby/rest/tokens'
79
+ require 'restcomm-ruby/rest/notifications'
80
+ require 'restcomm-ruby/rest/addresses'
81
+ require 'restcomm-ruby/rest/addresses/dependent_phone_numbers'
82
+ require 'restcomm-ruby/rest/client'
83
+ require 'rack/restcomm_webhook_authentication'
84
+
85
+ module Restcomm
86
+ extend SingleForwardable
87
+
88
+ def_delegators :configuration, :account_sid, :auth_token
89
+
90
+ ##
91
+ # Pre-configure with account SID and auth token so that you don't need to
92
+ # pass them to various initializers each time.
93
+ def self.configure(&block)
94
+ yield configuration
95
+ end
96
+
97
+ ##
98
+ # Returns an existing or instantiates a new configuration object.
99
+ def self.configuration
100
+ @configuration ||= Util::Configuration.new
101
+ end
102
+ private_class_method :configuration
103
+ end
@@ -0,0 +1,17 @@
1
+ module Restcomm
2
+ module REST
3
+ class Accounts < ListResource; end
4
+
5
+ class Account < InstanceResource
6
+ def initialize(path, client, params={})
7
+ super path, client, params
8
+
9
+ resource :sandbox, :available_phone_numbers, :incoming_phone_numbers,
10
+ :calls, :outgoing_caller_ids, :conferences, :sms, :recordings,
11
+ :transcriptions, :notifications, :applications, :connect_apps,
12
+ :authorized_connect_apps, :queues, :usage, :messages, :media, :sip,
13
+ :tokens, :addresses
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,12 @@
1
+ module Restcomm
2
+ module REST
3
+ class Addresses < ListResource; end
4
+
5
+ class Address < InstanceResource
6
+ def initialize(path, client, params={})
7
+ super path, client, params
8
+ resource :dependent_phone_numbers
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,6 @@
1
+ module Restcomm
2
+ module REST
3
+ class DependentPhoneNumbers < ListResource; end
4
+ class DependentPhoneNumber < InstanceResource; end
5
+ end
6
+ end
@@ -0,0 +1,6 @@
1
+ module Restcomm
2
+ module REST
3
+ class Applications < ListResource; end
4
+ class Application < InstanceResource; end
5
+ end
6
+ end
@@ -0,0 +1,6 @@
1
+ module Restcomm
2
+ module REST
3
+ class AuthorizedConnectApps < ListResource; end
4
+ class AuthorizedConnectApp < InstanceResource; end
5
+ end
6
+ end
@@ -0,0 +1,13 @@
1
+ module Restcomm
2
+ module REST
3
+ class AvailablePhoneNumbers < ListResource
4
+ def initialize(path, client)
5
+ @path, @client = path, client
6
+ @instance_class = Restcomm::REST::Country
7
+ @list_key, @instance_id_key = 'countries', 'country_code'
8
+ end
9
+ end
10
+
11
+ class AvailablePhoneNumber < InstanceResource; end
12
+ end
13
+ end
@@ -0,0 +1,10 @@
1
+ module Restcomm
2
+ module REST
3
+ class Country < InstanceResource
4
+ def initialize(path, client, params={})
5
+ super path, client, params
6
+ resource :local, :toll_free, :mobile
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,11 @@
1
+ module Restcomm
2
+ module REST
3
+ class Local < ListResource
4
+ def initialize(path, client)
5
+ @path, @client = path, client
6
+ @instance_class = Restcomm::REST::AvailablePhoneNumber
7
+ @list_key, @instance_id_key = 'available_phone_numbers', 'sid'
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ module Restcomm
2
+ module REST
3
+ class Mobile < ListResource
4
+ def initialize(path, client)
5
+ @path, @client = path, client
6
+ @instance_class = Restcomm::REST::AvailablePhoneNumber
7
+ @list_key, @instance_id_key = 'available_phone_numbers', 'sid'
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ module Restcomm
2
+ module REST
3
+ class TollFree < ListResource
4
+ def initialize(path, client)
5
+ @path, @client = path, client
6
+ @instance_class = Restcomm::REST::AvailablePhoneNumber
7
+ @list_key, @instance_id_key = 'available_phone_numbers', 'sid'
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,28 @@
1
+ module Restcomm
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 Restcomm
2
+ module REST
3
+ class FeedbackSummary < ListResource
4
+ def initialize(path, client)
5
+ @path, @client = path, client
6
+ @instance_class = Restcomm::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
@@ -0,0 +1,37 @@
1
+ module Restcomm
2
+ module REST
3
+ class Calls < ListResource
4
+ def initialize(path, client)
5
+ super
6
+ resource :feedback_summary
7
+ end
8
+
9
+ def make(from, to, url)
10
+ create from: from, to: to, url: url
11
+ end
12
+ end
13
+
14
+ class Call < InstanceResource
15
+ def initialize(path, client, params={})
16
+
17
+ super path, client, params
18
+ resource :recordings, :notifications, :feedback
19
+ end
20
+
21
+ def redirect_to(url)
22
+ update url: url
23
+ end
24
+
25
+ def cancel
26
+
27
+ raise "*********#{params}"
28
+
29
+ update status: 'canceled'
30
+ end
31
+
32
+ def hangup
33
+ update status: 'completed'
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,555 @@
1
+ module Restcomm
2
+ module REST
3
+ class BaseClient
4
+ include Restcomm::Util
5
+ include Restcomm::REST::Utils
6
+ require 'active_support/all'
7
+
8
+
9
+ HTTP_HEADERS = {
10
+ 'Accept' => 'application/json',
11
+ 'Accept-Charset' => 'utf-8',
12
+ 'User-Agent' => "restcomm-ruby/#{Restcomm::VERSION}" \
13
+ " (#{RUBY_ENGINE}/#{RUBY_PLATFORM}" \
14
+ " #{RUBY_VERSION}-p#{RUBY_PATCHLEVEL})"
15
+ }
16
+
17
+
18
+
19
+ attr_reader :account_sid, :last_request, :last_response
20
+
21
+
22
+
23
+
24
+
25
+ def initialize(*args)
26
+ options = args.last.is_a?(Hash) ? args.pop : {host: args[2]}
27
+ @config = get_defaults.merge! options
28
+
29
+ @account_sid = args[0] || Restcomm.account_sid
30
+ @auth_token = args[1] || Restcomm.auth_token
31
+ @host=args[2]
32
+
33
+
34
+ if @account_sid.nil? || @auth_token.nil?
35
+ raise ArgumentError, 'Account SID and auth token are required'
36
+ end
37
+
38
+ if @host.nil?
39
+ raise ArgumentError, 'Destination Host IP cannot is required!'
40
+ end
41
+
42
+ set_up_connection
43
+ set_up_subresources
44
+
45
+ end
46
+
47
+
48
+ DEFAULTS = {
49
+ host: '',
50
+ port: 8080,
51
+ use_ssl: false,
52
+ ssl_verify_peer: false,
53
+ ssl_ca_file: File.dirname(__FILE__) + '/../../../conf/cacert.pem',
54
+ timeout: 30,
55
+ proxy_addr: nil,
56
+ proxy_port: nil,
57
+ proxy_user: nil,
58
+ proxy_pass: nil,
59
+ retry_limit: 1
60
+ }
61
+
62
+
63
+ protected
64
+
65
+ ##
66
+ # Get the default config values.
67
+
68
+ def get_defaults
69
+ # To be overridden
70
+ DEFAULTS
71
+ end
72
+
73
+ ##
74
+ # Set up and cache a Net::HTTP object to use when making requests. This is
75
+ # a private method documented for completeness.
76
+ def set_up_connection # :doc:
77
+ connection_class = Net::HTTP::Proxy @config[:proxy_addr],
78
+ @config[:proxy_port], @config[:proxy_user], @config[:proxy_pass]
79
+ @connection = connection_class.new @config[:host], @config[:port]
80
+ set_up_ssl
81
+ @connection.open_timeout = @config[:timeout]
82
+ @connection.read_timeout = @config[:timeout]
83
+ end
84
+
85
+ ##
86
+ # Set up the ssl properties of the <tt>@connection</tt> Net::HTTP object.
87
+ # This is a private method documented for completeness.
88
+ def set_up_ssl # :doc:
89
+ @connection.use_ssl = @config[:use_ssl]
90
+ if @config[:ssl_verify_peer]
91
+ @connection.verify_mode = OpenSSL::SSL::VERIFY_PEER
92
+ @connection.ca_file = @config[:ssl_ca_file]
93
+ else
94
+ @connection.verify_mode = OpenSSL::SSL::VERIFY_NONE
95
+ end
96
+ end
97
+
98
+ ##
99
+ # Set up sub resources attributes.
100
+ def set_up_subresources # :doc:
101
+ # To be overridden
102
+ end
103
+
104
+ ##
105
+ # Send an HTTP request using the cached <tt>@connection</tt> object and
106
+ # return the JSON response body parsed into a hash. Also save the raw
107
+ # Net::HTTP::Request and Net::HTTP::Response objects as
108
+ # <tt>@last_request</tt> and <tt>@last_response</tt> to allow for
109
+ # inspection later.
110
+ def connect_and_send(request) # :doc:
111
+ @last_request = request
112
+ retries_left = @config[:retry_limit]
113
+ begin
114
+ response = @connection.request request
115
+ @last_response = response
116
+ if response.kind_of? Net::HTTPServerError
117
+ raise Restcomm::REST::ServerError
118
+ end
119
+ rescue Exception
120
+ raise if request.class == Net::HTTP::Post
121
+ if retries_left > 0 then retries_left -= 1; retry else raise end
122
+ end
123
+
124
+ if response.body and !response.body.empty?
125
+ object = MultiJson.load(response.body)
126
+ end
127
+
128
+ if response.kind_of? Net::HTTPClientError
129
+ raise Restcomm::REST::RequestError.new object['message'], object['code']
130
+
131
+ end
132
+ object
133
+ end
134
+ end
135
+
136
+ ##
137
+ # The Restcomm::REST::Client class caches authentication parameters and
138
+ # exposes methods to make HTTP requests to Restcomm's REST API. However, you
139
+ # should never really need to call these methods yourself since you can
140
+ # work with the more pleasant wrapper objects like Restcomm::REST::Call.
141
+ #
142
+ # Instantiate a client like so:
143
+ #
144
+ # @client = Restcomm::REST::Client.new account_sid, auth_token
145
+ #
146
+ # There are a few options you can use to configure the way your client will
147
+ # communicate with Restcomm. See #new for a list and descriptions.
148
+ #
149
+ # Once you have a client object you can use it to do fun things. Every
150
+ # client object exposes two wrapper objects which you can use as entry
151
+ # points into Restcomm: +account+ and +accounts+.
152
+ #
153
+ # ==== @client.account
154
+ #
155
+ # Most of the time you'll want to start with the +account+ attribute. This
156
+ # object is an instance of Restcomm::REST::Account that wraps the account
157
+ # referenced by the +account_sid+ you used when instantiating the client.
158
+ #
159
+ # An instance of Restcomm::REST::Account exposes objects wrapping all of the
160
+ # account-level Restcomm resources as properties. So
161
+ #
162
+ # @client.account.calls
163
+ #
164
+ # For convenience, the resources of the default account are also available
165
+ # on the client object. So the following call is equivalent to the example
166
+ # above
167
+ #
168
+ # @client.calls
169
+ #
170
+ # represents an account's call list.
171
+ #
172
+ # ==== @client.accounts
173
+ #
174
+ # If you are doing anything related to subaccounts you'll want to start
175
+ # here. This object is an instance of Restcomm::REST::Accounts that wraps
176
+ # the list of accounts belonging to the master account referenced by
177
+ # the +account_sid+ used to instantiate the client.
178
+ #
179
+ # This class inherits from Restcomm::REST::ListResource, so you can use
180
+ # methods like ListResource#list to return a (possibly filtered) list of
181
+ # accounts and ListResource#create to create a new account. Use
182
+ # ListResource#get to grab a particular account once you know its sid.
183
+ class Client < BaseClient
184
+ API_VERSION = '2012-04-24'
185
+
186
+ attr_reader :account, :accounts
187
+
188
+ ##
189
+ # Instantiate a new HTTP client to talk to Restcomm. The parameters
190
+ # +account_sid+ and +auth_token+ are required, unless you have configured
191
+ # them already using the block configure syntax, and used to generate the
192
+ # HTTP basic auth header in each request. The +options+ parameter is a
193
+ # hash of connection configuration options. the following keys are
194
+ # supported:
195
+ #
196
+ # === <tt>host: 'api.restcomm.com'</tt>
197
+ #
198
+ # The domain to which you'd like the client to make HTTP requests. Useful
199
+ # for testing. Defaults to 'api.restcomm.com'.
200
+ #
201
+ # === <tt>port: 443</tt>
202
+ #
203
+ # The port on which to connect to the above domain. Defaults to 443 and
204
+ # should be left that way except in testing environments.
205
+ #
206
+ # === <tt>use_ssl: true</tt>
207
+ #
208
+ # Declare whether ssl should be used for connections to the above domain.
209
+ # Defaults to true and should be left alone except when testing.
210
+ #
211
+ # === <tt>ssl_verify_peer: true</tt>
212
+ #
213
+ # Declare whether to verify the host's ssl cert when setting up the
214
+ # connection to the above domain. Defaults to true, but can be turned off
215
+ # to avoid ssl certificate verification failures in environments without
216
+ # the necessary ca certificates.
217
+ #
218
+ # === <tt>ssl_ca_file: '/path/to/ca/file'</tt>
219
+ #
220
+ # Specify the path to the certificate authority bundle you'd like to use
221
+ # to verify Restcomm's SSL certificate on each request. If not specified, a
222
+ # certificate bundle extraced from Firefox is packaged with the gem and
223
+ # used by default.
224
+ #
225
+ # === <tt>timeout: 30</tt>
226
+ #
227
+ # Set the time in seconds to wait before timing out the HTTP request.
228
+ # Defaults to 30 seconds. If you aren't fetching giant pages of call or
229
+ # SMS logs you can safely decrease this to something like 3 seconds or
230
+ # lower. In paricular if you are sending SMS you can set this to 1 second
231
+ # or less and swallow the exception if you don't care about the response.
232
+ #
233
+ # === <tt>proxy_addr: 'proxy.host.domain'</tt>
234
+ #
235
+ # The domain of a proxy through which you'd like the client to make HTTP
236
+ # requests. Defaults to nil.
237
+ #
238
+ # === <tt>proxy_port: 3128</tt>
239
+ #
240
+ # The port on which to connect to the above proxy. Defaults to nil.
241
+ #
242
+ # === <tt>proxy_user: 'username'</tt>
243
+ #
244
+ # The user name to use for authentication with the proxy. Defaults to nil.
245
+ #
246
+ # === <tt>proxy_pass: 'password'</tt>
247
+ #
248
+ # The password to use for authentication with the proxy. Defaults to nil.
249
+ #
250
+ # === <tt>retry_limit: 1</tt>
251
+ #
252
+ # The number of times to retry a request that has failed before throwing
253
+ # an exception. Defaults to one.
254
+ def initialize(*args)
255
+ super(*args)
256
+ end
257
+
258
+ def inspect # :nodoc:
259
+ "<Restcomm::REST::Client @account_sid=#{@account_sid}>"
260
+ end
261
+
262
+ ##
263
+ # Define #get, #put, #post and #delete helper methods for sending HTTP
264
+ # requests to Restcomm. You shouldn't need to use these methods directly,
265
+ # but they can be useful for debugging. Each method returns a hash
266
+ # obtained from parsing the JSON object in the response body.
267
+ [:get, :put, :post, :delete].each do |method|
268
+ method_class = Net::HTTP.const_get method.to_s.capitalize
269
+ define_method method do |path, *args|
270
+ params = restify args[0]; params = {} if params.empty?
271
+ unless args[1] # build the full path unless already given
272
+ path = "/restcomm#{path}.json"
273
+
274
+ if method == :get
275
+
276
+ if path.include?("/Accounts/#{@account_sid}.json" )
277
+ path.gsub!("/Accounts/#{@account_sid}.json", "/Accounts.json/#{@account_sid}")
278
+ end
279
+
280
+
281
+ if path.match(/Calls\/CA.*\/Recordings.json/ )
282
+ path.gsub!("/Recordings.json", ".json")
283
+ end
284
+
285
+ if path.include?("/Accounts/#{@account_sid}.json" )
286
+ path.gsub!("/Accounts/#{@account_sid}.json", "/Accounts.json/#{@account_sid}")
287
+ end
288
+ end
289
+
290
+
291
+ #### Make Restcomm path compatible with Twilio - convert Restcomm 2012-04-24/Accounts/ACae6e420f425248d6a26948c17a9e2acf/Calls/CA76d50db1b78d4a34bfaa708bc669d7db.json to /2012-04-24/Accounts/ACae6e420f425248d6a26948c17a9e2acf/Calls.json/CA76d50db1b78d4a34bfaa708bc669d7db
292
+
293
+ if method == :post
294
+
295
+ if path.match(/Calls\/CA.*/ )
296
+ call_sid = path.split("/").last
297
+ call_sid = call_sid.gsub!(".json", "")
298
+ path.gsub!("Calls/#{call_sid}.json", "Calls.json/#{call_sid}")
299
+
300
+
301
+ end
302
+ end
303
+
304
+ path << "?#{url_encode(params)}" if method == :get && !params.empty?
305
+ end
306
+ request = method_class.new path, HTTP_HEADERS
307
+ request.basic_auth @account_sid, @auth_token
308
+ request.form_data = params if [:post, :put].include? method
309
+ connect_and_send request
310
+ end
311
+ end
312
+
313
+ ##
314
+ # Delegate account methods from the client. This saves having to call
315
+ # <tt>client.account</tt> every time for resources on the default
316
+ # account.
317
+ def method_missing(method_name, *args, &block)
318
+ if account.respond_to?(method_name)
319
+ account.send(method_name, *args, &block)
320
+ else
321
+ super
322
+ end
323
+ end
324
+
325
+ def respond_to?(method_name, include_private=false)
326
+ if account.respond_to?(method_name, include_private)
327
+ true
328
+ else
329
+ super
330
+ end
331
+ end
332
+
333
+ protected
334
+
335
+ ##
336
+ # Set up +account+ and +accounts+ attributes.
337
+ def set_up_subresources # :doc:
338
+ @accounts = Restcomm::REST::Accounts.new "/#{API_VERSION}/Accounts", self
339
+ @account = @accounts.get @account_sid
340
+ end
341
+ end
342
+
343
+ class TaskRouterClient < BaseClient
344
+ API_VERSION = 'v1'
345
+
346
+ DEFAULTS = {
347
+ host: '192.168.1.8',
348
+ port: 80,
349
+ use_ssl: false,
350
+ ssl_verify_peer: false,
351
+ ssl_ca_file: File.dirname(__FILE__) + '/../../../conf/cacert.pem',
352
+ timeout: 30,
353
+ proxy_addr: nil,
354
+ proxy_port: nil,
355
+ proxy_user: nil,
356
+ proxy_pass: nil,
357
+ retry_limit: 1
358
+ }
359
+
360
+ attr_reader :workspace, :workspace_sid, :workspaces
361
+
362
+ ##
363
+ # Instantiate a new HTTP TaskRouter client to talk to Restcomm. The parameters
364
+ # +account_sid+, +auth_token+ and +workspace_sid are required, unless you
365
+ # have configured them already using the block configure syntax, and used
366
+ # to generate the HTTP basic auth header in each request. The +options+
367
+ # parameter is a hash of connection configuration options. the following
368
+ # keys are supported:
369
+ #
370
+ # === <tt>host: 'taskrouter.restcomm.com'</tt>
371
+ #
372
+ # The domain to which you'd like the client to make HTTP requests. Useful
373
+ # for testing. Defaults to 'api.restcomm.com'.
374
+ #
375
+ # === <tt>port: 443</tt>
376
+ #
377
+ # The port on which to connect to the above domain. Defaults to 443 and
378
+ # should be left that way except in testing environments.
379
+ #
380
+ # === <tt>use_ssl: true</tt>
381
+ #
382
+ # Declare whether ssl should be used for connections to the above domain.
383
+ # Defaults to true and should be left alone except when testing.
384
+ #
385
+ # === <tt>ssl_verify_peer: true</tt>
386
+ #
387
+ # Declare whether to verify the host's ssl cert when setting up the
388
+ # connection to the above domain. Defaults to true, but can be turned off
389
+ # to avoid ssl certificate verification failures in environments without
390
+ # the necessary ca certificates.
391
+ #
392
+ # === <tt>ssl_ca_file: '/path/to/ca/file'</tt>
393
+ #
394
+ # Specify the path to the certificate authority bundle you'd like to use
395
+ # to verify Restcomm's SSL certificate on each request. If not specified, a
396
+ # certificate bundle extraced from Firefox is packaged with the gem and
397
+ # used by default.
398
+ #
399
+ # === <tt>timeout: 30</tt>
400
+ #
401
+ # Set the time in seconds to wait before timing out the HTTP request.
402
+ # Defaults to 30 seconds. If you aren't fetching giant pages of call or
403
+ # SMS logs you can safely decrease this to something like 3 seconds or
404
+ # lower. In paricular if you are sending SMS you can set this to 1 second
405
+ # or less and swallow the exception if you don't care about the response.
406
+ #
407
+ # === <tt>proxy_addr: 'proxy.host.domain'</tt>
408
+ #
409
+ # The domain of a proxy through which you'd like the client to make HTTP
410
+ # requests. Defaults to nil.
411
+ #
412
+ # === <tt>proxy_port: 3128</tt>
413
+ #
414
+ # The port on which to connect to the above proxy. Defaults to nil.
415
+ #
416
+ # === <tt>proxy_user: 'username'</tt>
417
+ #
418
+ # The user name to use for authentication with the proxy. Defaults to nil.
419
+ #
420
+ # === <tt>proxy_pass: 'password'</tt>
421
+ #
422
+ # The password to use for authentication with the proxy. Defaults to nil.
423
+ #
424
+ # === <tt>retry_limit: 1</tt>
425
+ #
426
+ # The number of times to retry a request that has failed before throwing
427
+ # an exception. Defaults to one.
428
+ def initialize(*args)
429
+ @workspace_sid = args[2]
430
+ if @workspace_sid.nil?
431
+ raise ArgumentError, 'Workspace SID is required'
432
+ end
433
+ super(*args)
434
+ end
435
+
436
+ ##
437
+ # Define #get, #put, #post and #delete helper methods for sending HTTP
438
+ # requests to Restcomm. You shouldn't need to use these methods directly,
439
+ # but they can be useful for debugging. Each method returns a hash
440
+ # obtained from parsing the JSON object in the response body.
441
+ [:get, :put, :post, :delete].each do |method|
442
+ method_class = Net::HTTP.const_get method.to_s.capitalize
443
+ define_method method do |path, *args|
444
+ params = restify args[0]; params = {} if params.empty?
445
+ unless args[1] # build the full path unless already given
446
+ path = path.dup
447
+ path << "?#{url_encode(params)}" if method == :get && !params.empty?
448
+
449
+ end
450
+ request = method_class.new path, HTTP_HEADERS
451
+ request.basic_auth @account_sid, @auth_token
452
+ request.form_data = params if [:post, :put].include? method
453
+ connect_and_send request
454
+ end
455
+ end
456
+
457
+ def inspect # :nodoc:
458
+ "<Restcomm::REST::TaskRouterClient @account_sid=#{@account_sid}>"
459
+ end
460
+
461
+ ##
462
+ # Delegate workspace methods from the client. This saves having to call
463
+ # <tt>client.workspace</tt> every time for resources on the default
464
+ # workspace.
465
+ def method_missing(method_name, *args, &block)
466
+ if workspace.respond_to?(method_name)
467
+ workspace.send(method_name, *args, &block)
468
+ else
469
+ super
470
+ end
471
+ end
472
+
473
+ def respond_to?(method_name, include_private=false)
474
+ if workspace.respond_to?(method_name, include_private)
475
+ true
476
+ else
477
+ super
478
+ end
479
+ end
480
+
481
+ ##
482
+ # Get statistics of a task queue.
483
+ def task_queue_statistics(task_queue_sid, *args) # :doc:
484
+ if task_queue_sid.nil?
485
+ raise ArgumentError, 'Task queue SID is required'
486
+ end
487
+ path = "/#{API_VERSION}/Workspaces/#{@workspace_sid}/TaskQueues/#{task_queue_sid}/Statistics"
488
+ response = get path, args, true
489
+ Restcomm::REST::TaskRouter::TaskQueueStatistics.new path, self, response
490
+ end
491
+
492
+ ##
493
+ # Get statistics of task queues.
494
+ def task_queues_statistics(*args) # :doc:
495
+ path = "/#{API_VERSION}/Workspaces/#{@workspace_sid}/TaskQueues/Statistics"
496
+ stats = Restcomm::REST::TaskRouter::TaskQueuesStatistics.new path, self
497
+ stats.list args, true
498
+ end
499
+
500
+ ##
501
+ # Get statistics of a worker.
502
+ def worker_statistics(worker_sid, *args) # :doc:
503
+ if worker_sid.nil?
504
+ raise ArgumentError, 'Worker SID is required'
505
+ end
506
+ path = "/#{API_VERSION}/Workspaces/#{@workspace_sid}/Workers/#{worker_sid}/Statistics"
507
+ response = get path, args, true
508
+ Restcomm::REST::TaskRouter::WorkerStatistics.new path, self, response
509
+ end
510
+
511
+ ##
512
+ # Get statistics of workers.
513
+ def workers_statistics(*args) # :doc:
514
+ path = "/#{API_VERSION}/Workspaces/#{@workspace_sid}/Workers/Statistics"
515
+ response = get path, args, true
516
+ Restcomm::REST::TaskRouter::WorkersStatistics.new path, self, response
517
+ end
518
+
519
+ ##
520
+ # Get statistics of a workflow.
521
+ def workflow_statistics(workflow_sid, *args) # :doc:
522
+ if workflow_sid.nil?
523
+ raise ArgumentError, 'Workflow SID is required'
524
+ end
525
+ path = "/#{API_VERSION}/Workspaces/#{@workspace_sid}/Workflows/#{workflow_sid}/Statistics"
526
+ response = get path, args, true
527
+ Restcomm::REST::TaskRouter::WorkflowStatistics.new path, self, response
528
+ end
529
+
530
+ ##
531
+ # Get statistics of a workspace.
532
+ def workspace_statistics(*args) # :doc:
533
+ path = "/#{API_VERSION}/Workspaces/#{@workspace_sid}/Statistics"
534
+ response = get path, args, true
535
+ Restcomm::REST::TaskRouter::WorkspaceStatistics.new path, self, response
536
+ end
537
+
538
+ protected
539
+
540
+ ##
541
+ # Get the default config values.
542
+ def get_defaults
543
+ DEFAULTS
544
+ end
545
+
546
+ ##
547
+ # Set up +workspace+ and +workspaces+ attributes.
548
+ def set_up_subresources # :doc:
549
+ @workspaces = Restcomm::REST::TaskRouter::Workspaces.new "/#{API_VERSION}/Workspaces", self
550
+ @workspace = @workspaces.get @workspace_sid
551
+ end
552
+
553
+ end
554
+ end
555
+ end