Skip to content
Open

Test #194

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
# Change Log


## [4.31.0](https://github.com/plivo/plivo-go/tree/v4.31.0) (2022-09-29)
**Feature - Audio Streaming**
- Added functionality to start, stop and fetch audio streams

## [4.30.1](https://github.com/plivo/plivo-go/tree/v4.30.1) (2022-09-20)
**stability - faraday upgrade**
- faraday version upgrade
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ The Plivo Ruby SDK makes it simpler to integrate communications into your Ruby a
Add this line to your application's Gemfile:

```ruby
gem 'plivo', '>= 4.30.1'
gem 'plivo', '>= 4.31.0'
```

And then execute:
Expand Down
115 changes: 115 additions & 0 deletions lib/plivo/resources/calls.rb
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,73 @@ def cancel_request
@_client.send_request(resource_path, 'DELETE', nil, nil, false , is_voice_request: @_is_voice_request)
end

def start_stream(service_url, options = nil)
valid_param?(:service_url, service_url, [String, Symbol], true)
if options.nil?
return perform_action('Stream', 'POST', { service_url: service_url }, true)
end

valid_param?(:options, options, Hash, true)

params = { service_url: service_url }

if options.key?(:bidirectional) &&
valid_param?(:bidirectional, options[:bidirectional], [TrueClass, FalseClass], false )
params[:bidirectional] = options[:bidirectional]
end

if options.key?(:audio_track) &&
valid_param?(:audio_track, options[:audio_track],
[String, Symbol], false, %w[inbound outbound both])
params[:audio_track] = options[:audio_track]
end

if options.key?(:stream_timeout) &&
valid_param?(:stream_timeout, options[:stream_timeout], Integer, false)
params[:stream_timeout] = options[:stream_timeout]
end

if options.key?(:status_callback_url) &&
valid_param?(:status_callback_url, options[:status_callback_url], [String, Symbol], false)
params[:status_callback_url] = options[:status_callback_url]
end

if options.key?(:status_callback_method) &&
valid_param?(:status_callback_method, options[:status_callback_method],
[String, Symbol], false, %w[GET POST get post])
params[:status_callback_method] = options[:status_callback_method]
end

if options.key?(:content_type) &&
valid_param?(:content_type, options[:content_type], [String, Symbol, Integer], false)
params[:content_type] = options[:content_type]
end

if options.key?(:extra_headers) &&
valid_param?(:extra_headers, options[:extra_headers], [String, Symbol, Integer], false)
params[:extra_headers] = options[:extra_headers]
end
perform_action('Stream', 'POST', params, true)
end

def stop_all_streams
perform_action('Stream', 'DELETE', nil, false)
end

def stop_stream(stream_id)
valid_param?(:stream_id, stream_id, [String, Symbol, Integer], true)
perform_action('Stream/' + stream_id, 'DELETE', nil, false)
end

def get_all_streams
perform_action('Stream', 'GET', nil, true )
end

def get_stream(stream_id)
valid_param?(:stream_id, stream_id, [String, Symbol, Integer], true)
perform_action('Stream/' + stream_id, 'GET', nil, true)
end

