ringcentral_sdk 1.3.4 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (36) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +12 -0
  3. data/Gemfile.lock +70 -33
  4. data/{LICENSE.txt → LICENSE.md} +0 -0
  5. data/README.md +40 -76
  6. data/lib/ringcentral_sdk.rb +4 -3
  7. data/lib/ringcentral_sdk/rest.rb +18 -17
  8. data/lib/ringcentral_sdk/rest/cache.rb +9 -3
  9. data/lib/ringcentral_sdk/rest/cache/extensions.rb +91 -94
  10. data/lib/ringcentral_sdk/rest/client.rb +196 -202
  11. data/lib/ringcentral_sdk/rest/configuration.rb +91 -0
  12. data/lib/ringcentral_sdk/rest/event.rb +44 -43
  13. data/lib/ringcentral_sdk/rest/extension.rb +12 -9
  14. data/lib/ringcentral_sdk/rest/extension_presence.rb +73 -78
  15. data/lib/ringcentral_sdk/rest/messages.rb +40 -31
  16. data/lib/ringcentral_sdk/rest/messages_retriever.rb +30 -33
  17. data/lib/ringcentral_sdk/rest/request.rb +10 -5
  18. data/lib/ringcentral_sdk/rest/request/base.rb +24 -19
  19. data/lib/ringcentral_sdk/rest/request/fax.rb +88 -91
  20. data/lib/ringcentral_sdk/rest/request/inflator.rb +9 -2
  21. data/lib/ringcentral_sdk/rest/request/inflator/contact_info.rb +19 -12
  22. data/lib/ringcentral_sdk/rest/request/simple.rb +24 -34
  23. data/lib/ringcentral_sdk/rest/simple_client.rb +63 -78
  24. data/lib/ringcentral_sdk/rest/subscription.rb +223 -228
  25. data/test/test_base.rb +5 -5
  26. data/test/test_client.rb +87 -88
  27. data/test/test_event.rb +28 -11
  28. data/test/test_extension_presence.rb +64 -62
  29. data/test/test_helper_fax.rb +46 -47
  30. data/test/test_helper_inflator_contact_info.rb +8 -10
  31. data/test/test_helper_request.rb +1 -1
  32. data/test/test_setup.rb +24 -21
  33. data/test/test_subscription.rb +46 -48
  34. metadata +72 -33
  35. data/lib/ringcentral_sdk/rest/config.rb +0 -102
  36. data/test/test_config.rb +0 -29
@@ -1,102 +1,87 @@
1
- module RingCentralSdk::REST
1
+ module RingCentralSdk
2
+ module REST
3
+ # A simplified, but still generic, REST interface.
4
+ #
5
+ # NOTE: This is an experimental module.
6
+ #
7
+ # client = RingCentralSdk::REST::Client.new ...
8
+ # simple = RingCentralSdk::REST::SimpleClient client
9
+ #
10
+ # simple.post(
11
+ # path: 'sms',
12
+ # body: {
13
+ # from: {phoneNumber: '+16505551212'},
14
+ # to: [{phoneNumber: '+14155551212'}],
15
+ # text: 'Hi There!'
16
+ # }
17
+ # )
18
+ class SimpleClient
19
+ attr_accessor :client
2
20
 
3
- # A simplified, but still generic, REST interface.
4
- #
5
- # NOTE: This is an experimental module.
6
- #
7
- # client = RingCentralSdk::REST::Client.new ...
8
- # simple = RingCentralSdk::REST::SimpleClient client
9
- #
10
- # simple.post(
11
- # path: 'sms',
12
- # body: {
13
- # from: {phoneNumber: '+16505551212'},
14
- # to: [{phoneNumber: '+14155551212'}],
15
- # text: 'Hi There!'
16
- # }
17
- # )
18
- class SimpleClient
19
- attr_accessor :client
20
-
21
- def initialize(client)
22
- @client = client
23
- end
24
-
25
- def send(request)
26
- if request.is_a?(RingCentralSdk::Helpers::Request)
27
- return @client.request(request)
28
- elsif ! request.is_a?(Hash)
29
- raise "Request is not a RingCentralSdk::Helpers::Request or Hash"
21
+ def initialize(client)
22
+ @client = client
30
23
  end
31
24
 
