librevox 0.1.1 → 0.2

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -37,8 +37,8 @@ techniques:
37
37
  require 'librevox'
38
38
 
39
39
  class MyInbound < Librevox::Listener::Inbound
40
- def on_event
41
- puts "Got event: #{event.content[:event_name]}"
40
+ def on_event e
41
+ puts "Got event: #{e.content[:event_name]}"
42
42
  end
43
43
 
44
44
  # You can add a hook for a certain event:
@@ -46,6 +46,12 @@ techniques:
46
46
  # It is instance_eval'ed, so you can use your instance methods etc:
47
47
  do_something
48
48
  end
49
+
50
+ # If your hook block takes an argument, a Librevox::Response object for
51
+ # the given event is passed on:
52
+ event :channel_bridge do |e|
53
+ ...
54
+ end
49
55
 
50
56
  def do_something
51
57
  ...
@@ -64,15 +70,17 @@ but it only receives events related to that given session.
64
70
  ### Dialplan
65
71
 
66
72
  When a call is made and Freeswitch connects to the outbound event listener,
67
- the `session` callback is executed. This is where you set up your dialplan:
73
+ `session_initiated` is called. This is where you set up your dialplan:
68
74
 
69
- session do
75
+ def session_initiated
70
76
  answer
71
77
  set "some_var", "some value"
72
78
  playback "path/to/file"
73
79
  hangup
74
80
  end
75
81
 
82
+ All channel variables are available as a hash named `session`.
83
+
76
84
  When using applications that expect a reply, such as `play_and_get_digits`,
77
85
  you have to use callbacks to read the value, as the function itself returns
78
86
  immediately due to the async nature of EventMachine:
data/TODO CHANGED
@@ -1,10 +1,17 @@
1
+ - inbound listener: only subscribe to events w/ hooks, unless `events :all`
2
+ specified
3
+
4
+ - map more commands/applications.
5
+
6
+ - check command/application input and raise ArgumentError, possibly.
7
+
8
+ - filter events
9
+
1
10
  - the execute_app/run_app business might be done better, simpler. e.g.
2
11
  having to pass the block for every command becomes a bit tedious.
3
12
 
4
13
  - move test suite from bacon -> test/unit.
5
14
 
6
- - map more commands/applications.
7
-
8
15
  - test how this works in async mode - I imagine that it might mess with
9
16
  @command_queue
10
17
 
@@ -12,13 +19,7 @@
12
19
  do e.g. originate("user/coltrane", :endpoint => bridge("user/davis")) and
13
20
  it would translate to "originate user/coltrane &bridge(user/davis)"
14
21
 
15
- - add logger.
16
-
17
- - check command/application input and raise ArgumentError.
18
-
19
22
  - maybe let commands handle the response, so something useful could be returned?
20
23
 
21
24
  - possibly catch all exceptions, so everything doesn't die? or should this be
22
25
  be the users responsibilty?
23
-
24
- - filter events
@@ -1,9 +1,27 @@
1
+ require 'logger'
1
2
  require 'eventmachine'
2
3
  require 'librevox/listener/inbound'
3
4
  require 'librevox/listener/outbound'
4
5
 
5
6
  module Librevox
6
- VERSION = "0.1.1"
7
+ VERSION = "0.2"
8
+
9
+ def self.options
10
+ @options ||= {
11
+ :log_file => STDOUT,
12
+ :log_level => Logger::INFO
13
+ }
14
+ end
15
+
16
+ def self.logger
17
+ @logger ||= logger!
18
+ end
19
+
20
+ def self.logger!
21
+ logger = Logger.new(options[:log_file])
22
+ logger.level = options[:log_level]
23
+ logger
24
+ end
7
25
 
8
26
  # When called without a block, it will start the listener that is passed as
9
27
  # first argument:
@@ -17,6 +35,7 @@ module Librevox
17
35
  # run OtherListner
18
36
  # end
19
37
  def self.start(klass=nil, args={}, &block)
38
+ logger.info "Starting Librevox"
20
39
  EM.run {
21
40
  block_given? ? instance_eval(&block) : run(klass, args)
22
41
  }
@@ -27,11 +46,9 @@ module Librevox
27
46
  port = args.delete(:port)
28
47
 
29
48
  if klass.ancestors.include? Librevox::Listener::Inbound
