punchblock 0.5.1 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|