32
- verb = request.key?(:verb) ? request[:verb].to_s.downcase : 'get'
25
+ def send(request)
26
+ return @client.request(request) if request.is_a? RingCentralSdk::Helpers::Request
27
+ raise(ArgumentError, 'Request is not a ...Helpers::Request or Hash') unless request.is_a? Hash
33
28
 
34
- if verb == 'get'
35
- return get(request)
36
- elsif verb == 'post'
37
- return post(request)
38
- elsif verb == 'put'
39
- return put(request)
40
- elsif verb == 'delete'
41
- return delete(request)
42
- else
43
- raise 'Method not supported'
44
- end
45
- end
29
+ verb = request.key?(:verb) ? request[:verb].to_s.downcase : 'get'
46
30
 
47
- def delete(opts={})
48
- return @client.http.delete do |req|
49
- req.url build_url(opts[:path])
31
+ return get(request) if verb == 'get'
32
+ return post(request) if verb == 'post'
33
+ return put(request) if verb == 'put'
34
+ return delete(request) if verb == 'delete'
35
+ raise ArgumentError, "Method not supported #{verb}"
50
36
  end
51
- end
52
37
 
53
- def get(opts={})
54
- return @client.http.get do |req|
55
- req.url build_url(opts[:path])
38
+ def delete(opts = {})
39
+ @client.http.delete do |req|
40
+ req.url build_url(opts[:path])
41
+ end
56
42
  end
57
- end
58
43
 
59
- def post(opts={})
60
- return @client.http.post do |req|
61
- req = inflate_request req, opts
44
+ def get(opts = {})
45
+ @client.http.get do |req|
46
+ req.url build_url(opts[:path])
47
+ end
62
48
  end
63
- end
64
49
 
65
- def put(opts={})
66
- return @client.http.put do |req|
67
- req = inflate_request req, opts
50
+ def post(opts = {})
51
+ @client.http.post do |req|
52
+ req = inflate_request req, opts
53
+ end
68
54
  end
69
- end
70
55
 
71
- def inflate_request(req, opts={})
72
- req.url build_url(opts[:path])
73
- if opts.key? :body
74
- req.body = opts[:body]
75
- if opts[:body].is_a?(Hash)
76
- req.headers['Content-Type'] = 'application/json'
56
+ def put(opts = {})
57
+ @client.http.put do |req|
58
+ req = inflate_request req, opts
77
59
  end
78
60
  end
79
- req
80
- end
81
61
 
82
- def build_url(path)
83
- url = ''
84
- if !path.is_a?(Array)
85
- path = [path]
62
+ def inflate_request(req, opts = {})
63
+ req.url build_url(opts[:path])
64
+ if opts.key? :body
65
+ req.body = opts[:body]
66
+ if opts[:body].is_a?(Hash)
67
+ req.headers['Content-Type'] = 'application/json'
68
+ end
69
+ end
70
+ req
86
71
  end
87
- if path.length > 0
88
- path0 = path[0].to_s
89
- if path0 !~ /\//
90
- if path0.index('account') != 0
91
- if path0.index('extension') != 0
92
- path.unshift('extension/~')
93
- end
72
+
73
+ def build_url(path)
74
+ path = [path] unless path.is_a? Array
75
+
76
+ unless path.empty?
77
+ path0 = path[0].to_s
78
+ if path0.index('/').nil? && path0.index('account') != 0
79
+ path.unshift('extension/~') if path0.index('extension') != 0
94
80
  path.unshift('account/~')
95
81
  end
96
82
  end
83
+ path.join('/')
97
84
  end
98
- url = path.join('/')
99
- return url
100
85
  end
101
86
  end
102
87
  end
@@ -5,284 +5,279 @@ require 'observer'
5
5
  require 'openssl'
6
6
  require 'pubnub'
7
7
 