30
- port ||= "8021"
31
- EM.connect host, port, klass, args
49
+ EM.connect host, port || "8021", klass, args
32
50
  elsif klass.ancestors.include? Librevox::Listener::Outbound
33
- port ||= "8084"
34
- EM.start_server host, port, klass, args
51
+ EM.start_server host, port || "8084", klass, args
35
52
  end
36
53
  end
37
54
  end
@@ -8,10 +8,20 @@ module Librevox
8
8
  # Applications *must* pass on any eventual block passed to them.
9
9
  module Applications
10
10
  # Answers an incoming call or session.
11
- def answer(&b)
11
+ # @see http://wiki.freeswitch.org/wiki/Misc._Dialplan_Tools_answer
12
+ def answer &b
12
13
  execute_app "answer", &b
13
14
  end
14
15
 
16
+ # Make an attended transfer
17
+ # @example
18
+ # att_xfer("user/davis")
19
+ # @see http://wiki.freeswitch.org/wiki/Misc._Dialplan_Tools_att_xfer
20
+ # @todo Add support for origination_cancel_key
21
+ def att_xfer endpoint, &b
22
+ execute_app "att_xfer", endpoint, &b
23
+ end
24
+
15
25
  # Binds an application to the specified call legs.
16
26
  # @example
17
27
  # bind_meta_app :key => 2,
@@ -20,28 +30,98 @@ module Librevox
20
30
  # :application => "execute_extension",
21
31
  # :parameters => "dx XML features"
22
32
  # @see http://wiki.freeswitch.org/wiki/Misc._Dialplan_Tools_bind_meta_app
23
- def bind_meta_app(args={}, &b)
24
- key = args[:key]
25
- listen_to = args[:listen_to]
26
- respond_on = args[:respond_on]
27
- application = args[:application]
28
- parameters = args[:parameters] ? "::#{args[:parameters]}" : ""
29
-
30
- arg_string = "%s %s %s %s%s" % [key, listen_to, respond_on, application,
31
- parameters]
33
+ def bind_meta_app args={}, &b
34
+ arg_string =
35
+ args.values_at(:key, :listen_to, :respond_on, :application).join(" ")
36
+ arg_string += "::#{args[:parameters]}" if args[:parameters]
32
37
 
33
38
  execute_app "bind_meta_app", arg_string, &b
34
39
  end
35
40
 
36
- # Bridges an incoming call to an endpoint
41
+
42
+ # Bridges an incoming call to an endpoint, optionally taking an array of
43
+ # channel variables to set. If given an array of arrays, each contained
44
+ # array of endpoints will be called simultaneously, with the next array
45
+ # of endpoints as failover. See the examples below for different constructs
46
+ # and the callstring it sends to FreeSWITCH.
37
47
  # @example
38
48
  # bridge "user/coltrane", "user/backup-office"
49
+ # #=> user/coltrane,user/backup-office
50
+ # @example With channel variables
51
+ # bridge "user/coltrane", "user/backup-office", :some_var => "value"
52
+ # #=> {some_var=value}user/coltrane,user/backup-office
53
+ # @example With failover
54
+ # bridge ['user/coltrane', 'user/davis'], ['user/sun-ra', 'user/taylor']
55
+ # #=> user/coltrane,user/davis|user/sun-ra,user/taylor
39
56
  # @see http://wiki.freeswitch.org/wiki/Misc._Dialplan_Tools_bridgecall
