From ed300f429440f79abb2e9ad4457cb284fd7e4476 Mon Sep 17 00:00:00 2001 From: superchilled Date: Mon, 8 Aug 2022 10:38:28 +0100 Subject: [PATCH 1/7] Adding test for Websocket#connect method --- spec/opentok/websocket_spec.rb | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 spec/opentok/websocket_spec.rb diff --git a/spec/opentok/websocket_spec.rb b/spec/opentok/websocket_spec.rb new file mode 100644 index 0000000..2ce8b8c --- /dev/null +++ b/spec/opentok/websocket_spec.rb @@ -0,0 +1,26 @@ +require "opentok/opentok" +require "opentok/websocket" +require "opentok/version" +require "spec_helper" + +describe OpenTok::WebSocket do + before(:each) do + now = Time.parse("2017-04-18 20:17:40 +1000") + allow(Time).to receive(:now) { now } + end + + let(:api_key) { "123456" } + let(:api_secret) { "1234567890abcdef1234567890abcdef1234567890" } + let(:session_id) { "SESSIONID" } + let(:connection_id) { "CONNID" } + let(:expiring_token) { "TOKENID" } + let(:websocket_uri) { "ws://service.com/wsendpoint" } + let(:opentok) { OpenTok::OpenTok.new api_key, api_secret } + let(:websocket) { opentok.websocket } + subject { websocket } + + it "receives a valid response", :vcr => { :erb => { :version => OpenTok::VERSION + "-Ruby-Version-#{RUBY_VERSION}-p#{RUBY_PATCHLEVEL}"} } do + response = websocket.connect(session_id, expiring_token, websocket_uri) + expect(response).not_to be_nil + end +end From 90400d663f3e5a09b4023411a167e620cd09fc0d Mon Sep 17 00:00:00 2001 From: superchilled Date: Mon, 8 Aug 2022 10:39:11 +0100 Subject: [PATCH 2/7] Implementing Websocket connect functionality --- lib/opentok/client.rb | 29 +++++++++++++++++++++++++++++ lib/opentok/exceptions.rb | 2 ++ lib/opentok/opentok.rb | 5 +++++ lib/opentok/websocket.rb | 37 +++++++++++++++++++++++++++++++++++++ 4 files changed, 73 insertions(+) create mode 100644 lib/opentok/websocket.rb diff --git a/lib/opentok/client.rb b/lib/opentok/client.rb index 05a2353..1ad8a33 100644 --- a/lib/opentok/client.rb +++ b/lib/opentok/client.rb @@ -298,6 +298,35 @@ def signal(session_id, connection_id, opts) raise OpenTokError, "Failed to connect to OpenTok. Response code: #{e.message}" end + def connect_websocket(session_id, token, websocket_uri, opts) + opts.extend(HashExtensions) + body = { "sessionId" => session_id, + "token" => token, + "websocket" => { "uri" => websocket_uri }.merge(opts.camelize_keys!) + } + + response = self.class.post("/v2/project/#{@api_key}/connect", { + :body => body.to_json, + :headers => generate_headers("Content-Type" => "application/json") + }) + case response.code + when 200 + response + when 400 + raise ArgumentError, "One of the properties is invalid." + when 403 + raise OpenTokAuthenticationError, "You are not authorized to start the call, check your authentication information." + when 409 + raise OpenTokWebSocketError, "Conflict. Only routed sessions are allowed to initiate Connect Calls." + when 500 + raise OpenTokError, "OpenTok server error." + else + raise OpenTokWebSocketError, "The WebSocket could not be connected" + end + rescue StandardError => e + raise OpenTokError, "Failed to connect to OpenTok. Response code: #{e.message}" + end + def dial(session_id, token, sip_uri, opts) opts.extend(HashExtensions) body = { "sessionId" => session_id, diff --git a/lib/opentok/exceptions.rb b/lib/opentok/exceptions.rb index 65ddea8..fd16e79 100644 --- a/lib/opentok/exceptions.rb +++ b/lib/opentok/exceptions.rb @@ -14,5 +14,7 @@ class OpenTokConnectionError < OpenTokError; end class OpenTokStreamLayoutError < OpenTokError; end # Defines errors raised when you perform Broadcast operations. class OpenTokBroadcastError < OpenTokError; end + # Defines errors raised when connecting to WebSocket URIs. + class OpenTokWebSocketError < OpenTokError; end end diff --git a/lib/opentok/opentok.rb b/lib/opentok/opentok.rb index b031865..c5668e9 100644 --- a/lib/opentok/opentok.rb +++ b/lib/opentok/opentok.rb @@ -212,6 +212,11 @@ def connections @connections ||= Connections.new client end + # A WebSocket object, which lets you connect OpenTok streams to a WebSocket URI. + def websocket + @websocket ||= WebSocket.new client + end + protected def client @client ||= Client.new api_key, api_secret, api_url, ua_addendum, timeout_length: @timeout_length diff --git a/lib/opentok/websocket.rb b/lib/opentok/websocket.rb new file mode 100644 index 0000000..2dab134 --- /dev/null +++ b/lib/opentok/websocket.rb @@ -0,0 +1,37 @@ +require "opentok/client" + +# An object that lets you use the OpenTok SIP gateway. +module OpenTok + class WebSocket + # Dials a SIP gateway to input an audio-only stream into your OpenTok session. + # See the {https://tokbox.com/developer/guides/sip/ OpenTok SIP developer guide}. + # + # @example + # opts = { + # "streams" => ["STREAMID1", "STREAMID2"], + # "headers" => { + # "key1" => "val1", + # "key2" => "val2" + # } + # } + # response = opentok.websocket.connect(SESSIONID, TOKEN, "ws://service.com/wsendpoint", opts) + # + # @param [String] session_id The session ID corresponding to the session to which + # the SIP gateway will connect. + # @param [String] token The token for the session ID with which the SIP user + # will use to connect. + # @param [String] websocket_uri The SIP URI the OpenTok SIP gateway will dial. + # @param [Hash] opts A hash defining options for the SIP call. For example: + # @option opts [Array] :streams The stream IDs of the participants' whose audio is going to be connected. + # If not provided, all streams in session will be selected. + # @option opts [Hash] :headers A hash of key/val pairs with additional properties to send to your + # Websocket server, with a maximum length of 512 bytes. + def connect(session_id, token, websocket_uri, opts = {}) + response = @client.connect_websocket(session_id, token, websocket_uri, opts) + end + + def initialize(client) + @client = client + end + end +end From d0a725fb88c7896d761400772242d687140ed262 Mon Sep 17 00:00:00 2001 From: superchilled Date: Mon, 8 Aug 2022 10:39:30 +0100 Subject: [PATCH 3/7] Addig VCR recording for WebSocket test --- .../receives_a_valid_response.yml | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 spec/cassettes/OpenTok_WebSocket/receives_a_valid_response.yml diff --git a/spec/cassettes/OpenTok_WebSocket/receives_a_valid_response.yml b/spec/cassettes/OpenTok_WebSocket/receives_a_valid_response.yml new file mode 100644 index 0000000..b0cc789 --- /dev/null +++ b/spec/cassettes/OpenTok_WebSocket/receives_a_valid_response.yml @@ -0,0 +1,37 @@ +--- +http_interactions: +- request: + method: post + uri: https://api.opentok.com/v2/project/123456/connect + body: + encoding: UTF-8 + string: '{"sessionId":"SESSIONID","token":"TOKENID","websocket":{"uri":"ws://service.com/wsendpoint"}}' + headers: + User-Agent: + - OpenTok-Ruby-SDK/<%= version %> + X-Opentok-Auth: + - eyJpc3QiOiJwcm9qZWN0IiwiYWxnIjoiSFMyNTYifQ.eyJpc3MiOiIxMjM0NTYiLCJpYXQiOjE0OTI1MTA2NjAsImV4cCI6MTQ5MjUxMDk2MH0.BplMVhJWx4ld7KLKXqEmow6MjNPPFw9W8IHCMfeb120 + Content-Type: + - application/json + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + response: + status: + code: 200 + message: OK + headers: + Date: + - Sat, 06 Aug 2022 18:10:28 GMT + Content-Type: + - application/json + Content-Length: + - '73' + Connection: + - keep-alive + body: + encoding: UTF-8 + string: '{"id":"2299ba24-a6de-417c-88f7-28da54a441cf","connectionId":"833a7182-61a5-49d4-baae-c324b09953af"}' + recorded_at: Tue, 18 Apr 2017 10:17:40 GMT +recorded_with: VCR 6.0.0 From 841d944343cc87ba21d716cc5d2ac002db657586 Mon Sep 17 00:00:00 2001 From: superchilled Date: Wed, 28 Sep 2022 14:55:19 +0100 Subject: [PATCH 4/7] Fixing code comments for Websocket#connect method --- lib/opentok/websocket.rb | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/lib/opentok/websocket.rb b/lib/opentok/websocket.rb index 2dab134..ffc989f 100644 --- a/lib/opentok/websocket.rb +++ b/lib/opentok/websocket.rb @@ -1,10 +1,10 @@ require "opentok/client" -# An object that lets you use the OpenTok SIP gateway. +# An object that lets you work with Audio Streamer WebSocket connections. module OpenTok class WebSocket - # Dials a SIP gateway to input an audio-only stream into your OpenTok session. - # See the {https://tokbox.com/developer/guides/sip/ OpenTok SIP developer guide}. + # Starts an Audio Streamer WebSocket connection to send audio from a Vonage Video API session to a WebSocket URI. + # See the {https://tokbox.com/developer/guides/audio-streamer/ OpenTok Audio Streamer developer guide}. # # @example # opts = { @@ -16,16 +16,16 @@ class WebSocket # } # response = opentok.websocket.connect(SESSIONID, TOKEN, "ws://service.com/wsendpoint", opts) # - # @param [String] session_id The session ID corresponding to the session to which - # the SIP gateway will connect. - # @param [String] token The token for the session ID with which the SIP user - # will use to connect. - # @param [String] websocket_uri The SIP URI the OpenTok SIP gateway will dial. - # @param [Hash] opts A hash defining options for the SIP call. For example: - # @option opts [Array] :streams The stream IDs of the participants' whose audio is going to be connected. - # If not provided, all streams in session will be selected. - # @option opts [Hash] :headers A hash of key/val pairs with additional properties to send to your - # Websocket server, with a maximum length of 512 bytes. + # @param [String] session_id (required) The OpenTok session ID that includes the OpenTok streams you want to include in + # the WebSocket stream. + # @param [String] token (required) The OpenTok token to be used for the Audio Streamer connection to the. OpenTok session. + # @param [String] websocket_uri (required) A publicly reachable WebSocket URI to be used for the destination of the audio + # stream (such as "wss://service.com/ws-endpoint"). + # @param [Hash] opts (optional) A hash defining options for the Audio Streamer WebSocket connection. For example: + # @option opts [Array] :streams (optional) An array of stream IDs for the OpenTok streams you want to include in the WebSocket stream. + # If you omit this property, all streams in the session will be included. + # @option opts [Hash] :headers (optional) A hash of key-value pairs of headers to be sent to your WebSocket server with each message, + # with a maximum length of 512 bytes. def connect(session_id, token, websocket_uri, opts = {}) response = @client.connect_websocket(session_id, token, websocket_uri, opts) end From f063bc9ee0198b126333fb7da08b30a7f645a152 Mon Sep 17 00:00:00 2001 From: superchilled Date: Tue, 21 Feb 2023 11:26:33 +0000 Subject: [PATCH 5/7] Renaming Audio Streamer to Audio Connector --- lib/opentok/websocket.rb | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/lib/opentok/websocket.rb b/lib/opentok/websocket.rb index ffc989f..875487b 100644 --- a/lib/opentok/websocket.rb +++ b/lib/opentok/websocket.rb @@ -1,10 +1,10 @@ require "opentok/client" -# An object that lets you work with Audio Streamer WebSocket connections. +# An object that lets you work with Audio Connector WebSocket connections. module OpenTok class WebSocket - # Starts an Audio Streamer WebSocket connection to send audio from a Vonage Video API session to a WebSocket URI. - # See the {https://tokbox.com/developer/guides/audio-streamer/ OpenTok Audio Streamer developer guide}. + # Starts an Audio Connector WebSocket connection to send audio from a Vonage Video API session to a WebSocket URI. + # See the {https://tokbox.com/developer/guides/audio-connector/ OpenTok Audio Connector developer guide}. # # @example # opts = { @@ -16,13 +16,13 @@ class WebSocket # } # response = opentok.websocket.connect(SESSIONID, TOKEN, "ws://service.com/wsendpoint", opts) # - # @param [String] session_id (required) The OpenTok session ID that includes the OpenTok streams you want to include in + # @param [String] session_id (required) The OpenTok session ID that includes the OpenTok streams you want to include in # the WebSocket stream. - # @param [String] token (required) The OpenTok token to be used for the Audio Streamer connection to the. OpenTok session. - # @param [String] websocket_uri (required) A publicly reachable WebSocket URI to be used for the destination of the audio + # @param [String] token (required) The OpenTok token to be used for the Audio Connector connection to the. OpenTok session. + # @param [String] websocket_uri (required) A publicly reachable WebSocket URI to be used for the destination of the audio # stream (such as "wss://service.com/ws-endpoint"). - # @param [Hash] opts (optional) A hash defining options for the Audio Streamer WebSocket connection. For example: - # @option opts [Array] :streams (optional) An array of stream IDs for the OpenTok streams you want to include in the WebSocket stream. + # @param [Hash] opts (optional) A hash defining options for the Audio Connector WebSocket connection. For example: + # @option opts [Array] :streams (optional) An array of stream IDs for the OpenTok streams you want to include in the WebSocket stream. # If you omit this property, all streams in the session will be included. # @option opts [Hash] :headers (optional) A hash of key-value pairs of headers to be sent to your WebSocket server with each message, # with a maximum length of 512 bytes. From 45ed2dd93cb30629c07ce0b171b1a8ec7755ce48 Mon Sep 17 00:00:00 2001 From: Jeff Swartz Date: Wed, 8 Mar 2023 12:20:18 -0800 Subject: [PATCH 6/7] README updates and corrections --- README.md | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 731cda1..71e499f 100644 --- a/README.md +++ b/README.md @@ -18,6 +18,7 @@ The OpenTok Ruby SDK provides methods for: * [Disconnecting clients from sessions](https://tokbox.com/developer/guides/moderation/rest/) * [Forcing clients in a session to disconnect or mute published audio](https://tokbox.com/developer/guides/moderation/) * Working with OpenTok [Experience Composers](https://tokbox.com/developer/guides/experience-composer) +* Working with OpenTok [Audio Connector](https://tokbox.com/developer/guides/audio-connector) ## Installation @@ -188,7 +189,10 @@ archive = opentok.archives.create session_id :output_mode => :individual The `:output_mode => :composed` setting (the default) causes all streams in the archive to be recorded to a single (composed) file. -For composed archives you can set the resolution of the archive, either "640x480" (SD landscape, the default), "1280x720" (HD landscape), "1920x1080" (FHD landscape), "480x640" (SD portrait), "720x1280" (HD portrait), or "1080x1920" (FHD portrait).. The `resolution` parameter is optional and could be included in the options +For composed archives you can set the resolution of the archive, either "640x480" +(SD landscape, the default), "1280x720" (HD landscape), "1920x1080" (FHD landscape), +"480x640" (SD portrait), "720x1280" (HD portrait), or "1080x1920" (FHD portrait). +The `resolution` parameter is optional and could be included in the options hash (second argument) of the `opentok.archives.create()` method. ```ruby @@ -495,6 +499,11 @@ You can stop an Experience Composer by calling the `opentok.renders.stop(render_ You can get information about Experience Composers by calling the `opentok.renders.find(render_id)` and `opentok.renders.list(options)` methods. +### Working with Audio Connector + +You can start an [Audio Connector](https://tokbox.com/developer/guides/audio-connect) WebSocket +by calling the `opentok.websocket.connect()` method. + ## Samples There are three sample applications included in this repository. To get going as fast as possible, clone the whole From 960a57986d45f5be16266576f200377616be32a1 Mon Sep 17 00:00:00 2001 From: superchilled Date: Thu, 9 Mar 2023 12:09:50 +0000 Subject: [PATCH 7/7] Updating changelog and bumping version number --- CHANGES.md | 4 ++++ README.md | 6 +++--- lib/opentok/version.rb | 2 +- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index c13acc4..c984f5a 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,3 +1,7 @@ +# 4.6.0 + +* Adds functionality for working with the Audio Connector feature [#247](https://github.com/opentok/OpenTok-Ruby-SDK/pull/247) + # 4.5.1 * Fixes issue with uninitialized constant by adding missing `require` statement [#256](https://github.com/opentok/OpenTok-Ruby-SDK/pull/256) diff --git a/README.md b/README.md index 71e499f..ef0a16c 100644 --- a/README.md +++ b/README.md @@ -326,7 +326,7 @@ For more information on archiving, see the ### Signaling -You can send a signal using the `opentok.signals.send(session_id, connection_id, opts)` method. +You can send a signal using the `opentok.signals.send(session_id, connection_id, opts)` method. If `connection_id` is nil or an empty string, then the signal is send to all valid connections in the session. @@ -461,7 +461,7 @@ You can cause a client to be forced to disconnect from a session by using the ### Forcing clients in a session to mute published audio -You can force the publisher of a specific stream to stop publishing audio using the +You can force the publisher of a specific stream to stop publishing audio using the `opentok.streams.force_mute(session_id, stream_id)` method. You can force the publisher of all streams in a session (except for an optional list of streams) @@ -501,7 +501,7 @@ and `opentok.renders.list(options)` methods. ### Working with Audio Connector -You can start an [Audio Connector](https://tokbox.com/developer/guides/audio-connect) WebSocket +You can start an [Audio Connector](https://tokbox.com/developer/guides/audio-connector) WebSocket by calling the `opentok.websocket.connect()` method. ## Samples diff --git a/lib/opentok/version.rb b/lib/opentok/version.rb index 641e8e2..70bc320 100644 --- a/lib/opentok/version.rb +++ b/lib/opentok/version.rb @@ -1,4 +1,4 @@ module OpenTok # @private - VERSION = '4.5.1' + VERSION = '4.6.0' end