def to_s
call_details = {
answer_time: @answer_time,
Expand Down Expand Up @@ -575,6 +642,54 @@ def cancel_request(call_uuid)
valid_param?(:call_uuid, call_uuid, [String, Symbol], true)
Call.new(@_client, resource_id: call_uuid).cancel_request
end

# @param [String] service_url
# @param [Hash] options
# @option options [Boolean] :bidirectional
# @option options [String] :audio_track
# @option options [Int] :stream_timeout
# @option options [String] :status_callback_url
# @option options [String] :status_callback_method
# @option options [String] :content_type
# @option options [String] :extra_headers
def start_stream(call_uuid, service_url, options = {})
valid_param?(:call_uuid, call_uuid, [String, Symbol], true)
response = Call.new(@_client, resource_id: call_uuid).start_stream(service_url, options)
return Base::Response.new(Hash["api_id" => response.api_id,
"stream_id" => response.stream_id,
"message" => response.message])
end

def stop_all_streams(call_uuid)
valid_param?(:call_uuid, call_uuid, [String, Symbol], true )
Call.new(@_client, resource_id: call_uuid).stop_all_streams
end

def stop_stream(call_uuid, stream_id)
valid_param?(:call_uuid, call_uuid, [String, Symbol], true )
Call.new(@_client, resource_id: call_uuid).stop_stream(stream_id)
end

def get_all_streams(call_uuid)
valid_param?(:call_uuid, call_uuid, [String, Symbol], true )
response = Call.new(@_client, resource_id: call_uuid).get_all_streams
return Base::Response.new(Hash["api_id" => response.api_id,
"meta" => response.meta,
"objects" => response.objects])
end

def get_stream(call_uuid, stream_id)
valid_param?(:call_uuid, call_uuid, [String, Symbol], true )
response = Call.new(@_client, resource_id: call_uuid).get_stream(stream_id)
return Base::Response.new(Hash["api_id" => response.api_id,
"call_uuid" => response.call_uuid,
"end_time" => response.end_time,
"service_url" => response.service_url,
"start_time" => response.start_time,
"status" => response.status,
"status_callback_url" => response.status_callback_url,
"stream_id" => response.stream_id])
end
end
end
end
2 changes: 1 addition & 1 deletion lib/plivo/version.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
module Plivo
VERSION = "4.30.1".freeze
VERSION = "4.31.0".freeze
end
1 change: 1 addition & 0 deletions lib/plivo/xml.rb
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
require_relative 'xml/plivo_xml'
require_relative 'xml/multipartycall'
require_relative 'xml/cont'
require_relative 'xml/stream'
include Plivo::Exceptions

module Plivo
Expand Down
4 changes: 2 additions & 2 deletions lib/plivo/xml/plivo_xml.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@ def initialize(response = nil)
end

def to_xml
'<?xml version="1.0" encoding="utf-8" ?>' + @response.to_xml
'<?xml version="1.0" encoding="utf-8" ?>' + @response.to_xml.gsub("&quot;", "\"")
end

def to_s
'<?xml version="1.0" encoding="utf-8" ?>' + @response.to_s
'<?xml version="1.0" encoding="utf-8" ?>' + @response.to_s.gsub("&quot;", "\"")
end
end
end
Expand Down
2 changes: 1 addition & 1 deletion lib/plivo/xml/response.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ module Plivo
module XML
class Response < Element
@nestables = %w[Speak Play GetDigits GetInput Record Dial Message
Redirect Wait Hangup PreAnswer Conference DTMF MultiPartyCall]
Redirect Wait Hangup PreAnswer Conference DTMF MultiPartyCall Stream]
@valid_attributes = []

def initialize
Expand Down
41 changes: 41 additions & 0 deletions lib/plivo/xml/stream.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
module Plivo
module XML
class Stream < Element
@nestables = []
@valid_attributes = %w[bidirectional audioTrack streamTimeout statusCallbackUrl
statusCallbackMethod contentType extraHeaders]

SUPPORTED_BIDIRECTIONAL=%w(true false)
SUPPORTED_AUDIOTRACK=%w(inbound outbound both)
SUPPORTED_CALLBACKMETHOD=%w(GET POST)

def initialize(body, attributes = {})
if attributes && attributes[:extraHeaders]
input = attributes[:extraHeaders]
headers = Hash.new
input.each do |keys, value|
if keys.to_s.end_with?("X-PH")
headers[keys.to_s] = value
else
headers[keys.to_s + "X-PH"] = value
end
end
headersString = headers.to_json
puts headersString
attributes[:extraHeaders] = headersString
end
if attributes[:bidirectional] && !SUPPORTED_BIDIRECTIONAL.include?(attributes[:bidirectional])
raise PlivoXMLError, "<Stream> bidirectional #{attributes[:bidirectional]} is not valid."
end
if attributes[:audioTrack] && !SUPPORTED_AUDIOTRACK.include?(attributes[:audioTrack])
raise PlivoXMLError, "<Stream> audioTrack #{attributes[:audioTrack]} is not valid."
end
if attributes[:statusCallbackMethod] && !SUPPORTED_CALLBACKMETHOD.include?(attributes[:statusCallbackMethod].upcase)
raise PlivoXMLError, "<Stream> statusCallbackMethod #{attributes[:statusCallbackMethod]} is not valid."
end
raise PlivoXMLError, 'No text set for Stream' unless body
super(body, attributes)
end
end
end
end
5 changes: 5 additions & 0 deletions spec/mocks/streamStartCreateResponse.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"message": "stream started",
"api_id": "69487be8-3ef4-11e7-a51d-0245fa790d9e",
"stream_id": "69487be8-3ef4-11e7-a51d-0245fa790d77"
}
4 changes: 4 additions & 0 deletions spec/mocks/streamStartCreateResponses.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"message": "stream started",
"api_id": "69487be8-3ef4-11e7-a51d-0245fa790d9e"
}
16 changes: 16 additions & 0 deletions spec/resource_calls_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -327,4 +327,20 @@ def to_json_list_live(list_object)
method: 'DELETE',
data: nil)
end