40
- def bridge(*endpoints, &b)
41
- execute_app "bridge", endpoints.join(","), &b
57
+ def bridge *args, &b
58
+ variables = if args.last.is_a? Hash
59
+ # We need to sort the key/value pairs to facilitate testing.
60
+ # This can be removed once 1.8-compat is dropped.
61
+ key_value_pairs = args.pop.sort {|x,y| x.to_s <=> y.to_s}
62
+ key_value_pairs.map! {|k,v| "#{k}=#{v}"}
63
+ "{#{key_value_pairs.join(",")}}"
64
+ else
65
+ ""
66
+ end
67
+
68
+ endpoints = if args.first.is_a? Array
69
+ args.map {|e| e.join(",")}.join("|")
70
+ else
71
+ args.join ","
72
+ end
73
+
74
+ execute_app "bridge", variables + endpoints, &b
75
+ end
76
+
77
+ # Deflect a call by sending a REFER. Takes a SIP URI as argument, rerouting
78
+ # the call to that SIP URI.
79
+ #
80
+ # Beware that REFER only can be used on established calls. If a call hasn't
81
+ # been established with e.g. the {#answer} application, you should use
82
+ # {#redirect} instead.
83
+ # @example
84
+ # deflect "sip:miles@davis.com"
85
+ # @see #redirect
86
+ # @see http://wiki.freeswitch.org/wiki/Misc._Dialplan_Tools_deflect
87
+ def deflect uri, &b
88
+ execute_app "deflect", uri, &b
89
+ end
90
+
91
+ # Exports a channel variable from the A leg to the B leg. Variables and
92
+ # their values will be replicated in any new channels created from the one
93
+ # export was called.
94
+ #
95
+ # Set :local => false if the variable should only be exported to the B-leg.
96
+ #
97
+ # @example
98
+ # export "some_var"
99
+ # @example Only export to B-leg
100
+ # export "some_var", :local => false
101
+ # @see http://wiki.freeswitch.org/wiki/Misc._Dialplan_Tools_export
102
+ def export var, args={}, &b
103
+ nolocal = args[:local] == false ? "nolocal:" : "" # ugly!!111
104
+
105
+ execute_app "export", "#{nolocal}#{var}", &b
106
+ end
107
+
108
+ # Generate TGML tones
109
+ # @example Generate a 500ms beep at 800Hz
110
+ # gentones "%(500,0,800)"
111
+ # @example Generate a DTMF string
112
+ # gentones "0800500005"
113
+ # @see http://wiki.freeswitch.org/wiki/Misc._Dialplan_Tools_gentones
114
+ def gentones tgml, &b
115
+ execute_app "gentones", tgml, &b
42
116
  end
43
117
 
44
- def hangup(cause="", &b)
118
+ # Hang up current channel
119
+ # @example
120
+ # hangup
121
+ # @example Hang up with a reason
122
+ # hangup "USER_BUSY"
123
+ # @see http://wiki.freeswitch.org/wiki/Misc._Dialplan_Tools_hangup
124
+ def hangup cause="", &b
45
125
  execute_app "hangup", cause, &b
46
126
  end
47
127
 
@@ -55,7 +135,7 @@ module Librevox
55
135
  # :timeout => 5000,
56
136
  # :regexp => '\d+'
57
137
  # @see http://wiki.freeswitch.org/wiki/Misc._Dialplan_Tools_play_and_get_digits
58
- def play_and_get_digits(file, invalid_file, args={}, &b)
138
+ def play_and_get_digits file, invalid_file, args={}, &b
59
139
  min = args[:min] || 1
60
140
  max = args[:max] || 2
61
141
  tries = args[:tries] || 3
@@ -76,12 +156,20 @@ module Librevox
76
156
  # @example
77
157
  # playback "/path/to/file.wav"
78
158
  # @see http://wiki.freeswitch.org/wiki/Misc._Dialplan_Tools_playback
79
- def playback(file, &b)
159
+ def playback file, &b
80
160
  execute_app "playback", file, &b
81
161
  end
82
162
 
163
+ # Pre-answer establishes early media but does not answer.
164
+ # @example
165
+ # pre_anser
166
+ # @see http://wiki.freeswitch.org/wiki/Misc._Dialplan_Tools_pre_answer
167
+ def pre_answer &b
168
+ execute_app "pre_answer", &b
169
+ end
170
+
83
171
  # @see http://wiki.freeswitch.org/wiki/Misc._Dialplan_Tools_read
84
- def read(file, args={}, &b)
172
+ def read file, args={}, &b
85
173
  min = args[:min] || 1
86
174
  max = args[:max] || 2
87
175
  terminators = args[:terminators] || "#"
@@ -103,16 +191,31 @@ module Librevox
103
191
  # @example With 20 second limit
104
192
  # record "/path/to/new/file.wac", :limit => 20
105
193
  # @see http://wiki.freeswitch.org/wiki/Misc._Dialplan_Tools_record
106
- def record(path, params={}, &b)
194
+ def record path, params={}, &b
107
195
  args = [path, params[:limit]].compact.join(" ")
108
196
  execute_app "record", args, &b
109
197
  end
110
198
 
