test-rc-sdk 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: f0ed544553943eef59bca4060e254a266591ca821c64e31e9d6b18f70c770aa6
4
+ data.tar.gz: b59c797191c98112301c069ed94850708c2a41868cade83fcafa9ae833b1fc71
5
+ SHA512:
6
+ metadata.gz: e5ea09c8f9b261383ba26ad46987a9ab653e09a550ee81d48bf316119d857060f9031633339b7b3f3b9985f05525912579650ed40ad28b51394f1bbe88493bbe
7
+ data.tar.gz: d5a62a30adfdaa7835007fb6377e4414c9d7630dc9e9ebd5e631a417e2777ee4c7211897cb03387d94f85ebe82f2d97ab0d43591967ace3da6ed4d6ee4106982
data/README.md ADDED
@@ -0,0 +1,190 @@
1
+ # RingCentral SDK for Ruby
2
+
3
+ [![Ruby](https://github.com/ringcentral/ringcentral-ruby/actions/workflows/ruby.yml/badge.svg)](https://github.com/ringcentral/ringcentral-ruby/actions/workflows/ruby.yml)
4
+ [![Reference](https://img.shields.io/badge/rubydoc-reference-blue?logo=ruby)](https://ringcentral.github.io/ringcentral-ruby/)
5
+ [![Twitter](https://img.shields.io/twitter/follow/ringcentraldevs.svg?style=social&label=follow)](https://twitter.com/RingCentralDevs)
6
+
7
+ __[RingCentral Developers](https://developer.ringcentral.com/api-products)__ is a cloud communications platform which can be accessed via more than 70 APIs. The platform's main capabilities include technologies that enable:
8
+ __[Voice](https://developer.ringcentral.com/api-products/voice), [SMS/MMS](https://developer.ringcentral.com/api-products/sms), [Fax](https://developer.ringcentral.com/api-products/fax), [Glip Team Messaging](https://developer.ringcentral.com/api-products/team-messaging), [Data and Configurations](https://developer.ringcentral.com/api-products/configuration)__.
9
+
10
+ ## Additional resources
11
+
12
+ * [RingCentral API Reference](https://developer.ringcentral.com/api-docs/latest/index.html) - an interactive reference for the RingCentral API that allows developers to make API calls with no code.
13
+ * [Document](https://ringcentral.github.io/ringcentral-ruby/) - an interactive reference for the SDK code documentation.
14
+
15
+
16
+ ## Getting help and support
17
+
18
+ If you are having difficulty using this SDK, or working with the RingCentral API, please visit our [developer community forums](https://community.ringcentral.com/spaces/144/) for help and to get quick answers to your questions. If you wish to contact the RingCentral Developer Support team directly, please [submit a help ticket](https://developers.ringcentral.com/support/create-case) from our developer website.
19
+
20
+
21
+ ## Installation
22
+
23
+ ```
24
+ gem install ringcentral-sdk
25
+ ```
26
+
27
+ If for some reason `eventmachine` failed to install, please check [this](https://stackoverflow.com/a/31516586/862862).
28
+
29
+
30
+ ### Name collision with `ringcentral` gem
31
+
32
+ The `ringcentral` gem is using RingCentral's legacy API which was End-of-Lifed in 2018. Everyone is recommended to move to the REST API.
33
+
34
+ If you have both the `ringcentral` and `ringcentral-sdk` gems installed, you will run into a collision error when attempting to initialize the `ringcentral-sdk` RingCentral SDK.
35
+
36
+ The solution is `gem uninstall ringcentral`
37
+
38
+
39
+ ## Documentation
40
+
41
+ https://developer.ringcentral.com/api-docs/latest/index.html
42
+
43
+
44
+ ## Usage
45
+
46
+ ```ruby
47
+ require 'ringcentral'
48
+
49
+ rc = RingCentral.new('clientID', 'clientSecret', 'serverURL')
50
+ rc.authorize(jwt: 'jwt-token')
51
+
52
+ # get
53
+ r = rc.get('/restapi/v1.0/account/~/extension/~')
54
+ expect(r).not_to be_nil
55
+ expect('101').to eq(r.body['extensionNumber'])
56
+ ```
57
+
58
+
59
+ ## How to specify query parameters
60
+
61
+ ### for get & delete
62
+
63
+ ```ruby
64
+ rc.get('/restapi/v1.0/account/~/extension', { hello: 'world' })
65
+ ```
66
+
67
+ ### for post, put & patch
68
+
69
+ ```ruby
70
+ rc.post('/restapi/v1.0/account/~/extension/~/sms', payload: body, params: { hello: 'world' })
71
+ ```
72
+
73
+ ### multi-value query parameter
74
+
75
+ ```ruby
76
+ rc.get('/restapi/v1.0/account/~/extension', { hello: ['world1', 'world2'] })
77
+ ```
78
+
79
+ Above will be translated to `/restapi/v1.0/account/~/extension?hello=world1&hello=world2`.
80
+
81
+
82
+ ### Token Refresh
83
+
84
+ Access token expires. You need to call `rc.refresh()` before it expires.
85
+ If you want the SDK to do auto refresh please `rc.auto_refresh = true` before authorization.
86
+
87
+
88
+ ### Load pre-existing token
89
+
90
+ Let's say you already have a token. Then you can load it like this: `rc.token = your_token_object`.
91
+ The benefit of loading a preexisting token is you don't need to go through any authorization flow.
92
+
93
+ If what you have is a JSON string instead of a Ruby object, you need to convert it first: `JSON.parse(your_token_string)`.
94
+
95
+ If you only have a string for the access token instead of for the whole object, you can set it like this:
96
+
97
+ ```ruby
98
+ rc.token = { access_token: 'the token string' }
99
+ ```
100
+
101
+
102
+ ### Send SMS
103
+
104
+ ```ruby
105
+ r = rc.post('/restapi/v1.0/account/~/extension/~/sms', payload: {
106
+ to: [{phoneNumber: ENV['RINGCENTRAL_RECEIVER']}],
107
+ from: {phoneNumber: ENV['RINGCENTRAL_SENDER']},
108
+ text: 'Hello world'
109
+ })
110
+ ```
111
+
112
+
113
+ ### Send fax
114
+
115
+ ```ruby
116
+ rc.post('/restapi/v1.0/account/~/extension/~/fax',
117
+ payload: { to: [{ phoneNumber: ENV['RINGCENTRAL_RECEIVER'] }] },
118
+ files: [
119
+ ['spec/test.txt', 'text/plain'],
120
+ ['spec/test.png', 'image/png']
121
+ ]
122
+ )
123
+ ```
124
+
125
+
126
+ ### Send MMS
127
+
128
+ ```ruby
129
+ r = rc.post('/restapi/v1.0/account/~/extension/~/sms',
130
+ payload: {
131
+ to: [{ phoneNumber: ENV['RINGCENTRAL_RECEIVER'] }],
132
+ from: { phoneNumber: ENV['RINGCENTRAL_SENDER'] },
133
+ text: 'hello world'
134
+ },
135
+ files: [
136
+ ['spec/test.png', 'image/png']
137
+ ]
138
+ )
139
+ ```
140
+
141
+
142
+ ## Subscriptions
143
+
144
+ ### WebSocket Subscriptions
145
+
146
+ ```ruby
147
+ events = [
148
+ '/restapi/v1.0/account/~/extension/~/message-store',
149
+ ]
150
+ subscription = WS.new(rc, events, lambda { |message|
151
+ puts message
152
+ })
153
+ subscription.subscribe()
154
+ ```
155
+
156
+ #### How to keep a subscription running 24 * 7?
157
+
158
+ There are two main cases that a subscription will be terminated:
159
+
160
+ - Absolute time out. The maximum time for a subscription to run is 24 hours. After that, the websocket connection will be closed by the server.
161
+ - Network issue. It could be your local network issue or the server's network issue. In either case, your websocket connection will be closed
162
+
163
+ In order to keep a subscription running 24 * 7, you need to re-subscribe when the connection is closed.
164
+
165
+ ```ruby
166
+ subscription.on_ws_closed = lambda { |event|
167
+ # make sure that there is no network issue and re-subscribe
168
+ subscription.subscribe()
169
+ }
170
+ ```
171
+
172
+
173
+ ## How to test
174
+
175
+ ```
176
+ bundle install
177
+ ```
178
+
179
+ Rename `.env.sample` to `.env`.
180
+
181
+ Edit `.env` file to specify credentials.
182
+
183
+ `RINGCENTRAL_RECEIVER` is a phone number to receive SMS, Fax..etc.
184
+
185
+ Run `bundle exec rspec`
186
+
187
+
188
+ ## License
189
+
190
+ MIT
@@ -0,0 +1,227 @@
1
+ require 'base64'
2
+ require 'addressable/uri'
3
+ require 'json'
4
+ require 'concurrent'
5
+ require 'faraday'
6
+ require 'faraday/multipart'
7
+
8
+ class RingCentral
9
+ def self.PRODUCTION_SERVER
10
+ 'https://platform.ringcentral.com'
11
+ end
12
+
13
+ attr_reader :client_id, :client_secret, :server, :token
14
+ attr_accessor :auto_refresh, :debug_mode
15
+
16
+ def initialize(client_id, client_secret, server = self.PRODUCTION_SERVER, debug_mode = false)
17
+ @client_id = client_id
18
+ @client_secret = client_secret
19
+ @server = server
20
+ @auto_refresh = false
21
+ @debug_mode = debug_mode
22
+ @token = nil
23
+ @timer = nil
24
+ @faraday = Faraday.new(url: server, request: { params_encoder: Faraday::FlatParamsEncoder }) do |faraday|
25
+ faraday.request :multipart
26
+ faraday.request :url_encoded
27
+ faraday.response :json, content_type: /\bjson$/
28
+ faraday.adapter Faraday.default_adapter
29
+ end
30
+ end
31
+
32
+ def token=(value)
33
+ @token = value
34
+ if @timer != nil
35
+ @timer.shutdown
36
+ @timer = nil
37
+ end
38
+ if @auto_refresh && value != nil
39
+ @timer = Concurrent::TimerTask.new(execution_interval: value['expires_in'] - 120, timeout_interval: 60) { self.refresh }
40
+ @timer.execute
41
+ end
42
+ end
43
+
44
+ def authorize(username: nil, extension: nil, password: nil, auth_code: nil, redirect_uri: nil, jwt: nil, verifier: nil)
45
+ if auth_code != nil
46
+ payload = {
47
+ grant_type: 'authorization_code',
48
+ code: auth_code,
49
+ redirect_uri: redirect_uri,
50
+ }
51
+ if verifier != nil
52
+ payload["code_verifier"] = verifier
53
+ end
54
+ elsif jwt != nil
55
+ payload = {
56
+ grant_type: 'urn:ietf:params:oauth:grant-type:jwt-bearer',
57
+ assertion: jwt
58
+ }
59
+ else
60
+ warn('Password auth is deprecated. Use JWT auth or OAuth instead.')
61
+ payload = {
62
+ grant_type: 'password',
63
+ username: username,
64
+ extension: extension,
65
+ password: password,
66
+ }
67
+ end
68
+ self.token = nil
69
+ r = self.post('/restapi/oauth/token', payload: payload)
70
+ self.token = r.body
71
+ end
72
+
73
+ def refresh
74
+ return if @token == nil
75
+ payload = {
76
+ grant_type: 'refresh_token',
77
+ refresh_token: @token['refresh_token']
78
+ }
79
+ self.token = nil
80
+ r = self.post('/restapi/oauth/token', payload: payload)
81
+ self.token = r.body
82
+ end
83
+
84
+ def revoke
85
+ return if @token == nil
86
+ payload = { token: @token['access_token'] }
87
+ self.token = nil
88
+ self.post('/restapi/oauth/revoke', payload: payload)
89
+ end
90
+
91
+ def authorize_uri(redirect_uri, hash = {})
92
+ hash[:response_type] = 'code'
93
+ hash[:redirect_uri] = redirect_uri
94
+ hash[:client_id] = @client_id
95
+ uri = Addressable::URI.parse(@server) + '/restapi/oauth/authorize'
96
+ uri.query_values = hash
97
+ uri.to_s
98
+ end
99
+
100
+ def get(endpoint, params = {})
101
+ r = @faraday.get do |req|
102
+ req.url endpoint
103
+ req.params = params
104
+ req.headers = headers
105
+ end
106
+ if @debug_mode
107
+ puts r.status, r.body
108
+ end
109
+ if r.status >= 400
110
+ raise "HTTP status #{r.status}:
111
+
112
+ headers: #{r.headers}
113
+
114
+ body: #{r.body}"
115
+ end
116
+ return r
117
+ end
118
+
119
+ def post(endpoint, payload: nil, params: {}, files: nil)
120
+ r = @faraday.post do |req|
121
+ req.url endpoint
122
+ req.params = params
123
+ if files != nil && files.size > 0 # send fax or MMS
124
+ io = StringIO.new(payload.to_json)
125
+ payload = {}
126
+ payload[:json] = Faraday::UploadIO.new(io, 'application/json')
127
+ payload[:attachment] = files.map{ |file| Faraday::UploadIO.new(file[0], file[1]) }
128
+ req.headers = headers
129
+ req.body = payload
130
+ elsif payload != nil && @token != nil
131
+ req.headers = headers.merge({ 'Content-Type': 'application/json' })
132
+ req.body = payload.to_json
133
+ else
134
+ req.headers = headers
135
+ req.body = payload
136
+ end
137
+ end
138
+ if @debug_mode
139
+ puts r.status, r.body
140
+ end
141
+ if r.status >= 400
142
+ raise "HTTP status #{r.status}:
143
+
144
+ headers: #{r.headers}
145
+
146
+ body: #{r.body}"
147
+ end
148
+ return r
149
+ end
150
+
151
+ def put(endpoint, payload: nil, params: {}, files: nil)
152
+ r = @faraday.put do |req|
153
+ req.url endpoint
154
+ req.params = params
155
+ req.headers = headers.merge({ 'Content-Type': 'application/json' })
156
+ req.body = payload.to_json
157
+ end
158
+ if @debug_mode
159
+ puts r.status, r.body
160
+ end
161
+ if r.status >= 400
162
+ raise "HTTP status #{r.status}:
163
+
164
+ headers: #{r.headers}
165
+
166
+ body: #{r.body}"
167
+ end
168
+ return r
169
+ end
170
+
171
+ def patch(endpoint, payload: nil, params: {}, files: nil)
172
+ r = @faraday.patch do |req|
173
+ req.url endpoint
174
+ req.params = params
175
+ req.headers = headers.merge({ 'Content-Type': 'application/json' })
176
+ req.body = payload.to_json
177
+ end
178
+ if @debug_mode
179
+ puts r.status, r.body
180
+ end
181
+ if r.status >= 400
182
+ raise "HTTP status #{r.status}:
183
+
184
+ headers: #{r.headers}
185
+
186
+ body: #{r.body}"
187
+ end
188
+ return r
189
+ end
190
+
191
+ def delete(endpoint, params = {})
192
+ r = @faraday.delete do |req|
193
+ req.url endpoint
194
+ req.params = params
195
+ req.headers = headers
196
+ end
197
+ if @debug_mode
198
+ puts r.status, r.body
199
+ end
200
+ if r.status >= 400
201
+ raise "HTTP status #{r.status}:
202
+
203
+ headers: #{r.headers}
204
+
205
+ body: #{r.body}"
206
+ end
207
+ return r
208
+ end
209
+
210
+ private
211
+
212
+ def basic_key
213
+ Base64.encode64("#{@client_id}:#{@client_secret}").gsub(/\s/, '')
214
+ end
215
+
216
+ def autorization_header
217
+ @token != nil ? "Bearer #{@token['access_token']}" : "Basic #{basic_key}"
218
+ end
219
+
220
+ def headers
221
+ user_agent_header = "ringcentral/ringcentral-ruby Ruby #{RUBY_VERSION} #{RUBY_PLATFORM}"
222
+ {
223
+ 'Authorization': autorization_header,
224
+ 'X-User-Agent': user_agent_header,
225
+ }
226
+ end
227
+ end
@@ -0,0 +1,66 @@
1
+ require 'concurrent'
2
+ require 'faye/websocket'
3
+ require 'securerandom'
4
+ require 'eventmachine'
5
+
6
+ class WS
7
+ def initialize(ringcentral, events, callback, debugMode = false)
8
+ @rc = ringcentral
9
+ @events = events
10
+ @callback = callback
11
+ @debugMode = debugMode
12
+ end
13
+
14
+ def on_ws_closed=(callback)
15
+ @on_ws_closed = callback
16
+ end
17
+
18
+ def subscribe
19
+ r = @rc.post('/restapi/oauth/wstoken').body
20
+ @t = Thread.new do
21
+ EM.run {
22
+ @ws = Faye::WebSocket::Client.new(r['uri'] + '?access_token=' + r['ws_access_token'])
23
+ if @debugMode
24
+ class << @ws
25
+ def send(message)
26
+ puts "Sending...\n" + message
27
+ super(message)
28
+ end
29
+ end
30
+ end
31
+ @ws.on :open do
32
+ @ws.send([
33
+ { type: 'ClientRequest', method: 'POST', path: '/restapi/v1.0/subscription', messageId: SecureRandom.uuid },
34
+ { deliveryMode: { transportType: 'WebSocket' }, eventFilters: @events }
35
+ ].to_json())
36
+
37
+ # send a heartbeat every 10 minutes
38
+ @task = Concurrent::TimerTask.new(execution_interval: 600) do
39
+ @ws.send([
40
+ { type: 'Heartbeat', messageId: SecureRandom.uuid },
41
+ ].to_json())
42
+ end
43
+ @task.execute
44
+ end
45
+ @ws.on :message do |event|
46
+ if @debugMode
47
+ puts "Receiving...\n" + event.data
48
+ end
49
+ header, body = JSON.parse(event.data)
50
+ if header['type'] == 'ServerNotification'
51
+ @callback.call(body)
52
+ end
53
+ end
54
+ @ws.on :close do |event|
55
+ if @on_ws_closed
56
+ @on_ws_closed.call(event)
57
+ end
58
+ end
59
+ }
60
+ end
61
+ end
62
+
63
+ def revoke
64
+ @t.kill
65
+ end
66
+ end
data/spec/fax_spec.rb ADDED
@@ -0,0 +1,26 @@
1
+ require 'dotenv'
2
+ require 'ringcentral'
3
+ require "simplecov"
4
+ SimpleCov.start
5
+
6
+ RSpec.describe 'Fax' do
7
+ describe 'send fax' do
8
+ it 'should send a fax' do
9
+ Dotenv.load
10
+ rc = RingCentral.new(ENV['RINGCENTRAL_CLIENT_ID'], ENV['RINGCENTRAL_CLIENT_SECRET'], ENV['RINGCENTRAL_SERVER_URL'])
11
+ rc.authorize(jwt: ENV['RINGCENTRAL_JWT_TOKEN'])
12
+ r = rc.post('/restapi/v1.0/account/~/extension/~/fax',
13
+ payload: { to: [{ phoneNumber: ENV['RINGCENTRAL_RECEIVER'] }] },
14
+ files: [
15
+ ['spec/test.txt', 'text/plain'],
16
+ ['spec/test.png', 'image/png']
17
+ ]
18
+ )
19
+ expect(r).not_to be_nil
20
+ message = r.body
21
+ expect('Fax').to eq(message['type'])
22
+
23
+ rc.revoke()
24
+ end
25
+ end
26
+ end
data/spec/mms_spec.rb ADDED
@@ -0,0 +1,30 @@
1
+ require 'dotenv'
2
+ require 'ringcentral'
3
+ require "simplecov"
4
+ SimpleCov.start
5
+
6
+ RSpec.describe 'MMS' do
7
+ describe 'send MMS' do
8
+ it 'should send an MMS' do
9
+ Dotenv.load
10
+ rc = RingCentral.new(ENV['RINGCENTRAL_CLIENT_ID'], ENV['RINGCENTRAL_CLIENT_SECRET'], ENV['RINGCENTRAL_SERVER_URL'])
11
+ rc.authorize(jwt: ENV['RINGCENTRAL_JWT_TOKEN'])
12
+
13
+ r = rc.post('/restapi/v1.0/account/~/extension/~/sms',
14
+ payload: {
15
+ to: [{ phoneNumber: ENV['RINGCENTRAL_RECEIVER'] }],
16
+ from: { phoneNumber: ENV['RINGCENTRAL_SENDER'] },
17
+ text: 'hello world'
18
+ },
19
+ files: [
20
+ ['spec/test.png', 'image/png']
21
+ ]
22
+ )
23
+ expect(r).not_to be_nil
24
+ message = r.body
25
+ expect('SMS').to eq(message['type'])
26
+
27
+ rc.revoke()
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,25 @@
1
+ require 'dotenv'
2
+ require 'ringcentral'
3
+ require "simplecov"
4
+ SimpleCov.start
5
+
6
+ RSpec.describe 'query params' do
7
+ describe 'single' do
8
+ it 'contain single query param' do
9
+ Dotenv.load
10
+ rc = RingCentral.new(ENV['RINGCENTRAL_CLIENT_ID'], ENV['RINGCENTRAL_CLIENT_SECRET'], ENV['RINGCENTRAL_SERVER_URL'])
11
+ rc.authorize(jwt: ENV['RINGCENTRAL_JWT_TOKEN'])
12
+ r = rc.get('/restapi/v1.0/account/~/extension/~/address-book/contact', { phoneNumber: '666' })
13
+ expect(r).not_to be_nil
14
+ message = r.body
15
+ expect(message['uri']).to include('phoneNumber=666')
16
+
17
+ r = rc.get('/restapi/v1.0/account/~/extension/~/address-book/contact', { phoneNumber: ['666', '888'] })
18
+ expect(r).not_to be_nil
19
+ message = r.body
20
+ expect(message['uri']).to include('phoneNumber=666&phoneNumber=888')
21
+
22
+ rc.revoke()
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,86 @@
1
+ require 'ringcentral'
2
+ require "simplecov"
3
+ SimpleCov.start
4
+
5
+ RSpec.describe 'RingCentral' do
6
+ describe 'ringcentral' do
7
+ it 'test_class_variables' do
8
+ expect('https://platform.ringcentral.com').to eq(RingCentral.PRODUCTION_SERVER)
9
+ end
10
+
11
+ it 'test_initializer' do
12
+ rc = RingCentral.new('client_id', 'client_secret', RingCentral.PRODUCTION_SERVER)
13
+ expect('client_id').to eq(rc.client_id)
14
+ expect('client_secret').to eq(rc.client_secret)
15
+ expect('https://platform.ringcentral.com').to eq(rc.server)
16
+ expect(false).to eq(rc.auto_refresh)
17
+ end
18
+
19
+ it 'test_authorize_uri' do
20
+ rc = RingCentral.new('client_id', 'client_secret', RingCentral.PRODUCTION_SERVER)
21
+ expect(RingCentral.PRODUCTION_SERVER + '/restapi/oauth/authorize?client_id=client_id&redirect_uri=https%3A%2F%2Fexample.com&response_type=code&state=mystate').to eq(rc.authorize_uri('https://example.com', {state: 'mystate'}))
22
+ end
23
+
24
+ it 'test_jwt_flow' do
25
+ Dotenv.load
26
+ rc = RingCentral.new(ENV['RINGCENTRAL_CLIENT_ID'], ENV['RINGCENTRAL_CLIENT_SECRET'], ENV['RINGCENTRAL_SERVER_URL'])
27
+ expect(rc.token).to be_nil
28
+
29
+ # create token
30
+ rc.authorize(jwt: ENV['RINGCENTRAL_JWT_TOKEN'])
31
+ expect(rc.token).not_to be_nil
32
+
33
+ # refresh token
34
+ rc.refresh
35
+ expect(rc.token).not_to be_nil
36
+
37
+ # revoke token
38
+ rc.revoke
39
+ expect(rc.token).to be_nil
40
+ end
41
+
42
+ it 'test_http_methods' do
43
+ Dotenv.load
44
+ rc = RingCentral.new(ENV['RINGCENTRAL_CLIENT_ID'], ENV['RINGCENTRAL_CLIENT_SECRET'], ENV['RINGCENTRAL_SERVER_URL'])
45
+ rc.authorize(jwt: ENV['RINGCENTRAL_JWT_TOKEN'])
46
+
47
+ # get
48
+ r = rc.get('/restapi/v1.0/account/~/extension/~')
49
+ expect(r).not_to be_nil
50
+ expect(r.body['extensionNumber']).not_to be_nil
51
+
52
+ # post
53
+ r = rc.post('/restapi/v1.0/account/~/extension/~/company-pager', payload: {
54
+ to: [{extensionId: rc.token['owner_id']}],
55
+ from: {extensionId: rc.token['owner_id']},
56
+ text: 'Hello world'
57
+ })
58
+ expect(r).not_to be_nil
59
+ message = r.body
60
+ expect('Pager').to eq(message['type'])
61
+ messageUrl = "/restapi/v1.0/account/~/extension/~/message-store/#{message['id']}"
62
+
63
+ # put
64
+ r = rc.put(messageUrl, payload: { readStatus: 'Unread' })
65
+ expect(r).not_to be_nil
66
+ message = r.body
67
+ expect('Unread').to eq(message['readStatus'])
68
+ r = rc.put(messageUrl, payload: { readStatus: 'Read' })
69
+ expect(r).not_to be_nil
70
+ message = r.body
71
+ expect('Read').to eq(message['readStatus'])
72
+
73
+ # todo: test patch
74
+
75
+ # delete
76
+ r = rc.delete(messageUrl)
77
+ expect(r).not_to be_nil
78
+ r = rc.get(messageUrl)
79
+ expect(r).not_to be_nil
80
+ message = r.body
81
+ expect('Deleted').to eq(message['availability'])
82
+
83
+ rc.revoke()
84
+ end
85
+ end
86
+ end
@@ -0,0 +1,76 @@
1
+ require 'ringcentral'
2
+ require 'subscription'
3
+ require 'dotenv'
4
+ require 'rspec'
5
+ require "simplecov"
6
+ SimpleCov.start
7
+
8
+ Dotenv.load
9
+ $rc = RingCentral.new(ENV['RINGCENTRAL_CLIENT_ID'], ENV['RINGCENTRAL_CLIENT_SECRET'], ENV['RINGCENTRAL_SERVER_URL'])
10
+
11
+ RSpec.describe 'WebSocket Subscription' do
12
+ def createSubscription(callback)
13
+ events = [
14
+ '/restapi/v1.0/account/~/extension/~/message-store?type=Pager',
15
+ ]
16
+ subscription = WS.new($rc, events, lambda { |message|
17
+ callback.call(message)
18
+ })
19
+ subscription.subscribe()
20
+ # subscription.on_ws_closed = lambda { |event|
21
+ # puts 'WebSocket closed'
22
+ # }
23
+ return subscription
24
+ end
25
+
26
+ describe 'WebSocket Subscription' do
27
+ it 'receives message notification' do
28
+ $rc.authorize(jwt: ENV['RINGCENTRAL_JWT_TOKEN'])
29
+ count = 0
30
+ sub = createSubscription(lambda { |message|
31
+ count += 1
32
+ })
33
+
34
+ $rc.post('/restapi/v1.0/account/~/extension/~/company-pager', payload: {
35
+ to: [{extensionId: $rc.token['owner_id']}],
36
+ from: {extensionId: $rc.token['owner_id']},
37
+ text: 'Hello world'
38
+ })
39
+ sleep(10)
40
+ expect(count).to be > 0
41
+
42
+ # sleep for some time and see if the websocket is still alive
43
+ sleep(20)
44
+ $rc.post('/restapi/v1.0/account/~/extension/~/company-pager', payload: {
45
+ to: [{extensionId: $rc.token['owner_id']}],
46
+ from: {extensionId: $rc.token['owner_id']},
47
+ text: 'Hello world'
48
+ })
49
+ sleep(10)
50
+ expect(count).to be > 1
51
+
52
+ sub.revoke()
53
+ $rc.revoke()
54
+ end
55
+
56
+ it 'revoke' do
57
+ $rc.authorize(jwt: ENV['RINGCENTRAL_JWT_TOKEN'])
58
+ count = 0
59
+ subscription = createSubscription(lambda { |message|
60
+ count += 1
61
+ })
62
+
63
+ subscription.revoke()
64
+
65
+ $rc.post('/restapi/v1.0/account/~/extension/~/company-pager', payload: {
66
+ to: [{extensionId: $rc.token['owner_id']}],
67
+ from: {extensionId: $rc.token['owner_id']},
68
+ text: 'Hello world'
69
+ })
70
+ sleep(10)
71
+
72
+ expect(count).to eq(0)
73
+ $rc.revoke()
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,21 @@
1
+ Gem::Specification.new do |gem|
2
+ gem.name = 'test-rc-sdk'
3
+ gem.version = '1.0.0'
4
+ gem.authors = ['Sushil Mall']
5
+ gem.email = ['sushil.mall@ringcentral.com']
6
+ gem.description = 'Ruby SDK for you to access RingCentral platform API.'
7
+ gem.summary = 'RingCentral Ruby SDK.'
8
+ gem.homepage = 'https://github.com/SushilMallRC/ringcentral-ruby'
9
+ gem.license = 'MIT'
10
+
11
+ gem.require_paths = ['lib']
12
+ gem.files = %w(README.md test-rc-sdk.gemspec)
13
+ gem.files += Dir['lib/**/*.rb']
14
+ gem.test_files = Dir['spec/**/*.rb']
15
+
16
+ gem.add_dependency('addressable', '~> 2.8', '>= 2.8.6')
17
+ gem.add_dependency('concurrent-ruby', '~> 1.2', '>= 1.2.3')
18
+ gem.add_dependency('faraday', '~> 2.9', '>= 2.9.0')
19
+ gem.add_dependency('faraday-multipart', '~> 1.0', '>= 1.0.4')
20
+ gem.add_dependency('faye-websocket', '~> 0.11', '>= 0.11.3')
21
+ end
metadata ADDED
@@ -0,0 +1,157 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: test-rc-sdk
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Sushil Mall
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2024-05-02 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: addressable
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '2.8'
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: 2.8.6
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - "~>"
28
+ - !ruby/object:Gem::Version
29
+ version: '2.8'
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: 2.8.6
33
+ - !ruby/object:Gem::Dependency
34
+ name: concurrent-ruby
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: '1.2'
40
+ - - ">="
41
+ - !ruby/object:Gem::Version
42
+ version: 1.2.3
43
+ type: :runtime
44
+ prerelease: false
45
+ version_requirements: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - "~>"
48
+ - !ruby/object:Gem::Version
49
+ version: '1.2'
50
+ - - ">="
51
+ - !ruby/object:Gem::Version
52
+ version: 1.2.3
53
+ - !ruby/object:Gem::Dependency
54
+ name: faraday
55
+ requirement: !ruby/object:Gem::Requirement
56
+ requirements:
57
+ - - "~>"
58
+ - !ruby/object:Gem::Version
59
+ version: '2.9'
60
+ - - ">="
61
+ - !ruby/object:Gem::Version
62
+ version: 2.9.0
63
+ type: :runtime
64
+ prerelease: false
65
+ version_requirements: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - "~>"
68
+ - !ruby/object:Gem::Version
69
+ version: '2.9'
70
+ - - ">="
71
+ - !ruby/object:Gem::Version
72
+ version: 2.9.0
73
+ - !ruby/object:Gem::Dependency
74
+ name: faraday-multipart
75
+ requirement: !ruby/object:Gem::Requirement
76
+ requirements:
77
+ - - "~>"
78
+ - !ruby/object:Gem::Version
79
+ version: '1.0'
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: 1.0.4
83
+ type: :runtime
84
+ prerelease: false
85
+ version_requirements: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '1.0'
90
+ - - ">="
91
+ - !ruby/object:Gem::Version
92
+ version: 1.0.4
93
+ - !ruby/object:Gem::Dependency
94
+ name: faye-websocket
95
+ requirement: !ruby/object:Gem::Requirement
96
+ requirements:
97
+ - - "~>"
98
+ - !ruby/object:Gem::Version
99
+ version: '0.11'
100
+ - - ">="
101
+ - !ruby/object:Gem::Version
102
+ version: 0.11.3
103
+ type: :runtime
104
+ prerelease: false
105
+ version_requirements: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - "~>"
108
+ - !ruby/object:Gem::Version
109
+ version: '0.11'
110
+ - - ">="
111
+ - !ruby/object:Gem::Version
112
+ version: 0.11.3
113
+ description: Ruby SDK for you to access RingCentral platform API.
114
+ email:
115
+ - sushil.mall@ringcentral.com
116
+ executables: []
117
+ extensions: []
118
+ extra_rdoc_files: []
119
+ files:
120
+ - README.md
121
+ - lib/ringcentral.rb
122
+ - lib/subscription.rb
123
+ - spec/fax_spec.rb
124
+ - spec/mms_spec.rb
125
+ - spec/query_params_spec.rb
126
+ - spec/ringcentral_spec.rb
127
+ - spec/websocket_subscription_spec.rb
128
+ - test-rc-sdk.gemspec
129
+ homepage: https://github.com/SushilMallRC/ringcentral-ruby
130
+ licenses:
131
+ - MIT
132
+ metadata: {}
133
+ post_install_message:
134
+ rdoc_options: []
135
+ require_paths:
136
+ - lib
137
+ required_ruby_version: !ruby/object:Gem::Requirement
138
+ requirements:
139
+ - - ">="
140
+ - !ruby/object:Gem::Version
141
+ version: '0'
142
+ required_rubygems_version: !ruby/object:Gem::Requirement
143
+ requirements:
144
+ - - ">="
145
+ - !ruby/object:Gem::Version
146
+ version: '0'
147
+ requirements: []
148
+ rubygems_version: 3.4.19
149
+ signing_key:
150
+ specification_version: 4
151
+ summary: RingCentral Ruby SDK.
152
+ test_files:
153
+ - spec/fax_spec.rb
154
+ - spec/mms_spec.rb
155
+ - spec/query_params_spec.rb
156
+ - spec/ringcentral_spec.rb
157
+ - spec/websocket_subscription_spec.rb