freeswitcher 0.0.13 → 0.1.3
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/examples/play_and_get_test.rb +35 -0
- data/lib/fsr.rb +1 -1
- data/lib/fsr/app/limit.rb +19 -0
- data/lib/fsr/app/play_and_get_digits.rb +30 -0
- data/lib/fsr/cmd/calls.rb +46 -0
- data/lib/fsr/listener/outbound.rb +13 -2
- data/lib/fsr/model/call.rb +48 -0
- data/spec/fsr/app/limit.rb +26 -0
- data/spec/fsr/app/play_and_get_digits.rb +12 -0
- data/spec/fsr/cmd/calls.rb +13 -0
- data/spec/fsr/loading.rb +2 -2
- metadata +11 -2
@@ -0,0 +1,35 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require File.join(File.dirname(__FILE__), "..", 'lib', 'fsr')
|
4
|
+
require "fsr/listener/outbound"
|
5
|
+
$stdout.flush
|
6
|
+
|
7
|
+
FSR.load_all_applications
|
8
|
+
FSR.load_all_commands
|
9
|
+
class PlayAndGetTest < FSR::Listener::Outbound
|
10
|
+
|
11
|
+
def session_initiated
|
12
|
+
exten = @session.headers[:caller_caller_id_number]
|
13
|
+
FSR::Log.info "*** Answering incoming call from #{exten}"
|
14
|
+
answer # Answer the call
|
15
|
+
end
|
16
|
+
|
17
|
+
def receive_reply(reply)
|
18
|
+
exten = @session.headers[:caller_caller_id_number]
|
19
|
+
case @step
|
20
|
+
when 1
|
21
|
+
FSR::Log.info "*** Reading dtmf for #{exten}"
|
22
|
+
play_and_get_digits "tone_stream://%(10000,0,350,440)","/home/freeswitch/freeswitch/sounds/en/us/callie/misc/8000/error.wav",2,10,3,7000,["#"],"test", "\d+" # play_and_get_digits test
|
23
|
+
when 2
|
24
|
+
FSR::Log.info "*** updating session for #{exten}"
|
25
|
+
update_session
|
26
|
+
when 3
|
27
|
+
FSR::Log.info "** Success, grabbed #{@session.headers[:variable_test]} from #{exten}"
|
28
|
+
FSR::Log.info "*** Hanging up call"
|
29
|
+
hangup # Hangup the call
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
|
35
|
+
FSR.start_oes! PlayAndGetTest, :port => 8084, :host => "127.0.0.1"
|
data/lib/fsr.rb
CHANGED
@@ -0,0 +1,19 @@
|
|
1
|
+
require "fsr/app"
|
2
|
+
module FSR
|
3
|
+
module App
|
4
|
+
class Limit < Application
|
5
|
+
|
6
|
+
def initialize(id = nil, realm = "$${domain}", limit = 5)
|
7
|
+
@realm, @id, @limit = realm, id, limit
|
8
|
+
raise "Must supply a valid id" if @id.nil?
|
9
|
+
end
|
10
|
+
|
11
|
+
def arguments
|
12
|
+
[@realm, @id, @limit]
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
16
|
+
|
17
|
+
register(:limit, Limit)
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require "fsr/app"
|
2
|
+
module FSR
|
3
|
+
#http://wiki.freeswitch.org/wiki/Misc._Dialplan_Tools_play_and_get_digits
|
4
|
+
module App
|
5
|
+
class PlayAndGetDigits < Application
|
6
|
+
def initialize(sound_file, invalid_file, min = 0, max = 10, tries = 3, timeout = 7000, terminators = ["#"], chan_var = "fsr_read_dtmf", regexp = "\d")
|
7
|
+
@sound_file = sound_file
|
8
|
+
@invalid_file = invalid_file
|
9
|
+
@min = min
|
10
|
+
@max = max
|
11
|
+
@tries = tries
|
12
|
+
@timeout = timeout
|
13
|
+
@chan_var = chan_var
|
14
|
+
@terminators = terminators
|
15
|
+
@regexp = regexp
|
16
|
+
end
|
17
|
+
|
18
|
+
def arguments
|
19
|
+
[@min, @max, @tries, @timeout, @terminators.join(","), @sound_file, @invalid_file, @chan_var, @regexp]
|
20
|
+
end
|
21
|
+
|
22
|
+
def sendmsg
|
23
|
+
"call-command: execute\nexecute-app-name: %s\nexecute-app-arg: %s\nevent-lock:true\n\n" % ["play_and_get_digits", arguments.join(" ")]
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
|
28
|
+
register(:play_and_get_digits, PlayAndGetDigits)
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require "fsr/app"
|
2
|
+
module FSR
|
3
|
+
module Cmd
|
4
|
+
class Calls < Command
|
5
|
+
|
6
|
+
include Enumerable
|
7
|
+
def each(&block)
|
8
|
+
@calls ||= run
|
9
|
+
if @calls
|
10
|
+
@calls.each { |call| yield call }
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def initialize(fs_socket = nil)
|
15
|
+
@fs_socket = fs_socket # FSR::CommandSocket obj
|
16
|
+
end
|
17
|
+
|
18
|
+
# Send the command to the event socket, using bgapi by default.
|
19
|
+
def run(api_method = :api)
|
20
|
+
orig_command = "%s %s" % [api_method, raw]
|
21
|
+
Log.debug "saying #{orig_command}"
|
22
|
+
resp = @fs_socket.say(orig_command)
|
23
|
+
unless resp["body"] == "0 total."
|
24
|
+
call_info, count = resp["body"].split("\n\n")
|
25
|
+
require "fsr/model/call"
|
26
|
+
begin
|
27
|
+
require "fastercsv"
|
28
|
+
calls = FCSV.parse(call_info)
|
29
|
+
rescue LoadError
|
30
|
+
require "csv"
|
31
|
+
calls = CSV.parse(call_info)
|
32
|
+
end
|
33
|
+
return calls[1 .. -1].map { |c| FSR::Model::Call.new(*c) }
|
34
|
+
end
|
35
|
+
nil
|
36
|
+
end
|
37
|
+
|
38
|
+
# This method builds the API command to send to the freeswitch event socket
|
39
|
+
def raw
|
40
|
+
orig_command = "show calls"
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
register(:calls, Calls)
|
45
|
+
end
|
46
|
+
end
|
@@ -31,7 +31,6 @@ module FSR
|
|
31
31
|
# @param reply This HeaderAndContent instance will have the channel variables
|
32
32
|
# in #content, if the session has been updated
|
33
33
|
def receive_reply(reply)
|
34
|
-
FSR::Log.warn "#{self.class.name}#receive_reply not overwritten"
|
35
34
|
FSR::Log.debug reply.inspect
|
36
35
|
end
|
37
36
|
|
@@ -53,9 +52,15 @@ module FSR
|
|
53
52
|
send_data("api uuid_dump #{@session.headers[:unique_id]}\n\n")
|
54
53
|
end
|
55
54
|
|
55
|
+
def next_step
|
56
|
+
@step += 1
|
57
|
+
receive_reply(@session)
|
58
|
+
end
|
59
|
+
|
56
60
|
protected
|
57
61
|
def post_init
|
58
62
|
@session = nil # holds the session object
|
63
|
+
@stack = [] # Keep track of stack for state machine
|
59
64
|
send_data("connect\n\n")
|
60
65
|
FSR::Log.debug "Accepting connections."
|
61
66
|
end
|
@@ -83,20 +88,26 @@ module FSR
|
|
83
88
|
session_header_and_content = HeaderAndContentResponse.new({:headers => hash_header.merge(hash_content.strip_value_newlines), :content => {}})
|
84
89
|
@session = session_header_and_content
|
85
90
|
@step += 1
|
91
|
+
@stack.pop.call unless @stack.empty?
|
86
92
|
receive_reply(hash_header)
|
87
93
|
end
|
88
94
|
else
|
89
95
|
@step += 1
|
96
|
+
@stack.pop.call unless @stack.empty?
|
90
97
|
receive_reply(session_header_and_content)
|
91
98
|
end
|
92
99
|
end
|
93
100
|
|
101
|
+
def cmd(&block)
|
102
|
+
@stack << block
|
103
|
+
end
|
104
|
+
|
94
105
|
end
|
95
106
|
end
|
96
107
|
end
|
97
108
|
|
98
109
|
class Hash
|
99
110
|
def strip_value_newlines
|
100
|
-
Hash[self.map { |k,v| v.respond_to?(:to_s) ? [k, v.to_s.strip] : [k, v] }]
|
111
|
+
Hash[*(self.map { |k,v| v.respond_to?(:to_s) ? [k, v.to_s.strip] : [k, v] }.flatten)]
|
101
112
|
end
|
102
113
|
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module FSR
|
2
|
+
module Model
|
3
|
+
class Call
|
4
|
+
attr_reader :created, :created_epoch, :function, :caller_id_name, :caller_id_number,
|
5
|
+
:caller_destination, :caller_channel_name, :caller_uuid, :callee_id_name,
|
6
|
+
:callee_id_number, :callee_destination, :callee_channel_name, :callee_uuid
|
7
|
+
def initialize(created,
|
8
|
+
created_epoch,
|
9
|
+
function,
|
10
|
+
caller_cid_name,
|
11
|
+
caller_cid_num,
|
12
|
+
caller_dest_num,
|
13
|
+
caller_chan_name,
|
14
|
+
caller_uuid,
|
15
|
+
callee_cid_name,
|
16
|
+
callee_cid_num,
|
17
|
+
callee_dest_num,
|
18
|
+
callee_chan_name,
|
19
|
+
callee_uuid)
|
20
|
+
@created,
|
21
|
+
@created_epoch,
|
22
|
+
@function,
|
23
|
+
@caller_id_name,
|
24
|
+
@caller_id_number,
|
25
|
+
@caller_destination,
|
26
|
+
@caller_chan_name,
|
27
|
+
@caller_uuid,
|
28
|
+
@callee_id_name,
|
29
|
+
@callee_id_number,
|
30
|
+
@callee_destination,
|
31
|
+
@callee_channel_name,
|
32
|
+
@callee_uuid = created,
|
33
|
+
created_epoch,
|
34
|
+
function,
|
35
|
+
caller_cid_name,
|
36
|
+
caller_cid_num,
|
37
|
+
caller_dest_num,
|
38
|
+
caller_chan_name,
|
39
|
+
caller_uuid,
|
40
|
+
callee_cid_name,
|
41
|
+
callee_cid_num,
|
42
|
+
callee_dest_num,
|
43
|
+
callee_chan_name,
|
44
|
+
callee_uuid
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'spec/helper'
|
2
|
+
require "fsr/app"
|
3
|
+
FSR::App.load_application("limit")
|
4
|
+
|
5
|
+
describe "Testing FSR::App::Limit" do
|
6
|
+
## Calls ##
|
7
|
+
# Interface to calls
|
8
|
+
it "FSR::App::Limit should send proper limit command only passing an id" do
|
9
|
+
limit = FSR::App::Limit.new("fsr_caller")
|
10
|
+
limit.raw.should == "limit($${domain} fsr_caller 5)"
|
11
|
+
limit.sendmsg.should == "call-command: execute\nexecute-app-name: limit\nexecute-app-arg: $${domain} fsr_caller 5\n\n"
|
12
|
+
end
|
13
|
+
|
14
|
+
it "FSR::App::Limit should send proper limit command passing id and realm" do
|
15
|
+
limit = FSR::App::Limit.new("fsr_caller", "foodomain")
|
16
|
+
limit.raw.should == "limit(foodomain fsr_caller 5)"
|
17
|
+
limit.sendmsg.should == "call-command: execute\nexecute-app-name: limit\nexecute-app-arg: foodomain fsr_caller 5\n\n"
|
18
|
+
end
|
19
|
+
|
20
|
+
it "FSR::App::Limit should send proper limit command passing id, realm, and limit" do
|
21
|
+
limit = FSR::App::Limit.new("fsr_caller", "foodomain", 10)
|
22
|
+
limit.raw.should == "limit(foodomain fsr_caller 10)"
|
23
|
+
limit.sendmsg.should == "call-command: execute\nexecute-app-name: limit\nexecute-app-arg: foodomain fsr_caller 10\n\n"
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
require 'spec/helper'
|
2
|
+
require "fsr/app"
|
3
|
+
FSR::App.load_application("play_and_get_digits")
|
4
|
+
|
5
|
+
describe "Testing FSR::App::PlayAndGetDigits" do
|
6
|
+
# Utilize the [] shortcut to start a conference
|
7
|
+
it "Send a play_and_gets_digits command" do
|
8
|
+
tmp = FSR::App::PlayAndGetDigits.new("soundfile.wav", "invalid.wav")
|
9
|
+
tmp.sendmsg.should == "call-command: execute\nexecute-app-name: play_and_get_digits\nexecute-app-arg: 0 10 3 7000 # soundfile.wav invalid.wav fsr_read_dtmf d\nevent-lock:true\n\n"
|
10
|
+
end
|
11
|
+
|
12
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'spec/helper'
|
2
|
+
require "fsr/cmd"
|
3
|
+
FSR::Cmd.load_command("calls")
|
4
|
+
|
5
|
+
describe "Testing FSR::Cmd::Calls" do
|
6
|
+
## Calls ##
|
7
|
+
# Interface to calls
|
8
|
+
it "FSR::Cmd::Calls should send show calls" do
|
9
|
+
sofia = FSR::Cmd::Calls.new
|
10
|
+
sofia.raw.should == "show calls"
|
11
|
+
end
|
12
|
+
|
13
|
+
end
|
data/spec/fsr/loading.rb
CHANGED
@@ -4,7 +4,7 @@ require 'spec/helper'
|
|
4
4
|
describe "Testing FSR module loading methods" do
|
5
5
|
# When you add applications you must modify the expected apps_loaded behavior
|
6
6
|
it "Loads all applications" do
|
7
|
-
all_apps = [:uuid_dump, :uuid_setvar, :uuid_getvar, :read, :set, :transfer, :speak, :fs_sleep, :playback, :answer, :fifo, :bridge, :hangup, :conference, :fs_break, :log]
|
7
|
+
all_apps = [:play_and_get_digits, :uuid_dump, :uuid_setvar, :uuid_getvar, :read, :set, :transfer, :speak, :fs_sleep, :playback, :answer, :fifo, :bridge, :hangup, :conference, :fs_break, :log, :limit]
|
8
8
|
# Add any apps which will load to this set
|
9
9
|
apps_loaded = FSR.load_all_applications
|
10
10
|
apps_loaded.kind_of?(Array).should == true
|
@@ -16,7 +16,7 @@ describe "Testing FSR module loading methods" do
|
|
16
16
|
|
17
17
|
# When you add commands you must modify the expected cmds_loaded behavior
|
18
18
|
it "Loads all commands" do
|
19
|
-
all_commands = [:originate, :sofia, :fsctl, :sofia_contact, :status] # If you add a command add it to this set
|
19
|
+
all_commands = [:originate, :sofia, :fsctl, :sofia_contact, :status, :calls] # If you add a command add it to this set
|
20
20
|
cmds_loaded = FSR.load_all_commands
|
21
21
|
cmds_loaded.kind_of?(Array).should == true
|
22
22
|
all_commands.each do |cmd|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: freeswitcher
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.1.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jayson Vaughn
|
@@ -12,7 +12,7 @@ autorequire:
|
|
12
12
|
bindir: bin
|
13
13
|
cert_chain: []
|
14
14
|
|
15
|
-
date: 2009-04
|
15
|
+
date: 2009-05-04 00:00:00 -05:00
|
16
16
|
default_executable:
|
17
17
|
dependencies:
|
18
18
|
- !ruby/object:Gem::Dependency
|
@@ -43,6 +43,7 @@ files:
|
|
43
43
|
- examples/ies_demo.rb
|
44
44
|
- examples/ies_demo_with_hook.rb
|
45
45
|
- examples/oes_demo.rb
|
46
|
+
- examples/play_and_get_test.rb
|
46
47
|
- lib
|
47
48
|
- lib/fsr
|
48
49
|
- lib/fsr/app
|
@@ -53,7 +54,9 @@ files:
|
|
53
54
|
- lib/fsr/app/fs_break.rb
|
54
55
|
- lib/fsr/app/fs_sleep.rb
|
55
56
|
- lib/fsr/app/hangup.rb
|
57
|
+
- lib/fsr/app/limit.rb
|
56
58
|
- lib/fsr/app/log.rb
|
59
|
+
- lib/fsr/app/play_and_get_digits.rb
|
57
60
|
- lib/fsr/app/playback.rb
|
58
61
|
- lib/fsr/app/read.rb
|
59
62
|
- lib/fsr/app/set.rb
|
@@ -64,6 +67,7 @@ files:
|
|
64
67
|
- lib/fsr/app/uuid_setvar.rb
|
65
68
|
- lib/fsr/app.rb
|
66
69
|
- lib/fsr/cmd
|
70
|
+
- lib/fsr/cmd/calls.rb
|
67
71
|
- lib/fsr/cmd/fsctl.rb
|
68
72
|
- lib/fsr/cmd/originate.rb
|
69
73
|
- lib/fsr/cmd/sofia
|
@@ -91,6 +95,8 @@ files:
|
|
91
95
|
- lib/fsr/listener/outbound.rb
|
92
96
|
- lib/fsr/listener/outbound.rb.orig
|
93
97
|
- lib/fsr/listener.rb
|
98
|
+
- lib/fsr/model
|
99
|
+
- lib/fsr/model/call.rb
|
94
100
|
- lib/fsr.rb
|
95
101
|
- tasks
|
96
102
|
- tasks/package.rake
|
@@ -259,12 +265,15 @@ test_files:
|
|
259
265
|
- spec/fsr/app/conference.rb
|
260
266
|
- spec/fsr/app/fifo.rb
|
261
267
|
- spec/fsr/app/hangup.rb
|
268
|
+
- spec/fsr/app/limit.rb
|
262
269
|
- spec/fsr/app/log.rb
|
270
|
+
- spec/fsr/app/play_and_get_digits.rb
|
263
271
|
- spec/fsr/app/playback.rb
|
264
272
|
- spec/fsr/app/set.rb
|
265
273
|
- spec/fsr/app/transfer.rb
|
266
274
|
- spec/fsr/app.rb
|
267
275
|
- spec/fsr/cmd
|
276
|
+
- spec/fsr/cmd/calls.rb
|
268
277
|
- spec/fsr/cmd/originate.rb
|
269
278
|
- spec/fsr/cmd/sofia
|
270
279
|
- spec/fsr/cmd/sofia/profile.rb
|