199
+ # Redirect a channel to another endpoint. You must take care to not
200
+ # redirect incompatible channels, as that wont have the desired effect.
201
+ # I.e. if you redirect to a SIP URI, it should be a SIP channel.
202
+ #
203
+ # #{redirect} can only be used on non-established calls, i.e. calls that
204
+ # has not been answered with the #{answer} application yet. If the call has
205
+ # been answered, use #{deflect} instead.
206
+ # @example
207
+ # redirect "sip:freddie@hubbard.org"
208
+ # @see #{deflect}
209
+ # @see http://wiki.freeswitch.org/wiki/Misc._Dialplan_Tools_redirect
210
+ def redirect uri, &b
211
+ execute_app "redirect", uri, &b
212
+ end
213
+
111
214
  # Sets a channel variable.
112
215
  # @example
113
216
  # set "some_var", "some value"
114
217
  # @see http://wiki.freeswitch.org/wiki/Misc._Dialplan_Tools_set
115
- def set(variable, value, &b)
218
+ def set variable, value, &b
116
219
  execute_app "set", "#{variable}=#{value}", &b
117
220
  end
118
221
 
@@ -120,8 +223,24 @@ module Librevox
120
223
  # @example
121
224
  # transfer "new_context"
122
225
  # @see http://wiki.freeswitch.org/wiki/Misc._Dialplan_Tools_transfer
123
- def transfer(context, &b)
226
+ def transfer context, &b
124
227
  execute_app "transfer", context, &b
125
228
  end
229
+
230
+ # Unbinds a previously bound key with bind_meta_app
231
+ # @example
232
+ # unbind_meta_app 3
233
+ # @see http://wiki.freeswitch.org/wiki/Misc._Dialplan_Tools_unbind_meta_app
234
+ def unbind_meta_app key, &b
235
+ execute_app "unbind_meta_app", key.to_s, &b
236
+ end
237
+
238
+ # Unset a channel variable.
239
+ # @example
240
+ # unset "foo"
241
+ # @see http://wiki.freeswitch.org/wiki/Misc._Dialplan_Tools_unset
242
+ def unset variable, &b
243
+ execute_app "unset", variable, &b
244
+ end
126
245
  end
127
246
  end
@@ -38,7 +38,7 @@ module Librevox
38
38
 
39
39
  def run_cmd(cmd, &block)
40
40
  send_data "#{cmd}\n\n"
41
- @api_queue << (block || lambda {})
41
+ @command_queue << (block || lambda {})
42
42
  end
43
43
 
44
44
  attr_accessor :response
@@ -46,33 +46,37 @@ module Librevox
46
46
 
47
47
  def post_init
48
48
  @command_delegate = CommandDelegate.new(self)
49
- @api_queue = []
49
+ @command_queue = []
50
50
  end
51
51
 
52
52
  def receive_request(header, content)
53
53
  @response = Librevox::Response.new(header, content)
54
54
 
55
55
  if response.event?
56
- on_event
57
- invoke_event response.event
58
- elsif response.api_response? && @api_queue.any?
59
- invoke_api_queue
56
+ on_event response.dup
57
+ invoke_event_hooks
58
+ elsif response.api_response? && @command_queue.any?
59
+ invoke_command_queue
60
60
  end
61
61
  end
62
62
 
63
63
  # override
64
- def on_event
64
+ def on_event(event)
65
65
  end
66
66
 
67
+ alias :done :close_connection_after_writing
68
+
67
69
  private
68
- def invoke_event(event_name)
69
- self.class.hooks.each do |name,block|
70
- instance_eval(&block) if name == event_name.downcase.to_sym
71
- end
70
+ def invoke_event_hooks
71
+ self.class.hooks.each {|name,block|
72
+ if name == response.event.downcase.to_sym
73
+ instance_exec response.dup, &block
74
+ end
75
+ }
72
76
  end
73
77
 
74
- def invoke_api_queue
75
- block = @api_queue.shift
78
+ def invoke_command_queue
79
+ block = @command_queue.shift
76
80
  block.call(response)
77
81
  end
78
82
  end
@@ -4,14 +4,6 @@ require 'librevox/applications'
4
4
  module Librevox
5
5
  module Listener
6
6
  class Outbound < Base
7
- class << self
8
- attr_reader :session_callback
9
-
10
- def session(&block)
11
- @session_callback = block
12
- end
13
- end
14
-
15
7
  include Librevox::Applications
16
8
 
17
9
  def execute_app(app, args="", params={}, &block)
@@ -25,10 +17,10 @@ module Librevox
25
17
  @read_channel_var = params[:read_var]
