punchblock 0.5.1 → 0.6.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/CHANGELOG.md +5 -0
- data/LICENSE.txt +3 -1
- data/bin/punchblock-console +19 -1
- data/lib/punchblock.rb +11 -4
- data/lib/punchblock/command/reject.rb +6 -2
- data/lib/punchblock/component.rb +1 -0
- data/lib/punchblock/component/asterisk.rb +10 -0
- data/lib/punchblock/component/asterisk/agi.rb +11 -0
- data/lib/punchblock/component/asterisk/agi/command.rb +157 -0
- data/lib/punchblock/component/asterisk/ami.rb +12 -0
- data/lib/punchblock/component/asterisk/ami/action.rb +144 -0
- data/lib/punchblock/component/input.rb +2 -2
- data/lib/punchblock/connection.rb +1 -0
- data/lib/punchblock/connection/asterisk.rb +31 -0
- data/lib/punchblock/core_ext/celluloid.rb +11 -0
- data/lib/punchblock/event.rb +1 -1
- data/lib/punchblock/event/asterisk.rb +9 -0
- data/lib/punchblock/event/asterisk/ami.rb +11 -0
- data/lib/punchblock/event/asterisk/ami/event.rb +66 -0
- data/lib/punchblock/event/complete.rb +20 -0
- data/lib/punchblock/event/dtmf.rb +19 -0
- data/lib/punchblock/event/end.rb +23 -0
- data/lib/punchblock/event/offer.rb +23 -0
- data/lib/punchblock/header.rb +4 -44
- data/lib/punchblock/key_value_pair_node.rb +50 -0
- data/lib/punchblock/rayo_node.rb +1 -1
- data/lib/punchblock/ref.rb +6 -0
- data/lib/punchblock/translator.rb +7 -0
- data/lib/punchblock/translator/asterisk.rb +74 -0
- data/lib/punchblock/translator/asterisk/ami_action.rb +86 -0
- data/lib/punchblock/translator/asterisk/call.rb +25 -0
- data/lib/punchblock/translator/asterisk/component.rb +11 -0
- data/lib/punchblock/version.rb +1 -1
- data/punchblock.gemspec +3 -1
- data/spec/punchblock/command/accept_spec.rb +8 -0
- data/spec/punchblock/command/answer_spec.rb +8 -0
- data/spec/punchblock/command/dial_spec.rb +22 -2
- data/spec/punchblock/command/hangup_spec.rb +8 -0
- data/spec/punchblock/command/join_spec.rb +21 -0
- data/spec/punchblock/command/mute_spec.rb +8 -0
- data/spec/punchblock/command/redirect_spec.rb +21 -0
- data/spec/punchblock/command/reject_spec.rb +19 -8
- data/spec/punchblock/command/unjoin_spec.rb +17 -0
- data/spec/punchblock/command/unmute_spec.rb +8 -0
- data/spec/punchblock/component/asterisk/agi/command_spec.rb +102 -0
- data/spec/punchblock/component/asterisk/ami/action_spec.rb +118 -0
- data/spec/punchblock/component/input_spec.rb +40 -0
- data/spec/punchblock/component/output_spec.rb +28 -0
- data/spec/punchblock/component/record_spec.rb +27 -0
- data/spec/punchblock/connection/asterisk_spec.rb +69 -0
- data/spec/punchblock/event/asterisk/ami/event_spec.rb +60 -0
- data/spec/punchblock/event/complete_spec.rb +8 -0
- data/spec/punchblock/event/dtmf_spec.rb +8 -0
- data/spec/punchblock/event/end_spec.rb +8 -0
- data/spec/punchblock/event/offer_spec.rb +15 -2
- data/spec/punchblock/ref_spec.rb +6 -0
- data/spec/punchblock/translator/asterisk/ami_action_spec.rb +149 -0
- data/spec/punchblock/translator/asterisk/call_spec.rb +18 -0
- data/spec/punchblock/translator/asterisk/component_spec.rb +11 -0
- data/spec/punchblock/translator/asterisk_spec.rb +150 -0
- data/spec/spec_helper.rb +42 -0
- metadata +92 -42
- data/lib/punchblock/event/info.rb +0 -15
- data/spec/punchblock/event/info_spec.rb +0 -30
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
# develop
|
|
2
2
|
|
|
3
|
+
# v0.6.0
|
|
4
|
+
* API change: Punchblock consumers now need to instantiate both a Connection and a Client (see the punchblock-console gem for an example)
|
|
5
|
+
* Feature: Added a Connection for Asterisk, utilising RubyAMI to open an AMI connection to Asterisk, and allowing AMI actions to be executed. AMI events are handled by the client event handler.
|
|
6
|
+
* Deprecation: The punchblock-console and the associated DSL are now deprecated and the punchblock-console gem should be used instead
|
|
7
|
+
|
|
3
8
|
# v0.5.1
|
|
4
9
|
API change: Connections now raise a Punchblock::Connection::Connected instance as an event, rather than the class itself
|
|
5
10
|
|
data/LICENSE.txt
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
Copyright (
|
|
1
|
+
Copyright (C) 2011 Ben Klang
|
|
2
|
+
Copyright (C) 2011 Ben Langfeld
|
|
3
|
+
Copyright (C) 2011 Jason Goecke
|
|
2
4
|
|
|
3
5
|
Permission is hereby granted, free of charge, to any person obtaining
|
|
4
6
|
a copy of this software and associated documentation files (the
|
data/bin/punchblock-console
CHANGED
|
@@ -7,12 +7,20 @@ require 'pry'
|
|
|
7
7
|
require 'logger'
|
|
8
8
|
require 'optparse'
|
|
9
9
|
|
|
10
|
+
puts <<-DEPRECATION
|
|
11
|
+
********************
|
|
12
|
+
WARNING: This utility is deprecated and will be removed from a future version of Punchblock without further notice. You should use the punchblock-console gem instead.
|
|
13
|
+
********************
|
|
14
|
+
DEPRECATION
|
|
15
|
+
|
|
10
16
|
include Punchblock
|
|
11
17
|
|
|
12
18
|
Thread.abort_on_exception = true
|
|
13
19
|
|
|
14
20
|
options = { :username => 'usera@127.0.0.1', :password => '1', :wire_log_file => 'log/rayo-wire.log', :transport_log_file => 'log/rayo-transport.log', :auto_reconnect => false }
|
|
15
21
|
|
|
22
|
+
connection_class = Connection::XMPP
|
|
23
|
+
|
|
16
24
|
option_parser = OptionParser.new do |opts|
|
|
17
25
|
opts.banner = "Usage: punchblock-console [-u usera@127.0.0.1] [-p abc123]"
|
|
18
26
|
opts.on("-u", "--username USERNAME", String, "Specify the XMPP JID to connect to") do |u|
|
|
@@ -30,6 +38,11 @@ option_parser = OptionParser.new do |opts|
|
|
|
30
38
|
opts.on("--transport-log-file log/transportlog.log", String, "Specify the file to which the transport log should be written") do |tlf|
|
|
31
39
|
options[:transport_log_file] = tlf
|
|
32
40
|
end
|
|
41
|
+
opts.on("--asterisk", "Use Asterisk") do |tlf|
|
|
42
|
+
connection_class = Connection::Asterisk
|
|
43
|
+
options[:host] = '127.0.0.1'
|
|
44
|
+
options[:port] = 5038
|
|
45
|
+
end
|
|
33
46
|
opts.on_tail("-h", "--help", "Show this message") do
|
|
34
47
|
puts opts
|
|
35
48
|
exit
|
|
@@ -53,8 +66,9 @@ options[:wire_logger].debug "Starting up..."
|
|
|
53
66
|
options[:transport_logger] = Logger.new options.delete(:transport_log_file)
|
|
54
67
|
options[:transport_logger].level = Logger::DEBUG
|
|
55
68
|
options[:transport_logger].debug "Starting up..."
|
|
69
|
+
options[:logger] = options[:wire_logger]
|
|
56
70
|
|
|
57
|
-
connection =
|
|
71
|
+
connection = connection_class.new options
|
|
58
72
|
client = Client.new :connection => connection
|
|
59
73
|
|
|
60
74
|
[:INT, :TERM].each do |signal|
|
|
@@ -87,6 +101,10 @@ Thread.new do
|
|
|
87
101
|
puts "Waiting for a call..."
|
|
88
102
|
next
|
|
89
103
|
end
|
|
104
|
+
unless event.call_id
|
|
105
|
+
puts "Ad-hoc event: #{event.inspect}"
|
|
106
|
+
next
|
|
107
|
+
end
|
|
90
108
|
puts "#{event.class} event for call: #{event.call_id}"
|
|
91
109
|
case event
|
|
92
110
|
when Event::Offer
|
data/lib/punchblock.rb
CHANGED
|
@@ -34,15 +34,17 @@ module Punchblock
|
|
|
34
34
|
autoload :MediaNode
|
|
35
35
|
autoload :ProtocolError
|
|
36
36
|
autoload :RayoNode
|
|
37
|
+
autoload :Translator
|
|
37
38
|
|
|
38
39
|
##
|
|
39
40
|
# This exception may be raised if a transport error is detected.
|
|
40
41
|
TransportError = Class.new StandardError
|
|
41
42
|
|
|
42
|
-
BASE_RAYO_NAMESPACE
|
|
43
|
-
BASE_TROPO_NAMESPACE
|
|
44
|
-
|
|
45
|
-
|
|
43
|
+
BASE_RAYO_NAMESPACE = 'urn:xmpp:rayo'
|
|
44
|
+
BASE_TROPO_NAMESPACE = 'urn:xmpp:tropo'
|
|
45
|
+
BASE_ASTERISK_NAMESPACE = 'urn:xmpp:rayo:asterisk'
|
|
46
|
+
RAYO_VERSION = '1'
|
|
47
|
+
RAYO_NAMESPACES = {:core => [BASE_RAYO_NAMESPACE, RAYO_VERSION].compact.join(':')}
|
|
46
48
|
|
|
47
49
|
[:ext, :record, :output, :input].each do |ns|
|
|
48
50
|
RAYO_NAMESPACES[ns] = [BASE_RAYO_NAMESPACE, ns.to_s, RAYO_VERSION].compact.join(':')
|
|
@@ -53,6 +55,11 @@ module Punchblock
|
|
|
53
55
|
RAYO_NAMESPACES[ns] = [BASE_TROPO_NAMESPACE, ns.to_s, RAYO_VERSION].compact.join(':')
|
|
54
56
|
RAYO_NAMESPACES[:"#{ns}_complete"] = [BASE_TROPO_NAMESPACE, ns.to_s, 'complete', RAYO_VERSION].compact.join(':')
|
|
55
57
|
end
|
|
58
|
+
|
|
59
|
+
[:agi, :ami].each do |ns|
|
|
60
|
+
RAYO_NAMESPACES[ns] = [BASE_ASTERISK_NAMESPACE, ns.to_s, RAYO_VERSION].compact.join(':')
|
|
61
|
+
RAYO_NAMESPACES[:"#{ns}_complete"] = [BASE_ASTERISK_NAMESPACE, ns.to_s, 'complete', RAYO_VERSION].compact.join(':')
|
|
62
|
+
end
|
|
56
63
|
end
|
|
57
64
|
|
|
58
65
|
require 'punchblock/event'
|
|
@@ -26,8 +26,12 @@ module Punchblock
|
|
|
26
26
|
#
|
|
27
27
|
def self.new(options = {})
|
|
28
28
|
super().tap do |new_node|
|
|
29
|
-
|
|
30
|
-
|
|
29
|
+
case options
|
|
30
|
+
when Nokogiri::XML::Node
|
|
31
|
+
new_node.inherit options
|
|
32
|
+
when Hash
|
|
33
|
+
options.each_pair { |k,v| new_node.send :"#{k}=", v }
|
|
34
|
+
end
|
|
31
35
|
end
|
|
32
36
|
end
|
|
33
37
|
|
data/lib/punchblock/component.rb
CHANGED
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
module Punchblock
|
|
2
|
+
module Component
|
|
3
|
+
module Asterisk
|
|
4
|
+
module AGI
|
|
5
|
+
class Command < ComponentNode
|
|
6
|
+
register :command, :agi
|
|
7
|
+
|
|
8
|
+
def self.new(options = {})
|
|
9
|
+
super().tap do |new_node|
|
|
10
|
+
options.each_pair { |k,v| new_node.send :"#{k}=", v }
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def name
|
|
15
|
+
read_attr :name
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def name=(other)
|
|
19
|
+
write_attr :name, other
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
##
|
|
23
|
+
# @return [Array[String]] array of values of params
|
|
24
|
+
#
|
|
25
|
+
def params_array
|
|
26
|
+
params.map &:value
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
##
|
|
30
|
+
# @return [Array[Param]] params
|
|
31
|
+
#
|
|
32
|
+
def params
|
|
33
|
+
find('//ns:param', :ns => self.class.registered_ns).map do |i|
|
|
34
|
+
Param.new i
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
##
|
|
39
|
+
# @param [Hash, Array] params A hash of key-value param pairs, or an array of Param objects
|
|
40
|
+
#
|
|
41
|
+
def params=(params)
|
|
42
|
+
find('//ns:param', :ns => self.class.registered_ns).each &:remove
|
|
43
|
+
[params].flatten.each { |i| self << Param.new(i) } if params.is_a? Array
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def inspect_attributes # :nodoc:
|
|
47
|
+
[:name, :params_array] + super
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
class Param < RayoNode
|
|
51
|
+
##
|
|
52
|
+
# @param [String] name
|
|
53
|
+
# @param [String] value
|
|
54
|
+
#
|
|
55
|
+
def self.new(value)
|
|
56
|
+
super(:param).tap do |new_node|
|
|
57
|
+
case value
|
|
58
|
+
when Nokogiri::XML::Node
|
|
59
|
+
new_node.inherit value
|
|
60
|
+
else
|
|
61
|
+
new_node.value = value
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
# The Header's value
|
|
67
|
+
# @return [String]
|
|
68
|
+
def value
|
|
69
|
+
read_attr :value
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
# Set the Header's value
|
|
73
|
+
# @param [String] value the new value for the param
|
|
74
|
+
def value=(value)
|
|
75
|
+
write_attr :value, value
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def inspect_attributes # :nodoc:
|
|
79
|
+
[:value] + super
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
class Complete
|
|
84
|
+
class Success < Event::Complete::Reason
|
|
85
|
+
register :success, :agi_complete
|
|
86
|
+
|
|
87
|
+
def self.new(options = {})
|
|
88
|
+
super().tap do |new_node|
|
|
89
|
+
case options
|
|
90
|
+
when Nokogiri::XML::Node
|
|
91
|
+
new_node.inherit options
|
|
92
|
+
else
|
|
93
|
+
options.each_pair { |k,v| new_node.send :"#{k}=", v }
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def node_with_name(name)
|
|
99
|
+
n = if self.class.registered_ns
|
|
100
|
+
find_first "ns:#{name}", :ns => self.class.registered_ns
|
|
101
|
+
else
|
|
102
|
+
find_first name
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
unless n
|
|
106
|
+
self << (n = RayoNode.new(name, self.document))
|
|
107
|
+
n.namespace = self.class.registered_ns
|
|
108
|
+
end
|
|
109
|
+
n
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
def code_node
|
|
113
|
+
node_with_name 'code'
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
def result_node
|
|
117
|
+
node_with_name 'result'
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
def data_node
|
|
121
|
+
node_with_name 'data'
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
def code
|
|
125
|
+
code_node.text.to_i
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
def code=(other)
|
|
129
|
+
code_node.content = other
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
def result
|
|
133
|
+
result_node.text.to_i
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
def result=(other)
|
|
137
|
+
result_node.content = other
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
def data
|
|
141
|
+
data_node.text
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
def data=(other)
|
|
145
|
+
data_node.content = other
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
def inspect_attributes
|
|
149
|
+
[:code, :result, :data]
|
|
150
|
+
end
|
|
151
|
+
end
|
|
152
|
+
end # Complete
|
|
153
|
+
end # Command
|
|
154
|
+
end # AGI
|
|
155
|
+
end # Asterisk
|
|
156
|
+
end # Component
|
|
157
|
+
end # Punchblock
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
require 'punchblock/key_value_pair_node'
|
|
2
|
+
|
|
3
|
+
module Punchblock
|
|
4
|
+
module Component
|
|
5
|
+
module Asterisk
|
|
6
|
+
module AMI
|
|
7
|
+
class Action < ComponentNode
|
|
8
|
+
register :action, :ami
|
|
9
|
+
|
|
10
|
+
def self.new(options = {})
|
|
11
|
+
super().tap do |new_node|
|
|
12
|
+
options.each_pair { |k,v| new_node.send :"#{k}=", v }
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def name
|
|
17
|
+
read_attr :name
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def name=(other)
|
|
21
|
+
write_attr :name, other
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
##
|
|
25
|
+
# @return [Hash] hash of key-value pairs of params
|
|
26
|
+
#
|
|
27
|
+
def params_hash
|
|
28
|
+
params.inject({}) do |hash, param|
|
|
29
|
+
hash[param.name] = param.value
|
|
30
|
+
hash
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
##
|
|
35
|
+
# @return [Array[Param]] params
|
|
36
|
+
#
|
|
37
|
+
def params
|
|
38
|
+
find('//ns:param', :ns => self.class.registered_ns).map do |i|
|
|
39
|
+
Param.new i
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
##
|
|
44
|
+
# @param [Hash, Array] params A hash of key-value param pairs, or an array of Param objects
|
|
45
|
+
#
|
|
46
|
+
def params=(params)
|
|
47
|
+
find('//ns:param', :ns => self.class.registered_ns).each &:remove
|
|
48
|
+
if params.is_a? Hash
|
|
49
|
+
params.each_pair { |k,v| self << Param.new(k, v) }
|
|
50
|
+
elsif params.is_a? Array
|
|
51
|
+
[params].flatten.each { |i| self << Param.new(i) }
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def inspect_attributes # :nodoc:
|
|
56
|
+
[:name] + super
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
class Param < RayoNode
|
|
60
|
+
include KeyValuePairNode
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
class Complete
|
|
64
|
+
class Success < Event::Complete::Reason
|
|
65
|
+
register :success, :ami_complete
|
|
66
|
+
|
|
67
|
+
def self.new(options = {})
|
|
68
|
+
super().tap do |new_node|
|
|
69
|
+
case options
|
|
70
|
+
when Nokogiri::XML::Node
|
|
71
|
+
new_node.inherit options
|
|
72
|
+
else
|
|
73
|
+
options.each_pair { |k,v| new_node.send :"#{k}=", v }
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def message_node
|
|
79
|
+
mn = if self.class.registered_ns
|
|
80
|
+
find_first 'ns:message', :ns => self.class.registered_ns
|
|
81
|
+
else
|
|
82
|
+
find_first 'message'
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
unless mn
|
|
86
|
+
self << (mn = RayoNode.new('message', self.document))
|
|
87
|
+
mn.namespace = self.class.registered_ns
|
|
88
|
+
end
|
|
89
|
+
mn
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def message
|
|
93
|
+
message_node.text
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def message=(other)
|
|
97
|
+
message_node.content = other
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
##
|
|
101
|
+
# @return [Hash] hash of key-value pairs of attributes
|
|
102
|
+
#
|
|
103
|
+
def attributes_hash
|
|
104
|
+
attributes.inject({}) do |hash, attribute|
|
|
105
|
+
hash[attribute.name] = attribute.value
|
|
106
|
+
hash
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
##
|
|
111
|
+
# @return [Array[Attribute]] attributes
|
|
112
|
+
#
|
|
113
|
+
def attributes
|
|
114
|
+
find('//ns:attribute', :ns => self.class.registered_ns).map do |i|
|
|
115
|
+
Attribute.new i
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
##
|
|
120
|
+
# @param [Hash, Array] attributes A hash of key-value attribute pairs, or an array of Attribute objects
|
|
121
|
+
#
|
|
122
|
+
def attributes=(attributes)
|
|
123
|
+
find('//ns:attribute', :ns => self.class.registered_ns).each &:remove
|
|
124
|
+
if attributes.is_a? Hash
|
|
125
|
+
attributes.each_pair { |k,v| self << Attribute.new(k, v) }
|
|
126
|
+
elsif attributes.is_a? Array
|
|
127
|
+
[attributes].flatten.each { |i| self << Attribute.new(i) }
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
def inspect_attributes
|
|
132
|
+
[:message, :attributes_hash]
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
class Attribute < RayoNode
|
|
137
|
+
include KeyValuePairNode
|
|
138
|
+
end
|
|
139
|
+
end # Complete
|
|
140
|
+
end # Action
|
|
141
|
+
end # AMI
|
|
142
|
+
end # Asterisk
|
|
143
|
+
end # Component
|
|
144
|
+
end # Punchblock
|