restcomm-ruby 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
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