26
18
 
27
19
  if @read_channel_var
28
- @command_queue << lambda {update_session}
20
+ @application_queue << lambda {update_session}
29
21
  end
30
22
 
31
- @command_queue << (block || lambda {})
23
+ @application_queue << (block || lambda {})
32
24
  end
33
25
 
34
26
  # This should probably be in Application#sendmsg instead.
@@ -37,46 +29,47 @@ module Librevox
37
29
  end
38
30
 
39
31
  attr_accessor :session
32
+
33
+ # Called when a new session is initiated.
34
+ def session_initiated
35
+ end
40
36
 
41
37
  def post_init
42
38
  super
43
39
  @session = nil
44
- @command_queue = []
40
+ @application_queue = []
45
41
 
46
42
  send_data "connect\n\n"
47
43
  send_data "myevents\n\n"
48
- @command_queue << lambda {}
44
+ @application_queue << lambda {}
49
45
  send_data "linger\n\n"
50
- @command_queue << lambda {}
46
+ @application_queue << lambda {}
51
47
  end
52
48
 
53
49
  def receive_request(*args)
54
50
  super(*args)
55
51
 
56
52
  if session.nil?
57
- @session = response
58
- instance_eval &self.class.session_callback
53
+ @session = response.headers
54
+ session_initiated
59
55
  elsif response.event? && response.event == "CHANNEL_DATA"
60
- @session = response
56
+ @session = response.content
61
57
  resume_with_channel_var
62
58
  elsif response.command_reply? && !response.event?
63
- @command_queue.shift.call if @command_queue.any?
59
+ @application_queue.shift.call if @application_queue.any?
64
60
  end
65
61
  end
66
62
 
67
63
  def resume_with_channel_var
68
64
  if @read_channel_var
69
65
  variable = "variable_#{@read_channel_var}".to_sym
70
- value = @session.content[variable]
71
- @command_queue.shift.call(value) if @command_queue.any?
66
+ value = @session[variable]
67
+ @application_queue.shift.call(value) if @application_queue.any?
72
68
  end
73
69
  end
74
70
 
75
71
  def update_session
76
- send_data("api uuid_dump #{session.headers[:unique_id]}\n\n")
77
- end
78
-
79
- def session_initiated
72
+ send_data("api uuid_dump #{session[:unique_id]}\n\n")
80
73
  end
81
74
  end
82
75
  end
@@ -1,7 +1,7 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = "librevox"
3
- s.version = "0.1.1"
4
- s.date = "2010-01-05"
3
+ s.version = "0.2"
4
+ s.date = "2010-01-26"
5
5
  s.summary = "Ruby library for interacting with FreeSWITCH."
6
6
  s.email = "harry@vangberg.name"
7
7
  s.homepage = "http://github.com/ichverstehe/librevox"
@@ -25,13 +25,18 @@ shared "events" do
25
25
 
26
26
  @class.event(:some_event) {send_data "something"}
27
27
  @class.event(:other_event) {send_data "something else"}
28
+ @class.event(:hook_with_arg) {|e| send_data "got event arg: #{e.object_id}"}
29
+
30
+ def @listener.on_event(e)
31
+ send_data "from on_event: #{e.object_id}"
32
+ end
28
33
 
29
34
  # Establish session
30
35
  @listener.receive_data("Content-Length: 0\nTest: Testing\n\n")
31
36
  end
32
37
 
33
38
  should "add event hook" do
34
- @class.hooks.size.should == 2
39
+ @class.hooks.size.should == 3
35
40
  end
36
41
 
37
42
  should "execute callback for event" do
@@ -42,11 +47,28 @@ shared "events" do
42
47
  @listener.read_data.should == "something"
43
48
  end
44
49
 
50
+ should "pass response duplicate as arg to hook block" do
51
+ @listener.receive_data("Content-Length: 25\n\nEvent-Name: HOOK_WITH_ARG\n\n")
52
+ reply = @listener.read_data
53
+ reply.should =~ /^got event arg: /
54
+ reply.should.not =~ /^got event arg: #{@listener.response.object_id}$/
55
+ end
56
+
45
57
  should "expose response as event" do
46
58
  @listener.receive_data("Content-Length: 23\n\nEvent-Name: OTHER_EVENT\n\n")
47
59
  @listener.event.class.should == Librevox::Response