it 'start stream' do
id = 'MAXXXXXXXXXXXXXXXXXX'
contents = File.read(Dir.pwd + '/spec/mocks/streamStartCreateResponse.json')
response = File.read(Dir.pwd + '/spec/mocks/streamStartCreateResponses.json')
mock(202, JSON.parse(contents))
expect(JSON.parse(to_json_update(@api.calls
.start_stream(id,
'wss://mystream.ngrok.io/audiostream'))))
.to eql(JSON.parse(response))
compare_requests(uri: '/v1/Account/MAXXXXXXXXXXXXXXXXXX/Call/' + id + '/Stream/',
method: 'POST',
data: {
service_url: 'wss://mystream.ngrok.io/audiostream'
})
end
end
9 changes: 8 additions & 1 deletion spec/xml_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -108,8 +108,15 @@
statusCallbackEvents: 'participant-speak-events, participant-digit-input-events, add-participant-api-events, participant-state-changes, mpc-state-changes'
)

resp.addStream('Starting a new stream.')
resp.addStream('Starting a new stream with params.',
{
bidirectional: 'true',
audioTrack: 'outbound'
})

xml = Plivo::XML::PlivoXML.new(resp)
puts xml.to_xml
expect(xml.to_xml).to eql("<?xml version=\"1.0\" encoding=\"utf-8\" ?><Response><Conference callbackMethod='POST' callbackUrl='http://foo.com/confevents/' digitsMatch='#0,90,000'>My room</Conference><Dial confirmKey='3' confirmSound='http://foo.com/sound/'><Number sendDigits='wwww2410'>18217654321</Number><User sendDigits='wwww2410'>sip:john1234@phone.plivo.com</User></Dial><Dial action='http://foo.com/dial_action/' timeout='20'><Number>18217654321</Number></Dial><Dial><Number>15671234567</Number></Dial><DTMF>12345</DTMF><GetDigits action='http://ww.foo.com/gather_pin/' method='POST'><Speak>Enter PIN number.</Speak></GetDigits><Speak>Input not recieved.</Speak><GetInput action='http://ww.foo.com/gather_feedback/' method='POST'><Speak>Tell us more about your experience.</Speak></GetInput><Speak>Statement not recieved.</Speak><Hangup reason='rejected' schedule='60'/><Speak loop='0'>Call will hangup after a min.</Speak><Message callbackMethod='POST' callbackUrl='http://foo.com/sms_status/' dst='15671234567' src='12023222222' type='sms'>Hi, message from Plivo.</Message><Play>https://amazonaws.com/Trumpet.mp3</Play><PreAnswer><Speak>This call will cost $2 a min.</Speak></PreAnswer><Speak>Thanks for dropping by.</Speak><Record action='http://foo.com/get_recording/' redirect='false' startOnDialAnswer='true'/><Dial><Number>15551234567</Number></Dial><Speak>Leave message after the beep.</Speak><Record action='http://foo.com/get_recording/' finishOnKey='*' maxLength='30'/><Speak>Recording not received.</Speak><Speak>Your call is being transferred.</Speak><Redirect>http://foo.com/redirect/</Redirect><Speak loop='3'>Go green, go plivo.</Speak><Speak>I will wait 7 seconds starting now!</Speak><Wait length='7'/><Speak>I just waited 7 seconds.</Speak><Wait beep='true' length='120'/><Play>https://s3.amazonaws.com/abc.mp3</Play><Wait length='10'/><Speak>Hello</Speak><Wait length='10' minSilence='3000' silence='true'/><Speak>Hello, welcome to the Jungle.</Speak><MultiPartyCall agentHoldMusicMethod='GET' coachMode='true' customerHoldMusicMethod='GET' endMpcOnExit='false' enterSound='beep:1' enterSoundMethod='GET' exitSound='beep:2' exitSoundMethod='GET' hold='false' maxDuration='1000' maxParticipants='10' mute='false' onExitActionMethod='POST' record='false' recordFileFormat='mp3' recordMinMemberCount='1' recordingCallbackMethod='GET' relayDTMFInputs='false' role='Agent' startMpcOnEnter='true' startRecordingAudioMethod='GET' statusCallbackEvents='participant-speak-events, participant-digit-input-events, add-participant-api-events, participant-state-changes, mpc-state-changes' statusCallbackMethod='POST' stayAlone='false' stopRecordingAudioMethod='GET' waitMusicMethod='GET'>Nairobi</MultiPartyCall></Response>")
expect(xml.to_xml).to eql("<?xml version=\"1.0\" encoding=\"utf-8\" ?><Response><Conference callbackMethod='POST' callbackUrl='http://foo.com/confevents/' digitsMatch='#0,90,000'>My room</Conference><Dial confirmKey='3' confirmSound='http://foo.com/sound/'><Number sendDigits='wwww2410'>18217654321</Number><User sendDigits='wwww2410'>sip:john1234@phone.plivo.com</User></Dial><Dial action='http://foo.com/dial_action/' timeout='20'><Number>18217654321</Number></Dial><Dial><Number>15671234567</Number></Dial><DTMF>12345</DTMF><GetDigits action='http://ww.foo.com/gather_pin/' method='POST'><Speak>Enter PIN number.</Speak></GetDigits><Speak>Input not recieved.</Speak><GetInput action='http://ww.foo.com/gather_feedback/' method='POST'><Speak>Tell us more about your experience.</Speak></GetInput><Speak>Statement not recieved.</Speak><Hangup reason='rejected' schedule='60'/><Speak loop='0'>Call will hangup after a min.</Speak><Message callbackMethod='POST' callbackUrl='http://foo.com/sms_status/' dst='15671234567' src='12023222222' type='sms'>Hi, message from Plivo.</Message><Play>https://amazonaws.com/Trumpet.mp3</Play><PreAnswer><Speak>This call will cost $2 a min.</Speak></PreAnswer><Speak>Thanks for dropping by.</Speak><Record action='http://foo.com/get_recording/' redirect='false' startOnDialAnswer='true'/><Dial><Number>15551234567</Number></Dial><Speak>Leave message after the beep.</Speak><Record action='http://foo.com/get_recording/' finishOnKey='*' maxLength='30'/><Speak>Recording not received.</Speak><Speak>Your call is being transferred.</Speak><Redirect>http://foo.com/redirect/</Redirect><Speak loop='3'>Go green, go plivo.</Speak><Speak>I will wait 7 seconds starting now!</Speak><Wait length='7'/><Speak>I just waited 7 seconds.</Speak><Wait beep='true' length='120'/><Play>https://s3.amazonaws.com/abc.mp3</Play><Wait length='10'/><Speak>Hello</Speak><Wait length='10' minSilence='3000' silence='true'/><Speak>Hello, welcome to the Jungle.</Speak><MultiPartyCall agentHoldMusicMethod='GET' coachMode='true' customerHoldMusicMethod='GET' endMpcOnExit='false' enterSound='beep:1' enterSoundMethod='GET' exitSound='beep:2' exitSoundMethod='GET' hold='false' maxDuration='1000' maxParticipants='10' mute='false' onExitActionMethod='POST' record='false' recordFileFormat='mp3' recordMinMemberCount='1' recordingCallbackMethod='GET' relayDTMFInputs='false' role='Agent' startMpcOnEnter='true' startRecordingAudioMethod='GET' statusCallbackEvents='participant-speak-events, participant-digit-input-events, add-participant-api-events, participant-state-changes, mpc-state-changes' statusCallbackMethod='POST' stayAlone='false' stopRecordingAudioMethod='GET' waitMusicMethod='GET'>Nairobi</MultiPartyCall><Stream>Starting a new stream.</Stream><Stream audioTrack='outbound' bidirectional='true'>Starting a new stream with params.</Stream></Response>")
end
end