Skip to content

Commit

Permalink
Add Terminal Verbs (#76)
Browse files Browse the repository at this point in the history
* Add Terminal Verbs

* update bridge and add unit test

* add unit test for root verb module

* bridge test

* bridge comment

* update conference

* add terminal verb unit test

* verb test

* all attributes in bridge test

* add conference and test

* add conference to sdk

* remove backslash escaping

* test number

* use real booleans for conference

* add comment to bridge

* add pause and test

* conference timeout is a Number

* add forward and test

* add explicit empty hash to tag

* add hangup and test

* add pause_recording and test

* add phone_number and test

* add play_audio and test

* comments for params

* add record and test

* add redirect and test

* add resume_recording and test

* add ring and test

* add send_dtmf and test

* add sip_uri and test

* add speak_sentence and test

* add start_gather and test

* add start_recording and test

* add stop_gather and test

* add stop_recording and test

* add stop_stream and test

* _name for stop_stream

* add stream_param and test

* add test for tag verb

* turn ssml regex into constants

* test decimals in ring verb

* test decimals in conference

* comment clean up

* Add Non-Terminal Verbs (#77)

* Add Non-Terminal Verbs

* merge SWI-1730

* update gather and add tests

* period in gather comment

* add start_stream and test

* add transfer and test

* remove add_verb method

* update response and bxml class tests

* update non-terminal verbs and tests

* refactor base verb classes (#80)
  • Loading branch information
ckoegel committed Feb 28, 2023
1 parent 65a6220 commit ce88dc4
Show file tree
Hide file tree
Showing 59 changed files with 1,660 additions and 455 deletions.
27 changes: 26 additions & 1 deletion lib/bandwidth-sdk.rb
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,32 @@
require 'bandwidth-sdk/models/bxml/bxml'
require 'bandwidth-sdk/models/bxml/response'
require 'bandwidth-sdk/models/bxml/verb'
require 'bandwidth-sdk/models/bxml/terminal_verb'
require 'bandwidth-sdk/models/bxml/nestable_verb'
require 'bandwidth-sdk/models/bxml/verbs/bridge'
require 'bandwidth-sdk/models/bxml/verbs/conference'
require 'bandwidth-sdk/models/bxml/verbs/forward'
require 'bandwidth-sdk/models/bxml/verbs/gather'
require 'bandwidth-sdk/models/bxml/verbs/hangup'
require 'bandwidth-sdk/models/bxml/verbs/pause_recording'
require 'bandwidth-sdk/models/bxml/verbs/pause'
require 'bandwidth-sdk/models/bxml/verbs/phone_number'
require 'bandwidth-sdk/models/bxml/verbs/play_audio'
require 'bandwidth-sdk/models/bxml/verbs/record'
require 'bandwidth-sdk/models/bxml/verbs/redirect'
require 'bandwidth-sdk/models/bxml/verbs/resume_recording'
require 'bandwidth-sdk/models/bxml/verbs/ring'
require 'bandwidth-sdk/models/bxml/verbs/send_dtmf'
require 'bandwidth-sdk/models/bxml/verbs/sip_uri'
require 'bandwidth-sdk/models/bxml/verbs/speak_sentence'
require 'bandwidth-sdk/models/bxml/verbs/start_gather'
require 'bandwidth-sdk/models/bxml/verbs/start_recording'
require 'bandwidth-sdk/models/bxml/verbs/start_stream'
require 'bandwidth-sdk/models/bxml/verbs/stop_gather'
require 'bandwidth-sdk/models/bxml/verbs/stop_recording'
require 'bandwidth-sdk/models/bxml/verbs/stop_stream'
require 'bandwidth-sdk/models/bxml/verbs/stream_param'
require 'bandwidth-sdk/models/bxml/verbs/tag'
require 'bandwidth-sdk/models/bxml/verbs/transfer'

# APIs
require 'bandwidth-sdk/api/calls_api'
Expand Down
50 changes: 50 additions & 0 deletions lib/bandwidth-sdk/models/bxml/nestable_verb.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
require 'ox'

module Bandwidth
module Bxml
module NestableVerb
include Bandwidth::Bxml::Verb

# Initializer
# @param tag [String] Name of the XML element.
# @param content [String] XML element content. Defaults to nil.
# @param nested_verbs [Array] XML element children. Defaults to an empty array.
# @param attributes [Hash] The attributes to add to the element. Defaults to an empty hash.
def initialize(tag, content = nil, nested_verbs = [], attributes = {})
@tag = tag
@content = content
@nested_verbs = nested_verbs
@attributes = attributes
@attribute_map = []
end

# Generate an XML element for the verb
# @return [Node] The XML element.
def generate_xml
root = Ox::Element.new(@tag)
if @content
root << @content
end

if @nested_verbs.length > 0
@nested_verbs.each do |verb|
root << verb.generate_xml
end
end

if !@attributes.empty?
@attributes.each do |key, value|
if @attribute_map.include? key.to_sym
root[@attribute_map[key.to_sym]] = value
else
raise NoMethodError.new("attribute '#{key}' is not a valid attribute for this verb")
end
end
end

return root
end

end
end
end
7 changes: 5 additions & 2 deletions lib/bandwidth-sdk/models/bxml/root.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

module Bandwidth
module Bxml
SPEAK_SENTENCE_REGEX = /<SpeakSentence.*?>(.*?)<\/SpeakSentence>/
SSML_REGEX = /&lt;([a-zA-Z\/\/].*?)&gt;/

module Root
# Initializer
# @param tag [String] Name of the XML element.
Expand All @@ -25,7 +28,6 @@ def generate_xml
end
xml << root
return xml
# xml.target!().gsub(SPEAK_SENTENCE_REGEX){|s|s.gsub(SSML_REGEX, '<\1>')}
end

# Add a verb to the nested verbs array
Expand All @@ -37,7 +39,8 @@ def add_verb(nested_verbs)
# Return BXML representaion of this response
# @return [String] The XML response in string format.
def to_bxml
return Ox.dump(generate_xml)
bxml = Ox.dump(generate_xml)
return bxml.gsub(SPEAK_SENTENCE_REGEX) { |text| text.gsub(SSML_REGEX, '<\1>')}
end
end
end
Expand Down
21 changes: 0 additions & 21 deletions lib/bandwidth-sdk/models/bxml/terminal_verb.rb

This file was deleted.

16 changes: 1 addition & 15 deletions lib/bandwidth-sdk/models/bxml/verb.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,10 @@ module Verb
# Initializer
# @param tag [String] Name of the XML element.
# @param content [String] XML element content. Defaults to nil.
# @param nested_verbs [Array] XML element children. Defaults to an empty array.
# @param attributes [Hash] The attributes to add to the element. Defaults to an empty hash.
def initialize(tag, content = nil, nested_verbs = [], attributes = {})
def initialize(tag, content = nil, attributes = {})
@tag = tag
@content = content
@nested_verbs = nested_verbs
@attributes = attributes
@attribute_map = []
end
Expand All @@ -30,12 +28,6 @@ def generate_xml
root << @content
end

if @nested_verbs.length > 0
@nested_verbs.each do |verb|
root << verb.generate_xml
end
end

if !@attributes.empty?
@attributes.each do |key, value|
if @attribute_map.include? key.to_sym
Expand All @@ -49,12 +41,6 @@ def generate_xml
return root
end

# Add a verb to the nested verbs array
# @param nested_verbs [Verb] or [Array<Verb>] Verb or verbs to add to the array.
def add_verb(nested_verbs)
@nested_verbs.push(*nested_verbs)
end

# Return BXML representaion of this element
# @return [String] The XML element in string format.
def to_bxml
Expand Down
46 changes: 24 additions & 22 deletions lib/bandwidth-sdk/models/bxml/verbs/bridge.rb
Original file line number Diff line number Diff line change
@@ -1,27 +1,29 @@
require_relative 'xml_verb'

module Bandwidth
module Voice
# The Bridge verb allows you to connect 2 calls
module Bandwidth
module Bxml
class Bridge
include XmlVerb
include Bandwidth::Bxml::Verb

def to_bxml(xml)
xml.Bridge(call_id, compact_hash({
'bridgeCompleteUrl' => bridge_complete_url,
'bridgeCompleteMethod' => bridge_complete_method,
'bridgeTargetCompleteUrl' => bridge_target_complete_url,
'bridgeTargetCompleteMethod' => bridge_target_complete_method,
'username' => username,
'password' => password,
'tag' => tag,
'bridgeCompleteFallbackUrl' => bridge_complete_fallback_url,
'bridgeCompleteFallbackMethod' => bridge_complete_fallback_method,
'bridgeTargetCompleteFallbackUrl' => bridge_target_complete_fallback_url,
'bridgeTargetCompleteFallbackMethod' => bridge_target_complete_fallback_method,
'fallbackUsername' => fallback_username,
'fallbackPassword' => fallback_password
}))
# Initializer
# @param target_call [String] The callId of the call to be bridged.
# @param attributes [Hash] The attributes to add to the element. Defaults to an empty hash.
def initialize(target_call, attributes = {})
super("Bridge", target_call, attributes)

@attribute_map = {
bridge_complete_url: 'bridgeCompleteUrl', # Optional [String]: URL to send the Bridge Complete event to and request new BXML. If this attribute is specified, then Verbs following the <Bridge> verb will be ignored and the BXML returned in this webhook is executed on the call. If this attribute is not specified then no webhook will be sent, and execution of the verbs following the <Bridge> verb continues. May be a relative URL. Defaults to None.
bridge_complete_method: 'bridgeCompleteMethod', # Optional [String]: The HTTP method to use for the request to bridgeCompleteUrl. GET or POST. Default value is POST.
bridge_complete_fallback_url: 'bridgeCompleteFallbackUrl', # Optional [String]: A fallback url which, if provided, will be used to retry the Bridge Complete webhook delivery in case bridgeCompleteUrl fails to respond. Defaults to None.
bridge_complete_fallback_method: 'bridgeCompleteFallbackMethod', # Optional [String]: The HTTP method to use to deliver the Bridge Complete webhook to bridgeCompleteFallbackUrl. GET or POST. Default value is POST.
bridge_target_complete_url: 'bridgeTargetCompleteUrl', # Optional [String]: URL to send the Bridge Target Complete event to and request new BXML. If this attribute is specified, then the BXML returned in this webhook is executed on the target call. If this attribute is not specified then no webhook will be sent, and the target call will be hung up. May be a relative URL. Defaults to None.
bridge_target_complete_method: 'bridgeTargetCompleteMethod', # Optional [String]: The HTTP method to use for the request to bridgeTargetCompleteUrl. GET or POST. Default value is POST.
bridge_target_complete_fallback_url: 'bridgeTargetCompleteFallbackUrl', # Optional [String]: A fallback url which, if provided, will be used to retry the Bridge Target Complete webhook delivery in case bridgeTargetCompleteUrl fails to respond. Defaults to None.
bridge_target_complete_fallback_method: 'bridgeTargetCompleteFallbackMethod', # Optional [String]: The HTTP method to use to deliver the Bridge Target Complete webhook to bridgeTargetCompleteFallbackUrl. GET or POST. Default value is POST.
username: 'username', # Optional [String]: The username to send in the HTTP request to bridgeCompleteUrl and to bridgeTargetCompleteUrl. Defaults to None.
password: 'password', # Optional [String]: The password to send in the HTTP request to bridgeCompleteUrl and to bridgeTargetCompleteUrl. Defaults to None.
fallback_username: 'fallbackUsername', # Optional [String]: The username to send in the HTTP request to bridgeCompleteFallbackUrl and to bridgeTargetCompleteFallbackUrl. Defaults to None.
fallback_password: 'fallbackPassword', # Optional [String]: The password to send in the HTTP request to bridgeCompleteFallbackUrl and to bridgeTargetCompleteFallbackUrl. Defaults to None.
tag: 'tag', # Optional [String]: A custom string that will be sent with the bridgeComplete webhook and all future webhooks of the call unless overwritten by a future tag attribute or <Tag> verb, or cleared. May be cleared by setting tag="". Max length 256 characters. Defaults to None.
}
end
end
end
Expand Down
51 changes: 25 additions & 26 deletions lib/bandwidth-sdk/models/bxml/verbs/conference.rb
Original file line number Diff line number Diff line change
@@ -1,32 +1,31 @@
require_relative 'xml_verb'

module Bandwidth
module Voice
# The Conference verb is used to add callees to conferences
module Bandwidth
module Bxml
class Conference
include XmlVerb
include Bandwidth::Bxml::Verb

def to_bxml(xml)
if not call_ids_to_coach.nil?
coach_ids = call_ids_to_coach.instance_of?(String) ? call_ids_to_coach : call_ids_to_coach.join(",")
else
coach_ids = nil
end
xml.Conference(conference_name, compact_hash({
'mute' => mute,
'hold' => hold,
'callIdsToCoach' => coach_ids,
'conferenceEventUrl' => conference_event_url,
'conferenceEventMethod' => conference_event_method,
'username' => username,
'password' => password,
'tag' => tag,
'conferenceEventFallbackUrl' => conference_event_fallback_url,
'conferenceEventFallbackMethod' => conference_event_fallback_method,
'fallbackUsername' => fallback_username,
'fallbackPassword' => fallback_password
}))
# Initializer
# @param name [String] The name of the conference. Can contain up to 100 characters of letters, numbers, and the symbols -, _, and .
# @param attributes [Hash] The attributes to add to the element. Defaults to an empty hash.
def initialize(name, attributes = {})
super("Conference", name, attributes)

@attribute_map = {
mute: 'mute', # Optional [Boolean]: A boolean value to indicate whether the member should be on mute in the conference. When muted, a member can hear others speak, but others cannot hear them speak. Defaults to false.
hold: 'hold', # Optional [Boolean]: A boolean value to indicate whether the member should be on hold in the conference. When on hold, a member cannot hear others, and they cannot be heard. Defaults to false.
call_ids_to_coach: 'callIdsToCoach', # Optional [String]: A comma-separated list of call ids to coach. When a call joins a conference with this attribute set, it will coach the listed calls. Those calls will be able to hear and be heard by the coach, but other calls in the conference will not hear the coach.
conference_event_url: 'conferenceEventUrl', # Optional [String]: URL to send Conference events to. The URL, method, username, and password are set by the BXML document that creates the conference, and all events related to that conference will be delivered to that same endpoint. If more calls join afterwards and also have this property (or any other webhook related properties like username and password), they will be ignored and the original webhook information will be used. This URL may be a relative endpoint.
conference_event_method: 'conferenceEventMethod', # Optional [String]: The HTTP method to use for the request to conferenceEventUrl. GET or POST. Default value is POST.
conference_event_fallback_url: 'conferenceEventFallbackUrl', # Optional [String]: A fallback url which, if provided, will be used to retry the conference webhook deliveries in case conferenceEventUrl fails to respond.
conference_event_fallback_method: 'conferenceEventFallbackMethod', # Optional [String]: The HTTP method to use to deliver the conference webhooks to conferenceEventFallbackUrl. GET or POST. Default value is POST.
username: 'username', # Optional [String]: The username to send in the HTTP request to conferenceEventUrl.
password: 'password', # Optional [String]: The password to send in the HTTP request to conferenceEventUrl.
fallback_username: 'fallbackUsername', # Optional [String]: The username to send in the HTTP request to conferenceEventFallbackUrl.
fallback_password: 'fallbackPassword', # Optional [String]: The password to send in the HTTP request to conferenceEventFallbackUrl.
tag: 'tag', # Optional [String]: A custom string that will be sent with this and all future callbacks unless overwritten by a future tag attribute or <Tag> verb, or cleared. May be cleared by setting tag="". Max length 256 characters. Defaults to None.
callback_timeout: 'callbackTimeout', # Optional [Number]: This is the timeout (in seconds) to use when delivering webhooks for the conference. If not set, it will inherit the webhook timeout from the call that creates the conference. Can be any numeric value (including decimals) between 1 and 25.
}
end
end
end
end

30 changes: 17 additions & 13 deletions lib/bandwidth-sdk/models/bxml/verbs/forward.rb
Original file line number Diff line number Diff line change
@@ -1,17 +1,21 @@
require_relative 'xml_verb'

module Bandwidth
module Voice
module Bandwidth
module Bxml
class Forward
include XmlVerb
def to_bxml(xml)
xml.Forward(compact_hash({
'to' => to,
'from' => from,
'callTimeout' => call_timeout,
'diversionTreatment' => diversion_treatment,
'diversionReason' => diversion_reason
}))
include Bandwidth::Bxml::Verb

# Initializer
# @param attributes [Hash] The attributes to add to the element. Defaults to an empty hash.
def initialize(attributes = {})
super("Forward", nil, attributes)

@attribute_map = {
to: 'to', # [String]: The phone number destination of the call.
from: 'from', # Optional [String]: The phone number that the recipient will receive the call from.
call_timeout: 'callTimeout', # Optional [Number]: The number of seconds to wait before timing out the call.
diversion_treatment: 'diversionTreatment', # Optional [String]: Can be any of the following: - none: No diversion headers are sent on the outbound leg of the transferred call. - propagate: Copy the Diversion header from the inbound leg to the outbound leg. Ignored if there is no Diversion header present on the inbound leg. - stack: After propagating any Diversion header from the inbound leg to the outbound leg, stack on top another Diversion header based on the Request-URI of the inbound call. If diversionTreatment is not specified, no diversion header will be included for the transfer even if one came with the inbound call. Defaults to None.
diversion_reason: 'diversionReason', # Optional [String]: Can be any of the following values: unknown, user-busy, no-answer, unavailable, unconditional, time-of-day, do-not-disturb, deflection, follow-me, out-of-service, away. This parameter is considered only when diversionTreatment is set to stack. Defaults to None.
uui: 'uui', # Optional [String]: The value of the User-To-User header to send within the outbound INVITE when forwarding to a SIP URI. Must include the encoding parameter as specified in RFC 7433. Only base64 and jwt encoding are currently allowed. This value, including the encoding specifier, may not exceed 256 characters.
}
end
end
end
Expand Down
Loading

0 comments on commit ce88dc4

Please sign in to comment.