48
60
  @listener.event.content[:event_name].should == "OTHER_EVENT"
49
61
  end
62
+
63
+ should "call on_event" do
64
+ @listener.receive_data("Content-Length: 23\n\nEvent-Name: THIRD_EVENT\n\n")
65
+ @listener.read_data.should =~ /^from on_event/
66
+ end
67
+
68
+ should "call on_event with response duplicate as argument" do
69
+ @listener.receive_data("Content-Length: 23\n\nEvent-Name: THIRD_EVENT\n\n")
70
+ @listener.read_data.should.not =~ /^from on_event: #{@listener.response.object_id}$/
71
+ end
50
72
  end
51
73
 
52
74
  module Librevox::Commands
@@ -66,6 +88,9 @@ shared "api commands" do
66
88
  describe "multiple api commands" do
67
89
  before do
68
90
  @listener.outgoing_data.clear
91
+
92
+ def @listener.on_event(e) end # Don't send anything, kthx.
93
+
69
94
  @class.event(:api_test) {
70
95
  api :sample_cmd, "foo" do
71
96
  api :sample_cmd, "foo", "bar baz"
@@ -10,7 +10,7 @@ module Librevox::Applications
10
10
  end
11
11
 
12
12
  class OutboundTestListener < Librevox::Listener::Outbound
13
- session do
13
+ def session_initiated
14
14
  send_data "session was initiated"
15
15
  end
16
16
  end
@@ -34,7 +34,7 @@ describe "Outbound listener" do
34
34
  end
35
35
 
36
36
  should "establish a session" do
37
- @listener.session.class.should.equal Librevox::Response
37
+ @listener.session.class.should.equal Hash
38
38
  end
39
39
 
40
40
  should "call session callback after establishing new session" do
@@ -42,7 +42,7 @@ describe "Outbound listener" do
42
42
  end
43
43
 
44
44
  should "make channel variables available through session" do
45
- @listener.session.headers[:caller_caller_id_number].should.equal "8675309"
45
+ @listener.session[:caller_caller_id_number].should.equal "8675309"
46
46
  end
47
47
 
48
48
  behaves_like "events"
@@ -54,7 +54,7 @@ describe "Outbound listener" do
54
54
  end
55
55
 
56
56
  class OutboundListenerWithNestedApps < Librevox::Listener::Outbound
57
- session do
57
+ def session_initiated
58
58
  sample_app "foo" do
59
59
  sample_app "bar"
60
60
  end
@@ -106,7 +106,7 @@ module Librevox::Applications
106
106
  end
107
107
 
108
108
  class OutboundListenerWithReader < Librevox::Listener::Outbound
109
- session do
109
+ def session_initiated
110
110
  reader_app do |data|
111
111
  send_data "read this: #{data}"
112
112
  end
@@ -136,7 +136,7 @@ describe "Outbound listener with app reading data" do
136
136
  should "update session with new data" do
137
137
  @listener.receive_data("Content-Type: command/reply\nContent-Length: 3\n\n+OK\n\n")
138
138
  @listener.receive_data("Content-Type: command/reply\nContent-Length: 44\n\nEvent-Name: CHANNEL_DATA\nSession-Var: Second\n\n")
139
- @listener.session.content[:session_var].should == "Second"
139
+ @listener.session[:session_var].should == "Second"
140
140
  end
141
141
 
142
142
  should "pass value of channel variable to block" do
@@ -148,7 +148,7 @@ end
148
148
 
149
149
  class OutboundListenerWithNonNestedApps < Librevox::Listener::Outbound
150
150
  attr_reader :queue
151
- session do
151
+ def session_initiated
152
152
  sample_app "foo"
153
153
  reader_app do |data|
154
154
  send_data "the end: #{data}"
@@ -190,7 +190,7 @@ module Librevox::Commands
190
190
  end
191
191
 
192
192
  class OutboundListenerWithAppsAndApi < Librevox::Listener::Outbound
193
- session do
193
+ def session_initiated
194
194
  sample_app "foo" do
195
195
  api :sample_cmd, "bar" do
196
196
  sample_app "baz"
@@ -1,7 +1,7 @@
1
1
  require 'spec/helper'
2
2
  require 'librevox/applications'
3
3
 
4
- module ApplicationTest
4
+ module AppTest
5
5
  include Librevox::Applications
6
6
 
7
7
  extend self
@@ -17,16 +17,24 @@ module ApplicationTest
17
17
  end
18
18
 
19
19
  describe Librevox::Applications do
20
- A = ApplicationTest
20
+ describe "answer" do
21
+ should "answer" do
22
+ app = AppTest.answer
23
+ app[:name].should == "answer"
24
+ end
25
+ end
21
26
 
22
- should "answer" do
23
- app = A.answer
24
- app[:name].should == "answer"
27
+ describe "att_xfer" do
28
+ should "transfer to endpoint" do
29
+ app = AppTest.att_xfer("user/davis")
30
+ app[:name].should == "att_xfer"
31
+ app[:args].should == "user/davis"
32
+ end
25
33
  end
26
34
 
27
35
  describe "bind_meta_app" do
28
36
  should "bind meta app" do
29
- app = A.bind_meta_app :key => "2",
37
+ app = AppTest.bind_meta_app :key => "2",
30
38
  :listen_to => :a,
31
39
  :respond_on => :s,
32
40
  :application => "hangup"
@@ -36,7 +44,7 @@ describe Librevox::Applications do
36
44
  end
37
45
 
38
46
  should "bind meta app with parameters" do
39
- app = A.bind_meta_app :key => "2",
47
+ app = AppTest.bind_meta_app :key => "2",
40
48
  :listen_to => :a,
41
49
  :respond_on => :s,
42
50
  :application => "execute_extension",
@@ -47,33 +55,85 @@ describe Librevox::Applications do
47
55
  end
48
56
  end
49
57
 
50
- should "bridge" do
51
- app = A.bridge('user/coltrane')
52
- app[:name].should == "bridge"
53
- app[:args].should == 'user/coltrane'
58
+ describe "bridge" do
59
+ should "bridge to endpoints" do
60
+ app = AppTest.bridge('user/coltrane')
61
+ app[:name].should == "bridge"
62
+ app[:args].should == 'user/coltrane'
63
+
64
+ app = AppTest.bridge('user/coltrane', 'user/davis')
65
+ app[:args].should == 'user/coltrane,user/davis'
66
+ end
67
+
68
+ should "bridge with variables" do
69
+ app = AppTest.bridge('user/coltrane', 'user/davis', :foo => 'bar', :lol => 'cat')
70
+ app[:name].should == "bridge"
71
+
72
+ # fragile. hashes are not ordered in ruby 1.8
73
+ app[:args].should == "{foo=bar,lol=cat}user/coltrane,user/davis"
74
+ end
75
+
76
+ should "bridge with failover" do
77
+ app = AppTest.bridge(
78
+ ['user/coltrane', 'user/davis'], ['user/sun-ra', 'user/taylor']
79
+ )
80
+
81
+ app[:name].should == "bridge"
82
+ app[:args].should == "user/coltrane,user/davis|user/sun-ra,user/taylor"
83
+ end
84
+
85
+ # should "bridge with per endpoint variables" do
86
+ # end
87
+ end
88
+
89
+ describe "deflect" do
90
+ should "deflect call" do
91
+ app = AppTest.deflect "sip:miles@davis.org"
92
+ app[:name].should == "deflect"
93
+ app[:args].should == "sip:miles@davis.org"
94
+ end
95
+ end
96
+
97
+ describe "export" do
98
+ should "export variable" do
99
+ app = AppTest.export 'some_var'
100
+ app[:name].should == "export"
101
+ app[:args].should == "some_var"
102
+ end
54
103
 
55
- app = A.bridge('user/coltrane', 'user/davis')
56
- app[:args].should == 'user/coltrane,user/davis'
104
+ should "only export to b-leg " do
105
+ app = AppTest.export 'some_var', :local => false
106
+ app[:name].should == "export"
107
+ app[:args].should == "nolocal:some_var"
108
+ end
109
+ end
110
+
111
+ describe "gentones" do
112
+ should "generate tones" do
113
+ app = AppTest.gentones("%(500,0,800)")
114
+ app[:name].should == "gentones"
115
+ app[:args].should == "%(500,0,800)"
116
+ end
57
117
  end
58
118
 
59
119
  should "hangup" do
60
- app = A.hangup
120
+ app = AppTest.hangup
61
121
  app[:name].should == "hangup"
62
122
 
63
- app = A.hangup("some cause")
123
+ app = AppTest.hangup("some cause")
64
124
  app[:args].should == "some cause"
65
125
  end
66
126
 
67
127
  describe "play_and_get_digits" do
68
128
  should "have defaults" do
69
- app = A.play_and_get_digits "please-enter", "wrong-try-again"
129
+ app = AppTest.play_and_get_digits "please-enter", "wrong-try-again"
70
130
  app[:name].should == "play_and_get_digits"
71
131
  app[:args].should == "1 2 3 5000 # please-enter wrong-try-again read_digits_var \\d+"
72
132
  app[:params][:read_var].should == "read_digits_var"
73
133
  end
74
134
 
75
135
  should "take params" do
76
- app = A.play_and_get_digits "please-enter", "invalid-choice",
136
+ app = AppTest.play_and_get_digits "please-enter", "invalid-choice",
77
137
  :min => 2,
78
138
  :max => 3,
79
139
  :tries => 4,
@@ -88,21 +148,28 @@ describe Librevox::Applications do
88
148
  end
89
149
 
90
150
  should "playback" do
91
- app = A.playback("uri://some/file.wav")
151
+ app = AppTest.playback("uri://some/file.wav")
92
152
  app[:name].should == "playback"
93
153
  app[:args].should == "uri://some/file.wav"
94
154
  end
95
155
 
156
+ describe "pre_answer" do
157
+ should "pre_answer" do
158
+ app = AppTest.pre_answer
159
+ app[:name].should == "pre_answer"
160
+ end
161
+ end
162
+
96
163
  describe "read" do
97
164
  should "read with defaults" do
98
- app = A.read "please-enter.wav"
165
+ app = AppTest.read "please-enter.wav"
99
166
  app[:name].should == "read"
100
167
  app[:args].should == "1 2 please-enter.wav read_digits_var 5000 #"
101
168
  app[:params][:read_var].should == "read_digits_var"
102
169
  end
103
170
 
104
171
  should "take params" do
105
- app = A.read "please-enter.wav",
172
+ app = AppTest.read "please-enter.wav",
106
173
  :min => 2,
107
174
  :max => 3,
108
175
  :terminators => "0",
@@ -116,27 +183,51 @@ describe Librevox::Applications do
116
183
 
117
184
  describe "record" do
118
185
  should "start recording" do
119
- app = A.record "/path/to/file.mp3"
186
+ app = AppTest.record "/path/to/file.mp3"
120
187
  app[:name].should == "record"
121
188
  app[:args].should == "/path/to/file.mp3"
122
189
  end
123
190
 
124
191
  should "start recording with time limit" do
125
- app = A.record "/path/to/file.mp3", :limit => 15
192
+ app = AppTest.record "/path/to/file.mp3", :limit => 15
126
193
  app[:name].should == "record"
127
194
  app[:args].should == "/path/to/file.mp3 15"
128
195
  end
129
196
  end
130
197
 
198
+ describe "redirect" do
199
+ should "redirect to URI" do
200
+ app = AppTest.redirect("sip:miles@davis.org")
201
+ app[:name].should == "redirect"
202
+ app[:args].should == "sip:miles@davis.org"
203
+ end
204
+ end
205
+
131
206
  should "set" do
132
- app = A.set("foo", "bar")
207
+ app = AppTest.set("foo", "bar")
133
208
  app[:name].should == "set"
134
209
  app[:args].should == "foo=bar"
135
210
  end
136
211
 
137
212
  should "transfer" do
138
- app = A.transfer "new_extension"
213
+ app = AppTest.transfer "new_extension"
139
214
  app[:name].should == "transfer"
140
215
  app[:args].should == "new_extension"
141
216
  end
217
+
218
+ describe "unbind_meta_app" do
219
+ should "unbind" do
220
+ app = AppTest.unbind_meta_app 3
221
+ app[:name].should == "unbind_meta_app"
222
+ app[:args].should == "3"
223
+ end
224
+ end
225
+
226
+ describe "unset" do
227
+ should "unset a variable" do
228
+ app = AppTest.unset('foo')
229
+ app[:name].should == "unset"
230
+ app[:args].should == "foo"
231
+ end
232
+ end
142
233
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: librevox
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: "0.2"
5
5
  platform: ruby
6
6
  authors:
7
7
  - Harry Vangberg
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2010-01-05 00:00:00 +01:00
12
+ date: 2010-01-26 00:00:00 +01:00
13
13
  default_executable:
14
14
  dependencies: []
15
15