punchblock 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.document +5 -0
- data/.gitignore +12 -0
- data/.rspec +3 -0
- data/Gemfile +2 -0
- data/LICENSE.txt +20 -0
- data/README.markdown +31 -0
- data/Rakefile +23 -0
- data/assets/ozone/ask-1.0.xsd +56 -0
- data/assets/ozone/conference-1.0.xsd +17 -0
- data/assets/ozone/ozone-1.0.xsd +127 -0
- data/assets/ozone/say-1.0.xsd +24 -0
- data/assets/ozone/transfer-1.0.xsd +32 -0
- data/bin/punchblock-console +125 -0
- data/lib/punchblock/command/accept.rb +30 -0
- data/lib/punchblock/command/answer.rb +30 -0
- data/lib/punchblock/command/dial.rb +88 -0
- data/lib/punchblock/command/hangup.rb +25 -0
- data/lib/punchblock/command/join.rb +81 -0
- data/lib/punchblock/command/mute.rb +7 -0
- data/lib/punchblock/command/redirect.rb +49 -0
- data/lib/punchblock/command/reject.rb +61 -0
- data/lib/punchblock/command/unjoin.rb +50 -0
- data/lib/punchblock/command/unmute.rb +7 -0
- data/lib/punchblock/command.rb +16 -0
- data/lib/punchblock/command_node.rb +46 -0
- data/lib/punchblock/component/input.rb +320 -0
- data/lib/punchblock/component/output.rb +449 -0
- data/lib/punchblock/component/record.rb +216 -0
- data/lib/punchblock/component/tropo/ask.rb +197 -0
- data/lib/punchblock/component/tropo/conference.rb +328 -0
- data/lib/punchblock/component/tropo/say.rb +113 -0
- data/lib/punchblock/component/tropo/transfer.rb +178 -0
- data/lib/punchblock/component/tropo.rb +12 -0
- data/lib/punchblock/component.rb +73 -0
- data/lib/punchblock/connection.rb +209 -0
- data/lib/punchblock/core_ext/blather/stanza/presence.rb +11 -0
- data/lib/punchblock/core_ext/blather/stanza.rb +26 -0
- data/lib/punchblock/dsl.rb +46 -0
- data/lib/punchblock/event/answered.rb +7 -0
- data/lib/punchblock/event/complete.rb +65 -0
- data/lib/punchblock/event/dtmf.rb +19 -0
- data/lib/punchblock/event/end.rb +15 -0
- data/lib/punchblock/event/info.rb +15 -0
- data/lib/punchblock/event/joined.rb +50 -0
- data/lib/punchblock/event/offer.rb +29 -0
- data/lib/punchblock/event/ringing.rb +7 -0
- data/lib/punchblock/event/unjoined.rb +50 -0
- data/lib/punchblock/event.rb +16 -0
- data/lib/punchblock/generic_connection.rb +18 -0
- data/lib/punchblock/has_headers.rb +34 -0
- data/lib/punchblock/header.rb +47 -0
- data/lib/punchblock/media_container.rb +39 -0
- data/lib/punchblock/media_node.rb +17 -0
- data/lib/punchblock/protocol_error.rb +16 -0
- data/lib/punchblock/rayo_node.rb +88 -0
- data/lib/punchblock/ref.rb +26 -0
- data/lib/punchblock/version.rb +3 -0
- data/lib/punchblock.rb +42 -0
- data/log/.gitkeep +0 -0
- data/punchblock.gemspec +42 -0
- data/spec/punchblock/command/accept_spec.rb +13 -0
- data/spec/punchblock/command/answer_spec.rb +13 -0
- data/spec/punchblock/command/dial_spec.rb +54 -0
- data/spec/punchblock/command/hangup_spec.rb +13 -0
- data/spec/punchblock/command/join_spec.rb +21 -0
- data/spec/punchblock/command/mute_spec.rb +11 -0
- data/spec/punchblock/command/redirect_spec.rb +19 -0
- data/spec/punchblock/command/reject_spec.rb +43 -0
- data/spec/punchblock/command/unjoin_spec.rb +19 -0
- data/spec/punchblock/command/unmute_spec.rb +11 -0
- data/spec/punchblock/command_node_spec.rb +80 -0
- data/spec/punchblock/component/input_spec.rb +188 -0
- data/spec/punchblock/component/output_spec.rb +531 -0
- data/spec/punchblock/component/record_spec.rb +235 -0
- data/spec/punchblock/component/tropo/ask_spec.rb +183 -0
- data/spec/punchblock/component/tropo/conference_spec.rb +360 -0
- data/spec/punchblock/component/tropo/say_spec.rb +171 -0
- data/spec/punchblock/component/tropo/transfer_spec.rb +153 -0
- data/spec/punchblock/component_spec.rb +126 -0
- data/spec/punchblock/connection_spec.rb +194 -0
- data/spec/punchblock/event/answered_spec.rb +23 -0
- data/spec/punchblock/event/complete_spec.rb +80 -0
- data/spec/punchblock/event/dtmf_spec.rb +24 -0
- data/spec/punchblock/event/end_spec.rb +30 -0
- data/spec/punchblock/event/info_spec.rb +30 -0
- data/spec/punchblock/event/joined_spec.rb +32 -0
- data/spec/punchblock/event/offer_spec.rb +35 -0
- data/spec/punchblock/event/ringing_spec.rb +23 -0
- data/spec/punchblock/event/unjoined_spec.rb +32 -0
- data/spec/punchblock/header_spec.rb +44 -0
- data/spec/punchblock/protocol_error_spec.rb +9 -0
- data/spec/punchblock/ref_spec.rb +21 -0
- data/spec/spec_helper.rb +43 -0
- metadata +353 -0
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
module Punchblock
|
|
2
|
+
class Event
|
|
3
|
+
class Joined < Event
|
|
4
|
+
register :joined, :core
|
|
5
|
+
|
|
6
|
+
##
|
|
7
|
+
# Create a joined event
|
|
8
|
+
#
|
|
9
|
+
# @param [Hash] options
|
|
10
|
+
# @option options [String, Optional] :other_call_id the call ID that was joined
|
|
11
|
+
# @option options [String, Optional] :mixer_id the mixer name that was joined
|
|
12
|
+
#
|
|
13
|
+
# @return [Event::Joined] a formatted Rayo joined event
|
|
14
|
+
#
|
|
15
|
+
def self.new(options = {})
|
|
16
|
+
super().tap do |new_node|
|
|
17
|
+
options.each_pair { |k,v| new_node.send :"#{k}=", v }
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
##
|
|
22
|
+
# @return [String] the call ID that was joined
|
|
23
|
+
def other_call_id
|
|
24
|
+
read_attr :'call-id'
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
##
|
|
28
|
+
# @param [String] other the call ID that was joined
|
|
29
|
+
def other_call_id=(other)
|
|
30
|
+
write_attr :'call-id', other
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
##
|
|
34
|
+
# @return [String] the mixer name that was joined
|
|
35
|
+
def mixer_id
|
|
36
|
+
read_attr :'mixer-id'
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
##
|
|
40
|
+
# @param [String] other the mixer name that was joined
|
|
41
|
+
def mixer_id=(other)
|
|
42
|
+
write_attr :'mixer-id', other
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def inspect_attributes # :nodoc:
|
|
46
|
+
[:other_call_id, :mixer_id] + super
|
|
47
|
+
end
|
|
48
|
+
end # Joined
|
|
49
|
+
end
|
|
50
|
+
end # Punchblock
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
module Punchblock
|
|
2
|
+
class Event
|
|
3
|
+
class Offer < Event
|
|
4
|
+
register :offer, :core
|
|
5
|
+
|
|
6
|
+
include HasHeaders
|
|
7
|
+
|
|
8
|
+
def to
|
|
9
|
+
read_attr :to
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def to=(offer_to)
|
|
13
|
+
write_attr :to, offer_to
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def from
|
|
17
|
+
read_attr :from
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def from=(offer_from)
|
|
21
|
+
write_attr :from, offer_from
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def inspect_attributes # :nodoc:
|
|
25
|
+
[:to, :from] + super
|
|
26
|
+
end
|
|
27
|
+
end # Offer
|
|
28
|
+
end
|
|
29
|
+
end # Punchblock
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
module Punchblock
|
|
2
|
+
class Event
|
|
3
|
+
class Unjoined < Event
|
|
4
|
+
register :unjoined, :core
|
|
5
|
+
|
|
6
|
+
##
|
|
7
|
+
# Create an unjoined event
|
|
8
|
+
#
|
|
9
|
+
# @param [Hash] options
|
|
10
|
+
# @option options [String, Optional] :other_call_id the call ID that was unjoined
|
|
11
|
+
# @option options [String, Optional] :mixer_id the mixer name that was unjoined
|
|
12
|
+
#
|
|
13
|
+
# @return [Event::Unjoined] a formatted Rayo unjoined event
|
|
14
|
+
#
|
|
15
|
+
def self.new(options = {})
|
|
16
|
+
super().tap do |new_node|
|
|
17
|
+
options.each_pair { |k,v| new_node.send :"#{k}=", v }
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
##
|
|
22
|
+
# @return [String] the call ID that was unjoined
|
|
23
|
+
def other_call_id
|
|
24
|
+
read_attr :'call-id'
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
##
|
|
28
|
+
# @param [String] other the call ID that was unjoined
|
|
29
|
+
def other_call_id=(other)
|
|
30
|
+
write_attr :'call-id', other
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
##
|
|
34
|
+
# @return [String] the mixer name that was unjoined
|
|
35
|
+
def mixer_id
|
|
36
|
+
read_attr :'mixer-id'
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
##
|
|
40
|
+
# @param [String] other the mixer name that was unjoined
|
|
41
|
+
def mixer_id=(other)
|
|
42
|
+
write_attr :'mixer-id', other
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def inspect_attributes # :nodoc:
|
|
46
|
+
[:other_call_id, :mixer_id] + super
|
|
47
|
+
end
|
|
48
|
+
end # Unjoined
|
|
49
|
+
end
|
|
50
|
+
end # Punchblock
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
module Punchblock
|
|
2
|
+
class GenericConnection
|
|
3
|
+
attr_accessor :event_queue
|
|
4
|
+
|
|
5
|
+
##
|
|
6
|
+
# @param [Hash] options
|
|
7
|
+
# @option options [Logger] :transport_logger The logger to which transport events will be logged
|
|
8
|
+
#
|
|
9
|
+
def initialize(options = {})
|
|
10
|
+
@event_queue = Queue.new
|
|
11
|
+
@logger = options.delete(:transport_logger) if options[:transport_logger]
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def connected
|
|
15
|
+
'CONNECTED'
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
module Punchblock
|
|
2
|
+
module HasHeaders
|
|
3
|
+
##
|
|
4
|
+
# @return [Hash] hash of key-value pairs of headers
|
|
5
|
+
#
|
|
6
|
+
def headers_hash
|
|
7
|
+
headers.inject({}) do |hash, header|
|
|
8
|
+
hash[header.name] = header.value
|
|
9
|
+
hash
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
##
|
|
14
|
+
# @return [Array[Header]] headers
|
|
15
|
+
#
|
|
16
|
+
def headers
|
|
17
|
+
find('//ns:header', :ns => self.class.registered_ns).map do |i|
|
|
18
|
+
Header.new i
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
##
|
|
23
|
+
# @param [Hash, Array] headers A hash of key-value header pairs, or an array of Header objects
|
|
24
|
+
#
|
|
25
|
+
def headers=(headers)
|
|
26
|
+
find('//ns:header', :ns => self.class.registered_ns).each &:remove
|
|
27
|
+
if headers.is_a? Hash
|
|
28
|
+
headers.each_pair { |k,v| self << Header.new(k, v) }
|
|
29
|
+
elsif headers.is_a? Array
|
|
30
|
+
[headers].flatten.each { |i| self << Header.new(i) }
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
module Punchblock
|
|
2
|
+
class Header < RayoNode
|
|
3
|
+
##
|
|
4
|
+
# @param [String] name
|
|
5
|
+
# @param [String] value
|
|
6
|
+
#
|
|
7
|
+
def self.new(name, value = '')
|
|
8
|
+
super(:header).tap do |new_node|
|
|
9
|
+
case name
|
|
10
|
+
when Nokogiri::XML::Node
|
|
11
|
+
new_node.inherit name
|
|
12
|
+
else
|
|
13
|
+
new_node.name = name
|
|
14
|
+
new_node.value = value
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# The Header's name
|
|
20
|
+
# @return [Symbol]
|
|
21
|
+
def name
|
|
22
|
+
read_attr(:name).gsub('-', '_').to_sym
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# Set the Header's name
|
|
26
|
+
# @param [Symbol] name the new name for the header
|
|
27
|
+
def name=(name)
|
|
28
|
+
write_attr :name, name.to_s.gsub('_', '-')
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# The Header's value
|
|
32
|
+
# @return [String]
|
|
33
|
+
def value
|
|
34
|
+
read_attr :value
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# Set the Header's value
|
|
38
|
+
# @param [String] value the new value for the header
|
|
39
|
+
def value=(value)
|
|
40
|
+
write_attr :value, value
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def inspect_attributes # :nodoc:
|
|
44
|
+
[:name, :value] + super
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end # Punchblock
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
module Punchblock
|
|
2
|
+
module MediaContainer
|
|
3
|
+
##
|
|
4
|
+
# @return [String] the TTS voice to use
|
|
5
|
+
#
|
|
6
|
+
def voice
|
|
7
|
+
read_attr :voice
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
##
|
|
11
|
+
# @param [String] voice to use when rendering TTS
|
|
12
|
+
#
|
|
13
|
+
def voice=(voice)
|
|
14
|
+
write_attr :voice, voice
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
##
|
|
18
|
+
# @return [String] the SSML document to render TTS
|
|
19
|
+
#
|
|
20
|
+
def ssml
|
|
21
|
+
children.to_xml
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
##
|
|
25
|
+
# @param [String] ssml the SSML document to render TTS
|
|
26
|
+
#
|
|
27
|
+
def ssml=(ssml)
|
|
28
|
+
if ssml.instance_of?(String)
|
|
29
|
+
self << RayoNode.new('').parse(ssml) do |config|
|
|
30
|
+
config.noblanks.strict
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def inspect_attributes # :nodoc:
|
|
36
|
+
[:voice, :ssml] + super
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
module Punchblock
|
|
2
|
+
class MediaNode < RayoNode
|
|
3
|
+
include MediaContainer
|
|
4
|
+
|
|
5
|
+
def self.new(options = {})
|
|
6
|
+
super().tap do |new_node|
|
|
7
|
+
case options
|
|
8
|
+
when Hash
|
|
9
|
+
new_node << options.delete(:text) if options[:text]
|
|
10
|
+
options.each_pair { |k,v| new_node.send :"#{k}=", v }
|
|
11
|
+
when Nokogiri::XML::Element
|
|
12
|
+
new_node.inherit options
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
module Punchblock
|
|
2
|
+
##
|
|
3
|
+
# This exception may be raised if a transport error is detected.
|
|
4
|
+
class ProtocolError < StandardError
|
|
5
|
+
attr_accessor :name, :text, :call_id, :component_id
|
|
6
|
+
|
|
7
|
+
def initialize(name = nil, text = nil, call_id = nil, component_id = nil)
|
|
8
|
+
@name, @text, @call_id, @component_id = name, text, call_id, component_id
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def to_s
|
|
12
|
+
"#<#{self.class}: name=#{name.inspect} text=#{text.inspect} call_id=#{call_id.inspect} component_id=#{component_id.inspect}>"
|
|
13
|
+
end
|
|
14
|
+
alias :inspect :to_s
|
|
15
|
+
end
|
|
16
|
+
end
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
require 'active_support/core_ext/class/attribute'
|
|
2
|
+
require 'niceogiri'
|
|
3
|
+
|
|
4
|
+
module Punchblock
|
|
5
|
+
class RayoNode < Niceogiri::XML::Node
|
|
6
|
+
@@registrations = {}
|
|
7
|
+
|
|
8
|
+
class_attribute :registered_ns, :registered_name
|
|
9
|
+
|
|
10
|
+
attr_accessor :call_id, :component_id, :connection, :original_component
|
|
11
|
+
|
|
12
|
+
# Register a new stanza class to a name and/or namespace
|
|
13
|
+
#
|
|
14
|
+
# This registers a namespace that is used when looking
|
|
15
|
+
# up the class name of the object to instantiate when a new
|
|
16
|
+
# stanza is received
|
|
17
|
+
#
|
|
18
|
+
# @param [#to_s] name the name of the node
|
|
19
|
+
# @param [String, nil] ns the namespace the node belongs to
|
|
20
|
+
def self.register(name, ns = nil)
|
|
21
|
+
self.registered_name = name.to_s
|
|
22
|
+
self.registered_ns = ns.is_a?(Symbol) ? RAYO_NAMESPACES[ns] : ns
|
|
23
|
+
@@registrations[[self.registered_name, self.registered_ns]] = self
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# Find the class to use given the name and namespace of a stanza
|
|
27
|
+
#
|
|
28
|
+
# @param [#to_s] name the name to lookup
|
|
29
|
+
# @param [String, nil] xmlns the namespace the node belongs to
|
|
30
|
+
# @return [Class, nil] the class appropriate for the name/ns combination
|
|
31
|
+
def self.class_from_registration(name, ns = nil)
|
|
32
|
+
@@registrations[[name.to_s, ns]]
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# Import an XML::Node to the appropriate class
|
|
36
|
+
#
|
|
37
|
+
# Looks up the class the node should be then creates it based on the
|
|
38
|
+
# elements of the XML::Node
|
|
39
|
+
# @param [XML::Node] node the node to import
|
|
40
|
+
# @return the appropriate object based on the node name and namespace
|
|
41
|
+
def self.import(node, call_id = nil, component_id = nil)
|
|
42
|
+
ns = (node.namespace.href if node.namespace)
|
|
43
|
+
klass = class_from_registration(node.element_name, ns)
|
|
44
|
+
event = if klass && klass != self
|
|
45
|
+
klass.import node, call_id, component_id
|
|
46
|
+
else
|
|
47
|
+
new.inherit node
|
|
48
|
+
end
|
|
49
|
+
event.tap do |event|
|
|
50
|
+
event.call_id = call_id
|
|
51
|
+
event.component_id = component_id
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
# Create a new Node object
|
|
56
|
+
#
|
|
57
|
+
# @param [String, nil] name the element name
|
|
58
|
+
# @param [XML::Document, nil] doc the document to attach the node to. If
|
|
59
|
+
# not provided one will be created
|
|
60
|
+
# @return a new object with the registered name and namespace
|
|
61
|
+
def self.new(name = registered_name, doc = nil)
|
|
62
|
+
super name, doc, registered_ns
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def inspect_attributes # :nodoc:
|
|
66
|
+
[:call_id, :component_id]
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def inspect
|
|
70
|
+
"#<#{self.class} #{inspect_attributes.map { |c| "#{c}=#{self.__send__(c).inspect}" rescue nil }.compact * ', '}>"
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def eql?(o, *fields)
|
|
74
|
+
super o, *(fields + inspect_attributes)
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
##
|
|
78
|
+
# @return [RayoNode] the original command issued that lead to this event
|
|
79
|
+
#
|
|
80
|
+
def source
|
|
81
|
+
@source ||= connection.original_component_from_id component_id if connection && component_id
|
|
82
|
+
@source ||= original_component
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
alias :to_s :inspect
|
|
86
|
+
alias :xmlns :namespace_href
|
|
87
|
+
end
|
|
88
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
module Punchblock
|
|
2
|
+
##
|
|
3
|
+
# An rayo Ref message. This provides the command ID in response to execution of a command.
|
|
4
|
+
#
|
|
5
|
+
class Ref < RayoNode
|
|
6
|
+
register :ref, :core
|
|
7
|
+
|
|
8
|
+
##
|
|
9
|
+
# @return [String] the command ID
|
|
10
|
+
#
|
|
11
|
+
def id
|
|
12
|
+
read_attr :id
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
##
|
|
16
|
+
# @param [String] ref_id the command ID
|
|
17
|
+
#
|
|
18
|
+
def id=(ref_id)
|
|
19
|
+
write_attr :id, ref_id
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def inspect_attributes # :nodoc:
|
|
23
|
+
[:id] + super
|
|
24
|
+
end
|
|
25
|
+
end # Offer
|
|
26
|
+
end # Punchblock
|
data/lib/punchblock.rb
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
require 'active_support/dependencies/autoload'
|
|
2
|
+
require 'active_support/core_ext/object/blank'
|
|
3
|
+
require 'future-resource'
|
|
4
|
+
|
|
5
|
+
module Punchblock
|
|
6
|
+
extend ActiveSupport::Autoload
|
|
7
|
+
|
|
8
|
+
autoload :Command
|
|
9
|
+
autoload :CommandNode
|
|
10
|
+
autoload :Component
|
|
11
|
+
autoload :Connection
|
|
12
|
+
autoload :DSL
|
|
13
|
+
autoload :GenericConnection
|
|
14
|
+
autoload :HasHeaders
|
|
15
|
+
autoload :Header
|
|
16
|
+
autoload :MediaContainer
|
|
17
|
+
autoload :MediaNode
|
|
18
|
+
autoload :ProtocolError
|
|
19
|
+
autoload :RayoNode
|
|
20
|
+
|
|
21
|
+
##
|
|
22
|
+
# This exception may be raised if a transport error is detected.
|
|
23
|
+
TransportError = Class.new StandardError
|
|
24
|
+
|
|
25
|
+
BASE_RAYO_NAMESPACE = 'urn:xmpp:rayo'
|
|
26
|
+
BASE_TROPO_NAMESPACE = 'urn:xmpp:tropo'
|
|
27
|
+
RAYO_VERSION = '1'
|
|
28
|
+
RAYO_NAMESPACES = {:core => [BASE_RAYO_NAMESPACE, RAYO_VERSION].compact.join(':')}
|
|
29
|
+
|
|
30
|
+
[:ext, :record, :output, :input].each do |ns|
|
|
31
|
+
RAYO_NAMESPACES[ns] = [BASE_RAYO_NAMESPACE, ns.to_s, RAYO_VERSION].compact.join(':')
|
|
32
|
+
RAYO_NAMESPACES[:"#{ns}_complete"] = [BASE_RAYO_NAMESPACE, ns.to_s, 'complete', RAYO_VERSION].compact.join(':')
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
[:ask, :conference, :say, :transfer].each do |ns|
|
|
36
|
+
RAYO_NAMESPACES[ns] = [BASE_TROPO_NAMESPACE, ns.to_s, RAYO_VERSION].compact.join(':')
|
|
37
|
+
RAYO_NAMESPACES[:"#{ns}_complete"] = [BASE_TROPO_NAMESPACE, ns.to_s, 'complete', RAYO_VERSION].compact.join(':')
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
require 'punchblock/event'
|
|
42
|
+
require 'punchblock/ref'
|
data/log/.gitkeep
ADDED
|
File without changes
|
data/punchblock.gemspec
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
|
3
|
+
require "punchblock/version"
|
|
4
|
+
|
|
5
|
+
Gem::Specification.new do |s|
|
|
6
|
+
s.name = %q{punchblock}
|
|
7
|
+
s.version = Punchblock::VERSION
|
|
8
|
+
s.platform = Gem::Platform::RUBY
|
|
9
|
+
s.licenses = ["MIT"]
|
|
10
|
+
s.authors = ["Jason Goecke", "Ben Klang", "Ben Langfeld"]
|
|
11
|
+
s.email = %q{punchblock@adhearsion.com}
|
|
12
|
+
s.homepage = %q{http://github.com/adhearsion/punchblock}
|
|
13
|
+
s.summary = "Punchblock is a telephony middleware library"
|
|
14
|
+
s.description = "Like Rack is to Rails and Sinatra, Punchblock provides a consistent API on top of several underlying third-party call control protocols."
|
|
15
|
+
|
|
16
|
+
s.rubyforge_project = "punchblock"
|
|
17
|
+
|
|
18
|
+
s.files = `git ls-files`.split("\n")
|
|
19
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
|
20
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
|
21
|
+
s.require_paths = ["lib"]
|
|
22
|
+
|
|
23
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 1.3.7") if s.respond_to? :required_rubygems_version=
|
|
24
|
+
|
|
25
|
+
s.add_runtime_dependency %q<niceogiri>, [">= 0.0.4"]
|
|
26
|
+
s.add_runtime_dependency %q<blather>, [">= 0.5.3"]
|
|
27
|
+
s.add_runtime_dependency %q<pry>, [">= 0.8.3"]
|
|
28
|
+
s.add_runtime_dependency %q<activesupport>, [">= 2.1.0"]
|
|
29
|
+
s.add_runtime_dependency %q<state_machine>, [">= 1.0.1"]
|
|
30
|
+
s.add_runtime_dependency %q<future-resource>, [">= 0.0.2"]
|
|
31
|
+
|
|
32
|
+
s.add_development_dependency %q<bundler>, ["~> 1.0.0"]
|
|
33
|
+
s.add_development_dependency %q<rspec>, ["~> 2.3.0"]
|
|
34
|
+
s.add_development_dependency %q<ci_reporter>, [">= 1.6.3"]
|
|
35
|
+
s.add_development_dependency %q<yard>, ["~> 0.6.0"]
|
|
36
|
+
s.add_development_dependency %q<bluecloth>, [">= 0"]
|
|
37
|
+
s.add_development_dependency %q<rcov>, [">= 0"]
|
|
38
|
+
s.add_development_dependency %q<rake>, [">= 0"]
|
|
39
|
+
s.add_development_dependency %q<mocha>, [">= 0"]
|
|
40
|
+
s.add_development_dependency %q<i18n>, [">= 0"]
|
|
41
|
+
s.add_development_dependency %q<countdownlatch>, [">= 0"]
|
|
42
|
+
end
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
module Punchblock
|
|
4
|
+
module Command
|
|
5
|
+
describe Accept do
|
|
6
|
+
it 'registers itself' do
|
|
7
|
+
RayoNode.class_from_registration(:accept, 'urn:xmpp:rayo:1').should == Accept
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
it_should_behave_like 'command_headers'
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end # Punchblock
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
module Punchblock
|
|
4
|
+
module Command
|
|
5
|
+
describe Answer do
|
|
6
|
+
it 'registers itself' do
|
|
7
|
+
RayoNode.class_from_registration(:answer, 'urn:xmpp:rayo:1').should == Answer
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
it_should_behave_like 'command_headers'
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end # Punchblock
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
%w{
|
|
4
|
+
blather/client/dsl
|
|
5
|
+
punchblock/core_ext/blather/stanza
|
|
6
|
+
punchblock/core_ext/blather/stanza/presence
|
|
7
|
+
}.each { |f| require f }
|
|
8
|
+
|
|
9
|
+
module Punchblock
|
|
10
|
+
module Command
|
|
11
|
+
describe Dial do
|
|
12
|
+
|
|
13
|
+
it 'registers itself' do
|
|
14
|
+
RayoNode.class_from_registration(:dial, 'urn:xmpp:rayo:1').should == Dial
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
describe "when setting options in initializer" do
|
|
18
|
+
let(:join_params) { {:other_call_id => 'abc123'} }
|
|
19
|
+
|
|
20
|
+
subject { Dial.new :to => 'tel:+14155551212', :from => 'tel:+13035551212', :headers => { :x_skill => 'agent', :x_customer_id => 8877 }, :join => join_params }
|
|
21
|
+
|
|
22
|
+
it_should_behave_like 'command_headers'
|
|
23
|
+
|
|
24
|
+
its(:to) { should == 'tel:+14155551212' }
|
|
25
|
+
its(:from) { should == 'tel:+13035551212' }
|
|
26
|
+
its(:join) { should == Join.new(join_params) }
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
describe "#response=" do
|
|
30
|
+
before { subject.request! }
|
|
31
|
+
|
|
32
|
+
let(:call_id) { 'abc123' }
|
|
33
|
+
|
|
34
|
+
let :ref do
|
|
35
|
+
Ref.new.tap do |ref|
|
|
36
|
+
ref.id = call_id
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
let :iq do
|
|
41
|
+
Blather::Stanza::Iq.new(:result, 'blah').tap do |iq|
|
|
42
|
+
iq.from = "call.rayo.net"
|
|
43
|
+
iq << ref
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
it "should set the call ID from the ref" do
|
|
48
|
+
subject.response = iq
|
|
49
|
+
subject.call_id.should == call_id
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end # Punchblock
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
module Punchblock
|
|
4
|
+
module Command
|
|
5
|
+
describe Hangup do
|
|
6
|
+
it 'registers itself' do
|
|
7
|
+
RayoNode.class_from_registration(:hangup, 'urn:xmpp:rayo:1').should == Hangup
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
it_should_behave_like 'command_headers'
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end # Punchblock
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
module Punchblock
|
|
4
|
+
module Command
|
|
5
|
+
describe Join do
|
|
6
|
+
|
|
7
|
+
it 'registers itself' do
|
|
8
|
+
RayoNode.class_from_registration(:join, 'urn:xmpp:rayo:1').should == Join
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
describe "when setting options in initializer" do
|
|
12
|
+
subject { Join.new :other_call_id => 'abc123', :mixer_id => 'blah', :direction => :duplex, :media => :bridge }
|
|
13
|
+
|
|
14
|
+
its(:other_call_id) { should == 'abc123' }
|
|
15
|
+
its(:mixer_id) { should == 'blah' }
|
|
16
|
+
its(:direction) { should == :duplex }
|
|
17
|
+
its(:media) { should == :bridge }
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end # Punchblock
|