8
- module RingCentralSdk::REST
9
- class Subscription
10
- include Observable
11
-
12
- RENEW_HANDICAP = 60
13
-
14
- attr_reader :event_filters
15
-
16
- def initialize(client)
17
- @_client = client
18
- @event_filters = []
19
- @_timeout = nil
20
- @_subscription = nil_subscription()
21
- @_pubnub = nil
22
- @_logger_prefix = " -- #{self.class.name}: "
23
- end
8
+ module RingCentralSdk
9
+ module REST
10
+ # Subscription class is an observerable class that represents
11
+ # one RingCentral subscription using the PubNub transport via
12
+ # the Subscription API
13
+ class Subscription
14
+ include Observable
15
+
16
+ RENEW_HANDICAP = 60
17
+
18
+ attr_reader :event_filters
19
+
20
+ def initialize(client)
21
+ @_client = client
22
+ @event_filters = []
23
+ @_timeout = nil
24
+ @_subscription = nil_subscription
25
+ @_pubnub = nil
26
+ @_logger_prefix = " -- #{self.class.name}: "
27
+ end
24
28
 
25
- def nil_subscription()
26
- return {
27
- 'eventFilters' => [],
28
- 'expirationTime' => '', # 2014-03-12T19:54:35.613Z
29
- 'expiresIn' => 0,
30
- 'deliveryMode' => {
31
- 'transportType' => 'PubNub',
32
- 'encryption' => false,
33
- 'address' => '',
34
- 'subscriberKey' => '',
35
- 'secretKey' => ''
36
- },
37
- 'id' => '',
38
- 'creationTime' => '', # 2014-03-12T19:54:35.613Z
39
- 'status' => '', # Active
40
- 'uri' => ''
41
- }
42
- end
29
+ def nil_subscription
30
+ {
31
+ 'eventFilters' => [],
32
+ 'expirationTime' => '', # 2014-03-12T19:54:35.613Z
33
+ 'expiresIn' => 0,
34
+ 'deliveryMode' => {
35
+ 'transportType' => 'PubNub',
36
+ 'encryption' => false,
37
+ 'address' => '',
38
+ 'subscriberKey' => '',
39
+ 'secretKey' => ''
40
+ },
41
+ 'id' => '',
42
+ 'creationTime' => '', # 2014-03-12T19:54:35.613Z
43
+ 'status' => '', # Active
44
+ 'uri' => ''
45
+ }
46
+ end
43
47
 
44
- def pubnub()
45
- return @_pubnub
46
- end
48
+ def pubnub
49
+ @_pubnub
50
+ end
47
51
 
48
- def register(events = nil)
49
- return alive? ? renew(events) : subscribe(events)
50
- end
52
+ def register(events = nil)
53
+ alive? ? renew(events) : subscribe(events)
54
+ end
51
55
 
52
- def add_events(events)
53
- unless events.is_a? Array
54
- raise 'Events is not an array.'
56
+ def add_events(events)
57
+ raise 'Events is not an array.' unless events.is_a? Array
58
+ @event_filters.push(events) unless events.empty?
55
59
  end
56
- @event_filters.push(events) if events.length > 0
57
- end
58
60
 
59
- def set_events(events)
60
- unless events.is_a? Array
61
- raise 'Events is not an array.'
61
+ def set_events(events)
62
+ raise 'Events is not an array.' unless events.is_a? Array
63
+ @event_filters = events
62
64
  end
63
- @event_filters = events
64
- end
65
65
 
66
- def subscribe(events=nil)
67
- set_events(events) if events.is_a? Array
66
+ def subscribe(events = nil)
67
+ set_events(events) if events.is_a? Array
68
68
 
69
- if !@event_filters.is_a?(Array) || @event_filters.length == 0
70
- raise 'Events are undefined'
71
- end
69
+ raise 'Events are undefined' unless @event_filters.is_a?(Array) && !@event_filters.empty?
72
70
 
73
- begin
74
- response = @_client.http.post do |req|
75
- req.url 'subscription'
76
- req.headers['Content-Type'] = 'application/json'
77
- req.body = {
78
- eventFilters: @_client.create_urls(@event_filters),
79
- deliveryMode: {
80
- transportType: 'PubNub'
71
+ begin
72
+ response = @_client.http.post do |req|
73
+ req.url 'subscription'
74
+ req.headers['Content-Type'] = 'application/json'
75
+ req.body = {
76
+ eventFilters: @_client.create_urls(@event_filters),
77
+ deliveryMode: { transportType: 'PubNub' }
81
78
  }
82
- }
79
+ end
80
+ set_subscription response.body
81
+ _subscribe_at_pubnub
82
+ changed
83
+ notify_observers response
84
+ return response
85
+ rescue StandardError => e
86
+ reset
87
+ changed
88
+ notify_observers(e)
89
+ raise 'Subscribe HTTP Request Error: ' + e.to_s
83
90
  end
84
- set_subscription response.body
85
- _subscribe_at_pubnub()
86
- changed
87
- notify_observers response
88
- return response
89
- rescue StandardError => e
90
- reset()
91
- changed
92
- notify_observers(e)
93
- raise 'Subscribe HTTP Request Error: ' + e.to_s
94
91
  end
95
- end
96
92
 
97
- def renew(events = nil)
98
- set_events(events) if events.is_a? Array
99
-
100
- unless alive?
101
- raise 'Subscription is not alive'
93
+ def renew(events = nil)
94
+ set_events(events) if events.is_a? Array
95
+
96
+ raise 'Subscription is not alive' unless alive?
97
+ raise 'Events are undefined' if @event_filters.empty?
98
+ _clear_timeout
99
+
100
+ begin
101
+ response = @_client.http.post do |req|
102
+ req.url uri_join(@_subscription['uri'], 'renew')
103
+ req.headers['Content-Type'] = 'application/json'
104
+ end
105
+
106
+ set_subscription response.body
107
+ changed
108
+ notify_observers response
109
+
110
+ return response
111
+ rescue StandardError => e
112
+ @client.logger.warn "RingCentralSdk::REST::Subscription: RENEW_ERROR #{e}"
113
+ reset
114
+ changed
115
+ notify_observers e
116
+ raise 'Renew HTTP Request Error'
117
+ end
102
118
  end
103
119
 
104
- if !@event_filters.is_a?(Array) || @event_filters.length ==0
105
- raise 'Events are undefined'
120
+ def remove
121
+ raise 'Subscription is not alive' unless alive?
122
+
123
+ begin
124
+ response = @_client.http.delete do |req|
125
+ req.url 'subscription/' + @_subscription['id'].to_s
126
+ end
127
+ reset
128
+ changed
129
+ notify_observers response.body
130
+ return response
131
+ rescue StandardError => e
132
+ reset
133
+ changed
134
+ notify_observers e
135
+ end
106
136
  end
107
- _clear_timeout
108
137
 
109
- begin
110
- response = @_client.http.post do |req|
111
- req.url uri_join(@_subscription['uri'], 'renew')
112
- req.headers['Content-Type'] = 'application/json'
138
+ def alive?
139
+ s = @_subscription
140
+ if
141
+ (s.key?('deliveryMode') && s['deliveryMode']) \
142
+ && (s['deliveryMode'].key?('subscriberKey') && s['deliveryMode']['subscriberKey']) \
143
+ && (
144
+ s['deliveryMode'].key?('address') \
145
+ && !s['deliveryMode']['address'].nil? \
146
+ && !s['deliveryMode']['address'].empty?
147
+ )
148
+ return true
113
149
  end
114
-
115
- set_subscription response.body
116
- changed
117
- notify_observers response
118
-
119
- return response
120
- rescue StandardError => e
121
- puts "RingCentralSdk::REST::Subscription: RENEW_ERROR #{e}"
122
- reset()
123
- changed
124
- notify_observers e
125
- raise 'Renew HTTP Request Error'
150
+ false
126
151
  end
127
- end
128
152
 
129
- def remove()
130
- unless alive?
131
- raise 'Subscription is not alive'
153
+ def subscription
154
+ @_subscription
132
155
  end
133
156
 
134
- begin
135
- response = @_client.http.delete do |req|
136
- req.url 'subscription/' + @_subscription['id'].to_s
137
- end
138
- reset()
139
- changed
140
- notify_observers response.body
141
- return response
142
- rescue StandardError => e
143
- reset()
144
- changed
145
- notify_observers e
157
+ def set_subscription(data)
158
+ _clear_timeout
159
+ @_subscription = data
160
+ _set_timeout
146
161
  end
147
- end
148
162
 
149
- def alive?
150
- s = @_subscription
151
- return (s.has_key?('deliveryMode') && s['deliveryMode']) && \
152
- (s['deliveryMode'].has_key?('subscriberKey') && s['deliveryMode']['subscriberKey']) && \
153
- (
154
- s['deliveryMode'].has_key?('address') && s['deliveryMode']['address'] && \
155
- s['deliveryMode']['address'].length>0) \
156
- ? true : false
157
- end
158
-
159
- def subscription
160
- return @_subscription
161
- end
163
+ def reset
164
+ _clear_timeout
165
+ _unsubscribe_at_pubnub
166
+ @_subscription = nil_subscription
167
+ end
162
168
 
163
- def set_subscription(data)
164
- _clear_timeout
165
- @_subscription = data
166
- _set_timeout
167
- end
169
+ def destroy
170
+ reset
171
+ end
168
172
 
169
- def reset
170
- _clear_timeout()
171
- _unsubscribe_at_pubnub()
172
- @_subscription = nil_subscription()
173
- end
173
+ def _subscribe_at_pubnub
174
+ raise 'Subscription is not alive' unless alive?
175
+
176
+ s_key = @_subscription['deliveryMode']['subscriberKey']
177
+
178
+ @_pubnub = new_pubnub(s_key, false, '')
179
+
180
+ callback = Pubnub::SubscribeCallback.new(
181
+ message: ->(envelope) {
182
+ @_client.logger.debug "MESSAGE: #{envelope.result[:data]}"
183
+ _notify envelope.result[:data][:message]
184
+ changed
185
+ },
186
+ presence: ->(envelope) {
187
+ @_client.logger.info "PRESENCE: #{envelope.result[:data]}"
188
+ },
189
+ status: lambda do |envelope|
190
+ @_client.logger.info "\n\n\n#{envelope.status}\n\n\n"
191
+ if envelope.error?
192
+ @_client.logger.info "ERROR! #{envelope.status[:category]}"
193
+ elsif envelope.status[:last_timetoken] == 0 # Connected!
194
+ @_client.logger.info('CONNECTED!')
195
+ end
196
+ end
197
+ )
198
+
199
+ @_pubnub.add_listener callback: callback, name: :ringcentral
200
+
201
+ @_pubnub.subscribe(
202
+ channels: @_subscription['deliveryMode']['address']
203
+ )
204
+ @_client.logger.debug('SUBSCRIBED')
205
+ end
174
206
 
175
- def destroy
176
- reset()
177
- end
207
+ def _notify(message)
208
+ count = count_observers
209
+ @_client.logger.debug("RingCentralSdk::REST::Subscription NOTIFYING '#{count}' observers")
178
210
 
179
- def _subscribe_at_pubnub
180
- unless alive?
181
- raise 'Subscription is not alive'
211
+ message = _decrypt message
212
+ changed
213
+ notify_observers message
182
214
  end
183
215
 
184
- s_key = @_subscription['deliveryMode']['subscriberKey']
185
-
186
- @_pubnub = new_pubnub(s_key, false, '')
216
+ def _decrypt(message)
217
+ unless alive?
218
+ raise 'Subscription is not alive'
219
+ end
187
220
 
188
- callback = lambda { |envelope|
189
- _notify(envelope.msg)
190
- changed
191
- }
221
+ if _encrypted?
222
+ delivery_mode = @_subscription['deliveryMode']
192
223
 
193
- @_pubnub.subscribe(
194
- channel: @_subscription['deliveryMode']['address'],
195
- callback: callback,
196
- error: lambda { |envelope| puts('ERROR: ' + envelope.msg.to_s) },
197
- connect: lambda { |envelope| puts('CONNECTED') },
198
- reconnect: lambda { |envelope| puts('RECONNECTED') },
199
- disconnect: lambda { |envelope| puts('DISCONNECTED') }
200
- )
201
- end
224
+ cipher = OpenSSL::Cipher::AES.new(128, :ECB)
225
+ cipher.decrypt
226
+ cipher.key = Base64.decode64(delivery_mode['encryptionKey'].to_s)
202
227
 
203
- def _notify(message)
204
- count = count_observers
205
- count_string = " -- RingCentralSdk::REST::Subscription: Notify #{count.to_s} observers"
206
- puts count_string
228
+ ciphertext = Base64.decode64(message)
229
+ plaintext = cipher.update(ciphertext) + cipher.final
207
230
 
208
- message = _decrypt message
209
- changed
210
- notify_observers message
211
- end
231
+ message = MultiJson.decode(plaintext, symbolize_keys: false)
232
+ end
212
233
 
213
- def _decrypt(message)
214
- unless alive?
215
- raise 'Subscription is not alive'
234
+ message
216
235
  end
217
236
 
218
- if _encrypted?()
237
+ def _encrypted?
219
238
  delivery_mode = @_subscription['deliveryMode']
220
-
221
- cipher = OpenSSL::Cipher::AES.new(128, :ECB)
222
- cipher.decrypt
223
- cipher.key = Base64.decode64(delivery_mode['encryptionKey'].to_s)
224
-
225
- ciphertext = Base64.decode64(message)
226
- plaintext = cipher.update(ciphertext) + cipher.final
227
-
228
- message = MultiJson.decode(plaintext, symbolize_keys: false)
239
+ is_encrypted = delivery_mode.key?('encryption') \
240
+ && delivery_mode['encryption'] \
241
+ && delivery_mode.key?('encryptionKey') \
242
+ && delivery_mode['encryptionKey']
243
+ is_encrypted
229
244
  end
230
245
 
231
- return message
232
- end
233
-
234
- def _encrypted?
235
- delivery_mode = @_subscription['deliveryMode']
236
- is_encrypted = delivery_mode.has_key?('encryption') && \
237
- delivery_mode['encryption'] && \
238
- delivery_mode.has_key?('encryptionKey') && \
239
- delivery_mode['encryptionKey']
240
- return is_encrypted
241
- end
242
-
243
- def _unsubscribe_at_pubnub
244
- if @_pubnub && alive?()
245
- @_pubnub.unsubscribe(channel: @_subscription['deliveryMode']['address']) do |envelope|
246
- # puts envelope.message
246
+ def _unsubscribe_at_pubnub
247
+ if @_pubnub && alive?
248
+ @_pubnub.unsubscribe(channel: @_subscription['deliveryMode']['address']) do |envelope|
249
+ puts envelope.status
250
+ end
247
251
  end
248
252
  end
249
- end
250
253
 
251
- def _set_timeout
252
- _clear_timeout
254
+ def _set_timeout
255
+ _clear_timeout
253
256
 
254
- time_to_expiration = @_subscription['expiresIn'] - RENEW_HANDICAP
257
+ time_to_expiration = @_subscription['expiresIn'] - RENEW_HANDICAP
255
258
 
256
- @_timeout = Thread.new do
257
- sleep time_to_expiration
258
- renew
259
+ @_timeout = Thread.new do
260
+ sleep time_to_expiration
261
+ renew
262
+ end
259
263
  end
260
- end
261
264
 
262
- def _clear_timeout
263
- @_timeout.exit if @_timeout.is_a?(Thread) && @_timeout.status == 'sleep'
264
- @_timeout = nil
265
- end
265
+ def _clear_timeout
266
+ @_timeout.exit if @_timeout.is_a?(Thread) && @_timeout.status == 'sleep'
267
+ @_timeout = nil
268
+ end
266
269
 
267
- def uri_join(*args)
268
- url = args.join('/').gsub(/\/+/, '/')
269
- return url.gsub(/^(https?:\/)/i, '\1/')
270
- end
270
+ def uri_join(*args)
271
+ url = args.join('/').gsub(%r{/+}, '/')
272
+ url.gsub(%r{^(https?:/)}i, '\1/')
273
+ end
271
274
 
272
- def new_pubnub(subscribe_key='', ssl_on=false, publish_key='', my_logger=nil)
273
- my_logger = Logger.new(STDOUT) if my_logger.nil?
274
-
275
- return Pubnub.new(
276
- subscribe_key: subscribe_key.to_s,
277
- publish_key: publish_key.to_s,
278
- error_callback: lambda { |msg|
279
- puts "Error callback says: #{msg.inspect}"
280
- },
281
- connect_callback: lambda { |msg|
282
- puts "CONNECTED: #{msg.inspect}"
283
- },
284
- logger: my_logger
285
- )
275
+ def new_pubnub(subscribe_key = '', ssl_on = false, publish_key = '', my_logger = nil)
276
+ Pubnub.new(
277
+ subscribe_key: subscribe_key.to_s,
278
+ publish_key: publish_key.to_s
279
+ )
280
+ end
286
281
  end
287
282
  end
288
283
  end