bougyman-freeswitcher 0.0.9 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README +45 -4
- data/{bin → examples/bin}/cmd_demo.rb +0 -0
- data/examples/bin/dtmf_test.rb +38 -0
- data/{bin → examples/bin}/ies_demo.rb +0 -0
- data/{bin → examples/bin}/ies_demo_with_hook.rb +0 -2
- data/{bin → examples/bin}/oes_demo.rb +0 -0
- data/examples/dtmf_test.rb +35 -0
- data/examples/ies_demo.rb +19 -0
- data/examples/ies_demo_with_hook.rb +25 -0
- data/examples/oes_demo.rb +21 -0
- data/examples/play_and_get_test.rb +35 -0
- data/lib/fsr.rb +1 -1
- data/lib/fsr/app/hangup.rb +3 -3
- data/lib/fsr/app/play_and_get_digits.rb +30 -0
- data/lib/fsr/app/playback.rb +2 -3
- data/lib/fsr/app/read.rb +22 -0
- data/lib/fsr/app/transfer.rb +2 -2
- data/lib/fsr/app/uuid_dump.rb +22 -0
- data/lib/fsr/app/uuid_getvar.rb +23 -0
- data/lib/fsr/app/uuid_setvar.rb +24 -0
- data/lib/fsr/cmd/calls.rb +46 -0
- data/lib/fsr/listener/outbound.rb +65 -25
- data/lib/fsr/listener/outbound.rb.orig +131 -0
- data/lib/fsr/model/call.rb +48 -0
- data/spec/fsr/app/hangup.rb +16 -0
- data/spec/fsr/app/log.rb +11 -0
- data/spec/fsr/app/play_and_get_digits.rb +12 -0
- data/spec/fsr/app/playback.rb +11 -0
- data/spec/fsr/app/set.rb +12 -0
- data/spec/fsr/app/transfer.rb +11 -0
- data/spec/fsr/cmd/calls.rb +13 -0
- data/spec/fsr/listener/inbound.rb +7 -0
- data/spec/fsr/loading.rb +2 -2
- metadata +74 -15
data/README
CHANGED
@@ -44,11 +44,11 @@ Example of creating an Outbound Eventsocket listener:
|
|
44
44
|
|
45
45
|
class OesDemo < FSR::Listener::Outbound
|
46
46
|
|
47
|
-
def session_initiated
|
48
|
-
number = session.headers[:caller_caller_id_number] # Grab the inbound caller id
|
47
|
+
def session_initiated
|
48
|
+
number = @session.headers[:caller_caller_id_number] # Grab the inbound caller id
|
49
49
|
FSR::Log.info "*** Answering incoming call from #{number}"
|
50
50
|
answer # Answer the call
|
51
|
-
set "
|
51
|
+
set("hangup_after_bridge", "true")# Set a variable
|
52
52
|
speak 'Hello, This is your phone switch. Have a great day' # use mod_flite to speak
|
53
53
|
hangup # Hangup the call
|
54
54
|
end
|
@@ -59,12 +59,53 @@ Example of creating an Outbound Eventsocket listener:
|
|
59
59
|
|
60
60
|
|
61
61
|
|
62
|
+
Example of creating an Outbound Eventsocket listener that can read DTMF input and keep state:
|
63
|
+
|
64
|
+
#!/usr/bin/env ruby
|
65
|
+
|
66
|
+
require 'fsr'
|
67
|
+
require 'fsr/listener/outbound'
|
68
|
+
|
69
|
+
FSR.load_all_applications
|
70
|
+
FSR.load_all_commands
|
71
|
+
|
72
|
+
class DtmfDemo < FSR::Listener::Outbound
|
73
|
+
|
74
|
+
def session_initiated
|
75
|
+
exten = @session.headers[:caller_caller_id_number]
|
76
|
+
FSR::Log.info "*** Answering incoming call from #{exten}"
|
77
|
+
answer # Answer the call
|
78
|
+
end
|
79
|
+
|
80
|
+
def receive_reply(reply)
|
81
|
+
exten = @session.headers[:caller_caller_id_number]
|
82
|
+
case @step
|
83
|
+
when 1
|
84
|
+
FSR::Log.info "*** Reading dtmf for #{exten}"
|
85
|
+
read "/home/freeswitch/freeswitch/sounds/music/8000/sweet.wav",4,10,"test",15000 # read test
|
86
|
+
when 2
|
87
|
+
FSR::Log.info "*** updating session for #{exten}"
|
88
|
+
update_session
|
89
|
+
when 3
|
90
|
+
FSR::Log.info "** Success, grabbed #{@session.headers[:variable_test].strip} from #{exten}"
|
91
|
+
FSR::Log.info "*** Hanging up call"
|
92
|
+
hangup # Hangup the call
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
end
|
97
|
+
|
98
|
+
FSR.start_oes! DtmfDemo, :port => 8084, :host => "127.0.0.1"
|
99
|
+
|
100
|
+
|
101
|
+
|
62
102
|
Example of creating an Inbound Eventsocket listener:
|
63
103
|
|
64
104
|
#!/usr/bin/env ruby
|
65
105
|
|
66
106
|
require 'fsr'
|
67
|
-
require
|
107
|
+
require 'fsr/listener/inbound'
|
108
|
+
require 'pp'
|
68
109
|
|
69
110
|
class IesDemo < FSR::Listener::Inbound
|
70
111
|
|
File without changes
|
@@ -0,0 +1,38 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require File.join(File.dirname(__FILE__), "..", 'start_common')
|
3
|
+
require 'eventmachine'
|
4
|
+
require "fsr/listener/outbound"
|
5
|
+
require 'pp'
|
6
|
+
$stdout.flush
|
7
|
+
FSR.load_all_applications
|
8
|
+
FSR.load_all_commands
|
9
|
+
class ConsumerLogin < FSR::Listener::Outbound
|
10
|
+
|
11
|
+
def session_initiated(session, step = 0)
|
12
|
+
@step ||= step
|
13
|
+
exten = session.headers[:channel_caller_id_number]
|
14
|
+
pp session.headers
|
15
|
+
FSR::Log.info "*** Answering incoming call from #{exten}"
|
16
|
+
answer # Answer the call
|
17
|
+
end
|
18
|
+
|
19
|
+
def receive_reply(reply)
|
20
|
+
exten = @session.headers[:channel_caller_id_number]
|
21
|
+
@step += 1
|
22
|
+
case @step
|
23
|
+
when 1
|
24
|
+
FSR::Log.info "*** Reading dtmf for #{exten}"
|
25
|
+
read "/home/freeswitch/freeswitch/sounds/music/8000/sweet.wav",4,10,"test",15000 # read test
|
26
|
+
when 2
|
27
|
+
FSR::Log.info "*** updating session for #{exten}"
|
28
|
+
update_session
|
29
|
+
when 3
|
30
|
+
FSR::Log.info "** Success, grabbed #{reply.content[:variable_test].strip} from #{exten}"
|
31
|
+
FSR::Log.info "*** Hanging up call"
|
32
|
+
hangup # Hangup the call
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
|
38
|
+
FSR.start_oes! ConsumerLogin, :port => 8084, :host => "127.0.0.1"
|
File without changes
|
File without changes
|
@@ -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 DtmfDemo < 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
|
+
read "/home/freeswitch/freeswitch/sounds/music/8000/sweet.wav",4,10,"test",15000 # read 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].strip} 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! DtmfDemo, :port => 8084, :host => "127.0.0.1"
|
@@ -0,0 +1,19 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'pp'
|
4
|
+
require File.join(File.dirname(__FILE__), "..", 'lib', 'fsr')
|
5
|
+
puts $LOAD_PATH.inspect
|
6
|
+
$stdout.flush
|
7
|
+
require "fsr/listener/inbound"
|
8
|
+
|
9
|
+
|
10
|
+
class IesDemo < FSR::Listener::Inbound
|
11
|
+
|
12
|
+
def on_event(event)
|
13
|
+
pp event.headers
|
14
|
+
pp event.content[:event_name]
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
|
19
|
+
FSR.start_ies!(IesDemo, :host => "localhost", :port => 8021)
|
@@ -0,0 +1,25 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'pp'
|
4
|
+
require File.join(File.dirname(__FILE__), "..", 'lib', 'fsr')
|
5
|
+
puts $LOAD_PATH.inspect
|
6
|
+
$stdout.flush
|
7
|
+
require "fsr/listener/inbound"
|
8
|
+
|
9
|
+
# EXAMPLE 1
|
10
|
+
# This adds a hook on CHANNEL_CREATE events. You can also create a method to handle the event you're after. See the next example
|
11
|
+
FSL::Inbound.add_event_hook(:CHANNEL_CREATE) {|event| FSR::Log.info "*** [#{event.content[:unique_id]}] Channel created - greetings from the hook!" }
|
12
|
+
|
13
|
+
# EXAMPLE 2
|
14
|
+
# Define a method to handle CHANNEL_HANGUP events.
|
15
|
+
def custom_channel_hangup_handler(event)
|
16
|
+
FSR::Log.info "*** [#{event.content[:unique_id]}] Channel hangup. The event:"
|
17
|
+
pp event
|
18
|
+
end
|
19
|
+
# This adds a hook for EXAMPLE 2
|
20
|
+
FSL::Inbound.add_event_hook(:CHANNEL_HANGUP) {|event| custom_channel_hangup_handler(event) }
|
21
|
+
|
22
|
+
|
23
|
+
# Start FSR Inbound Listener
|
24
|
+
FSR.start_ies!(FSL::Inbound, :host => "localhost", :port => 8021)
|
25
|
+
|
@@ -0,0 +1,21 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require File.join(File.dirname(__FILE__), "..", 'lib', 'fsr')
|
4
|
+
$stdout.flush
|
5
|
+
require "fsr/listener/outbound"
|
6
|
+
|
7
|
+
class OesDemo < FSR::Listener::Outbound
|
8
|
+
|
9
|
+
def session_initiated
|
10
|
+
number = @session.headers[:caller_caller_id_number] # Grab the inbound caller id
|
11
|
+
FSR::Log.info "*** Answering incoming call from #{number}"
|
12
|
+
answer # Answer the call
|
13
|
+
log("1", "Pong from the FSR event socket!")
|
14
|
+
set("hangup_after_bridge", "true") # Set a variable
|
15
|
+
speak 'Hello, This is your phone switch. Have a great day' # use mod_flite to speak
|
16
|
+
hangup # Hangup the call
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
|
21
|
+
FSR.start_oes!(OesDemo, :port => 1888, :host => "localhost")
|
@@ -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
data/lib/fsr/app/hangup.rb
CHANGED
@@ -3,12 +3,12 @@ module FSR
|
|
3
3
|
module App
|
4
4
|
# http://wiki.freeswitch.org/wiki/Misc._Dialplan_Tools_hangup
|
5
5
|
class Hangup < Application
|
6
|
-
def initialize(
|
7
|
-
@
|
6
|
+
def initialize(cause = nil)
|
7
|
+
@cause = cause
|
8
8
|
end
|
9
9
|
|
10
10
|
def arguments
|
11
|
-
@
|
11
|
+
@cause
|
12
12
|
end
|
13
13
|
|
14
14
|
def sendmsg
|
@@ -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
|
data/lib/fsr/app/playback.rb
CHANGED
@@ -1,4 +1,3 @@
|
|
1
|
-
|
2
1
|
require "fsr/app"
|
3
2
|
module FSR
|
4
3
|
module App
|
@@ -10,11 +9,11 @@ module FSR
|
|
10
9
|
@wavfile = wavfile
|
11
10
|
end
|
12
11
|
def arguments
|
13
|
-
|
12
|
+
@wavfile
|
14
13
|
end
|
15
14
|
|
16
15
|
def sendmsg
|
17
|
-
"call-command: execute\nexecute-app-name: %s\nexecute-app-arg: %s\nevent-lock:true\n\n" % [app_name, arguments
|
16
|
+
"call-command: execute\nexecute-app-name: %s\nexecute-app-arg: %s\nevent-lock:true\n\n" % [app_name, arguments]
|
18
17
|
end
|
19
18
|
end
|
20
19
|
|
data/lib/fsr/app/read.rb
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
require "fsr/app"
|
2
|
+
module FSR
|
3
|
+
# http://wiki.freeswitch.org/wiki/Misc._Dialplan_Tools_read
|
4
|
+
module App
|
5
|
+
class Read < Application
|
6
|
+
def initialize(sound_file, min = 0, max = 10, chan_var = "fsr_read_dtmf", timeout = 10000, terminators = ["#"])
|
7
|
+
@sound_file, @min, @max, @chan_var, @timeout, @terminators = sound_file, min, max, chan_var, timeout, terminators
|
8
|
+
end
|
9
|
+
|
10
|
+
def arguments
|
11
|
+
[@min, @max, @sound_file, @chan_var, @timeout, @terminators.join(",")]
|
12
|
+
end
|
13
|
+
|
14
|
+
def sendmsg
|
15
|
+
"call-command: execute\nexecute-app-name: %s\nexecute-app-arg: %s\nevent-lock:true\n\n" % [app_name, arguments.join(" ")]
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
|
20
|
+
register(:read, Read)
|
21
|
+
end
|
22
|
+
end
|
data/lib/fsr/app/transfer.rb
CHANGED
@@ -6,8 +6,8 @@ module FSR
|
|
6
6
|
|
7
7
|
def initialize(destination_number, dialplan = nil, context = nil)
|
8
8
|
@destination_number = destination_number
|
9
|
-
@dialplan = dialplan
|
10
|
-
@context = context
|
9
|
+
@dialplan = dialplan
|
10
|
+
@context = context
|
11
11
|
end
|
12
12
|
|
13
13
|
def arguments
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require "fsr/app"
|
2
|
+
module FSR
|
3
|
+
#http://wiki.freeswitch.org/wiki/Mod_commands#uuid_dump
|
4
|
+
module App
|
5
|
+
class UuidDump < Application
|
6
|
+
def initialize(uuid)
|
7
|
+
@uuid = uuid # Unique channel ID
|
8
|
+
end
|
9
|
+
|
10
|
+
def arguments
|
11
|
+
[@uuid]
|
12
|
+
end
|
13
|
+
|
14
|
+
def sendmsg
|
15
|
+
"call-command: execute\nexecute-app-name: %s\nexecute-app-arg: %s\nevent-lock:true\n\n" % [app_name, arguments.join(" ")]
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
|
20
|
+
register(:uuid_dump, UuidDump)
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require "fsr/app"
|
2
|
+
module FSR
|
3
|
+
#http://wiki.freeswitch.org/wiki/Mod_commands#uuid_getvar
|
4
|
+
module App
|
5
|
+
class UuidGetVar < Application
|
6
|
+
def initialize(uuid, var)
|
7
|
+
@uuid = uuid # Unique channel ID
|
8
|
+
@var = var # Channel variable you wish to 'get'
|
9
|
+
end
|
10
|
+
|
11
|
+
def arguments
|
12
|
+
[@uuid, @var]
|
13
|
+
end
|
14
|
+
|
15
|
+
def sendmsg
|
16
|
+
"call-command: execute\nexecute-app-name: %s\nexecute-app-arg: %s\nevent-lock:true\n\n" % [app_name, arguments.join(" ")]
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
|
21
|
+
register(:uuid_getvar, UuidGetVar)
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require "fsr/app"
|
2
|
+
module FSR
|
3
|
+
#http://wiki.freeswitch.org/wiki/Mod_commands#uuid_setvar
|
4
|
+
module App
|
5
|
+
class UuidSetVar < Application
|
6
|
+
def initialize(uuid, var, assignment)
|
7
|
+
@uuid = uuid # Unique channel ID
|
8
|
+
@var = var # Channel variable you wish to 'set'
|
9
|
+
@assignment
|
10
|
+
end
|
11
|
+
|
12
|
+
def arguments
|
13
|
+
[@uuid, @var, @assignment]
|
14
|
+
end
|
15
|
+
|
16
|
+
def sendmsg
|
17
|
+
"call-command: execute\nexecute-app-name: %s\nexecute-app-arg: %s\nevent-lock:true\n\n" % [app_name, arguments.join(" ")]
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
|
22
|
+
register(:uuid_setvar, UuidSetVar)
|
23
|
+
end
|
24
|
+
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
|
@@ -7,6 +7,7 @@ module FSR
|
|
7
7
|
load_all_applications
|
8
8
|
module Listener
|
9
9
|
class Outbound < EventMachine::Protocols::HeaderAndContentProtocol
|
10
|
+
attr_reader :session
|
10
11
|
|
11
12
|
# Include FSR::App to get all the applications defined as methods
|
12
13
|
include FSR::App
|
@@ -15,33 +16,23 @@ module FSR
|
|
15
16
|
SENDMSG_METHOD_DEFINITION = "def %s(*args, &block); sendmsg super; end"
|
16
17
|
APPLICATIONS.each { |app, obj| module_eval(SENDMSG_METHOD_DEFINITION % app.to_s) }
|
17
18
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
19
|
+
# session_initiated is called when a @session is first created.
|
20
|
+
# Overwrite this in your worker class with the call/channel
|
21
|
+
# handling logic you desire
|
22
|
+
def session_initiated
|
23
|
+
FSR::Log.warn "#{self.class.name}#session_initiated not overwritten"
|
24
|
+
FSR::Log.debug session_data.inspect
|
22
25
|
end
|
23
26
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
# Received data dispatches the data received by the EM socket,
|
37
|
-
# Either as a Session, a continuation of a Session, or as a Session's last CommandReply
|
38
|
-
|
39
|
-
def session_initiated(session)
|
40
|
-
session
|
41
|
-
end
|
42
|
-
|
43
|
-
def receive_reply(session)
|
44
|
-
session
|
27
|
+
# receive_reply is called when a response is received.
|
28
|
+
# Overwrite this in your worker class with the call/channel
|
29
|
+
# handling logic you desire, taking @step into account for
|
30
|
+
# state management between commands
|
31
|
+
# @param reply This HeaderAndContent instance will have the channel variables
|
32
|
+
# in #content, if the session has been updated
|
33
|
+
def receive_reply(reply)
|
34
|
+
FSR::Log.warn "#{self.class.name}#receive_reply not overwritten"
|
35
|
+
FSR::Log.debug reply.inspect
|
45
36
|
end
|
46
37
|
|
47
38
|
# sendmsg sends data to the EM app socket via #send_data, or
|
@@ -56,7 +47,56 @@ module FSR
|
|
56
47
|
self.respond_to?(:send_data) ? send_data(message) : message
|
57
48
|
end
|
58
49
|
|
50
|
+
# Update_session
|
51
|
+
|
52
|
+
def update_session
|
53
|
+
send_data("api uuid_dump #{@session.headers[:unique_id]}\n\n")
|
54
|
+
end
|
55
|
+
|
56
|
+
protected
|
57
|
+
def post_init
|
58
|
+
@session = nil # holds the session object
|
59
|
+
send_data("connect\n\n")
|
60
|
+
FSR::Log.debug "Accepting connections."
|
61
|
+
end
|
62
|
+
|
63
|
+
# receive_request is called each time data is received by the event machine
|
64
|
+
# it will manipulate the received data into either a new session or a reply,
|
65
|
+
# to be picked up by #session_initiated or #receive_reply.
|
66
|
+
# If your listener is listening for events, this will also renew your @session
|
67
|
+
# each time you receive a CHANNEL_DATA event.
|
68
|
+
# @param header The header of the request, as passed by HeaderAndContentProtocol
|
69
|
+
# @param content The content of the request, as passed by HeaderAndContentProtocol
|
70
|
+
#
|
71
|
+
# @returns HeaderAndContentResponse
|
72
|
+
def receive_request(header, content)
|
73
|
+
hash_header = headers_2_hash(header)
|
74
|
+
hash_content = headers_2_hash(content)
|
75
|
+
session_header_and_content = HeaderAndContentResponse.new({:headers => hash_header, :content => hash_content})
|
76
|
+
# If we're a new session, call session initiate
|
77
|
+
if @session.nil?
|
78
|
+
@session = session_header_and_content
|
79
|
+
@step = 0
|
80
|
+
session_initiated
|
81
|
+
elsif session_header_and_content.content[:event_name] # If content includes an event_name, it must be a response from an api command
|
82
|
+
if session_header_and_content.content[:event_name].to_s.match(/CHANNEL_DATA/i) # Anytime we see CHANNEL_DATA event, we want to update our @session
|
83
|
+
session_header_and_content = HeaderAndContentResponse.new({:headers => hash_header.merge(hash_content.strip_value_newlines), :content => {}})
|
84
|
+
@session = session_header_and_content
|
85
|
+
@step += 1
|
86
|
+
receive_reply(hash_header)
|
87
|
+
end
|
88
|
+
else
|
89
|
+
@step += 1
|
90
|
+
receive_reply(session_header_and_content)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
59
94
|
end
|
95
|
+
end
|
96
|
+
end
|
60
97
|
|
98
|
+
class Hash
|
99
|
+
def strip_value_newlines
|
100
|
+
Hash[*(self.map { |k,v| v.respond_to?(:to_s) ? [k, v.to_s.strip] : [k, v] }.flatten)]
|
61
101
|
end
|
62
102
|
end
|
@@ -0,0 +1,131 @@
|
|
1
|
+
require "yaml"
|
2
|
+
require "fsr/listener"
|
3
|
+
module FSR
|
4
|
+
load_all_applications
|
5
|
+
module Listener
|
6
|
+
module Outbound
|
7
|
+
include FSR::Listener
|
8
|
+
|
9
|
+
# Include FSR::App to get all the applications defined as methods
|
10
|
+
include FSR::App
|
11
|
+
|
12
|
+
# Redefine the FSR::App methods to wrap sendmsg around them
|
13
|
+
SENDMSG_METHOD_DEFINITION = "def %s(*args, &block); sendmsg super; end"
|
14
|
+
APPLICATIONS.each { |app, obj| module_eval(SENDMSG_METHOD_DEFINITION % app.to_s) }
|
15
|
+
|
16
|
+
def post_init
|
17
|
+
@session = nil # holds the session object
|
18
|
+
send_data("connect\n\n")
|
19
|
+
FSR::Log.debug "Accepting connections."
|
20
|
+
end
|
21
|
+
|
22
|
+
# Received data dispatches the data received by the EM socket,
|
23
|
+
# Either as a Session, a continuation of a Session, or as a Session's last CommandReply
|
24
|
+
def receive_data(data)
|
25
|
+
FSR::Log.debug("received #{data}")
|
26
|
+
if @session.nil? # if @session is nil, create a new Session object
|
27
|
+
@session = Session.new(data)
|
28
|
+
session_initiated(@session) if @session.initiated?
|
29
|
+
else
|
30
|
+
# If it's not nil, we add the data to this session, Session knows whether
|
31
|
+
# or not to create a CommandReply, complete a CommandReply, or simply add to
|
32
|
+
# its own @data array and @headers/@body structures
|
33
|
+
if @session.initiated?
|
34
|
+
@session << data
|
35
|
+
reply_received(@session.replies.last) if @session.replies.last.complete?
|
36
|
+
else
|
37
|
+
@session << data
|
38
|
+
session_initiated(@session) if @session.initiated?
|
39
|
+
end
|
40
|
+
end
|
41
|
+
@session
|
42
|
+
end
|
43
|
+
|
44
|
+
def session_initiated(session)
|
45
|
+
session
|
46
|
+
end
|
47
|
+
|
48
|
+
def reply_received(command_reply)
|
49
|
+
command_reply
|
50
|
+
end
|
51
|
+
|
52
|
+
alias :receive_response :reply_received
|
53
|
+
# sendmsg sends data to the EM app socket via #send_data, or
|
54
|
+
# returns the string it would send if #send_data is not defined.
|
55
|
+
# It expects an object which responds to either #sendmsg or #to_s,
|
56
|
+
# which should return a EM Outbound Event Socket formatted instruction
|
57
|
+
def sendmsg(message)
|
58
|
+
text = message.respond_to?(:sendmsg) ? message.sendmsg : message.to_s
|
59
|
+
FSR::Log.debug "sending #{text}"
|
60
|
+
message = "sendmsg\n%s\n" % text
|
61
|
+
self.respond_to?(:send_data) ? send_data(message) : message
|
62
|
+
end
|
63
|
+
|
64
|
+
|
65
|
+
class SocketResponse
|
66
|
+
attr_accessor :headers, :body, :data
|
67
|
+
def initialize(data = "")
|
68
|
+
@data = [data]
|
69
|
+
@headers = {}
|
70
|
+
if data.match(/\n$/)
|
71
|
+
headers, @body = data.split("\n\n")
|
72
|
+
headers.each_line do |line|
|
73
|
+
key, value = line.split(":")
|
74
|
+
@headers[key] = value.to_s.strip
|
75
|
+
end
|
76
|
+
end
|
77
|
+
@body ||= ""
|
78
|
+
FSR::Log.debug("New #{self.class.name} created: #{self}")
|
79
|
+
end
|
80
|
+
|
81
|
+
def <<(data)
|
82
|
+
if data.match(/\n$/)
|
83
|
+
@data.last.match(/\n$/) ? @data << data : @data.last << data
|
84
|
+
extra_headers, more_body = @data.last.split("\n\n")
|
85
|
+
extra_headers.each_line do |line|
|
86
|
+
key, value = line.split(":")
|
87
|
+
@headers[key] = value.to_s.strip
|
88
|
+
end
|
89
|
+
@body << more_body unless more_body.nil?
|
90
|
+
else
|
91
|
+
@data.last.match(/\n$/) ? @data << data : @data.last << data
|
92
|
+
end
|
93
|
+
self
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
class Session < SocketResponse
|
98
|
+
attr_accessor :replies
|
99
|
+
def initialize(data = "")
|
100
|
+
super
|
101
|
+
@replies = []
|
102
|
+
end
|
103
|
+
|
104
|
+
def <<(data)
|
105
|
+
if initiated?
|
106
|
+
if @replies.empty? or @replies.last.complete?
|
107
|
+
@replies << CommandReply.new(data)
|
108
|
+
else
|
109
|
+
@replies.last << data
|
110
|
+
end
|
111
|
+
else
|
112
|
+
super
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
def initiated?
|
117
|
+
@headers.keys.include?("Control")
|
118
|
+
end
|
119
|
+
|
120
|
+
end
|
121
|
+
|
122
|
+
class CommandReply < SocketResponse
|
123
|
+
# Set this to true for now, fill it in when we know what completed a reply
|
124
|
+
def complete?
|
125
|
+
true
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
end
|
131
|
+
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,16 @@
|
|
1
|
+
require 'spec/helper'
|
2
|
+
require "fsr/app"
|
3
|
+
FSR::App.load_application("hangup")
|
4
|
+
|
5
|
+
describe "Testing FSR::App::Hangup" do
|
6
|
+
it "Hangs up the channel" do
|
7
|
+
hangup = FSR::App::Hangup.new
|
8
|
+
hangup.sendmsg.should == "call-command: execute\nexecute-app-name: hangup\nexecute-app-arg: \n\n"
|
9
|
+
end
|
10
|
+
|
11
|
+
it "Hangs up the channel using a hangup cause" do
|
12
|
+
hangup = FSR::App::Hangup.new("USER_BUSY")
|
13
|
+
hangup.sendmsg.should == "call-command: execute\nexecute-app-name: hangup\nexecute-app-arg: USER_BUSY\n\n"
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
data/spec/fsr/app/log.rb
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
require 'spec/helper'
|
2
|
+
require "fsr/app"
|
3
|
+
FSR::App.load_application("log")
|
4
|
+
|
5
|
+
describe "Testing FSR::App::Log" do
|
6
|
+
it "Logs to the console" do
|
7
|
+
log = FSR::App::Log.new(1, "This is a test! :-)")
|
8
|
+
log.sendmsg.should == "call-command: execute\nexecute-app-name: log\nexecute-app-arg: 1 This is a test! :-)\nevent-lock:true\n\n"
|
9
|
+
end
|
10
|
+
|
11
|
+
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,11 @@
|
|
1
|
+
require 'spec/helper'
|
2
|
+
require "fsr/app"
|
3
|
+
FSR::App.load_application("playback")
|
4
|
+
|
5
|
+
describe "Testing FSR::App::Playback" do
|
6
|
+
it "Plays a file or stream" do
|
7
|
+
playback = FSR::App::Playback.new("shout://scfire-ntc-aa01.stream.aol.com/stream/1035")
|
8
|
+
playback.sendmsg.should == "call-command: execute\nexecute-app-name: playback\nexecute-app-arg: shout://scfire-ntc-aa01.stream.aol.com/stream/1035\nevent-lock:true\n\n"
|
9
|
+
end
|
10
|
+
|
11
|
+
end
|
data/spec/fsr/app/set.rb
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
require 'spec/helper'
|
2
|
+
require "fsr/app"
|
3
|
+
FSR::App.load_application("set")
|
4
|
+
|
5
|
+
describe "Testing FSR::App::Set" do
|
6
|
+
# Utilize the [] shortcut to start a conference
|
7
|
+
it "Sets a single variable" do
|
8
|
+
set = FSR::App::Set.new("hangup_after_bridge", true)
|
9
|
+
set.sendmsg.should == "call-command: execute\nexecute-app-name: set\nexecute-app-arg: hangup_after_bridge=true\nevent-lock:true\n\n"
|
10
|
+
end
|
11
|
+
|
12
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
require 'spec/helper'
|
2
|
+
require "fsr/app"
|
3
|
+
FSR::App.load_application("transfer")
|
4
|
+
|
5
|
+
describe "Testing FSR::App::Transfer" do
|
6
|
+
it "Transfers the call" do
|
7
|
+
transfer = FSR::App::Transfer.new("500", "XML", "default")
|
8
|
+
transfer.sendmsg.should == "call-command: execute\nexecute-app-name: transfer\nexecute-app-arg: 500 XML default\nevent-lock:true\n\n"
|
9
|
+
end
|
10
|
+
|
11
|
+
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
|
@@ -16,4 +16,11 @@ describe "Testing FSR::Listener::Inbound" do
|
|
16
16
|
FSR::Listener::Inbound.method_defined?(:post_init).should == true
|
17
17
|
end
|
18
18
|
|
19
|
+
it "adds and deletes hooks" do
|
20
|
+
FSL::Inbound.add_event_hook(:CHANNEL_CREATE) {|event| puts event.inspect }
|
21
|
+
FSL::Inbound::HOOKS.size.should == 1
|
22
|
+
FSL::Inbound.del_event_hook(:CHANNEL_CREATE)
|
23
|
+
FSL::Inbound::HOOKS.size.should == 0
|
24
|
+
end
|
25
|
+
|
19
26
|
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 = [: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]
|
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: bougyman-freeswitcher
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jayson Vaughn
|
@@ -25,7 +25,7 @@ dependencies:
|
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: "0"
|
27
27
|
version:
|
28
|
-
description: "========================================================= FreeSWITCHeR Copyright (c) 2009 The Rubyists (Jayson Vaughn, Tj Vanderpoel, Michael Fellinger, Kevin Berry) Distributed under the terms of the MIT License. ========================================================== About ----- *** STILL UNDER HEAVY DEVELOPMENT *** A ruby library for interacting with the \"FreeSWITCH\" (http://www.freeswitch.org) opensource telephony platform *** STILL UNDER HEAVY DEVELOPMENT *** Requirements ------------ - ruby (>= 1.8) - eventmachine (If you wish to use Outbound and Inbound listener) Usage ----- Example of originating a new call in 'irb' using FSR::CommandSocket#originate: irb(main):001:0> require 'fsr' => true irb(main):002:0> FSR.load_all_commands => [:sofia, :originate] irb(main):003:0> sock = FSR::CommandSocket.new => #<FSR::CommandSocket:0xb7a89104 @server=\"127.0.0.1\", @socket=#<TCPSocket:0xb7a8908c>, @port=\"8021\", @auth=\"ClueCon\"> irb(main):007:0> sock.originate(:target => 'sofia/gateway/carlos/8179395222', :endpoint => FSR::App::Bridge.new(\"user/bougyman\")).run => {\"Job-UUID\"=>\"732075a4-7dd5-4258-b124-6284a82a5ae7\", \"body\"=>\"\", \"Content-Type\"=>\"command/reply\", \"Reply-Text\"=>\"+OK Job-UUID: 732075a4-7dd5-4258-b124-6284a82a5ae7\"} Example of creating an Outbound Eventsocket listener: #!/usr/bin/env ruby require 'fsr' require \"fsr/listener/outbound\" class OesDemo < FSR::Listener::Outbound def session_initiated
|
28
|
+
description: "========================================================= FreeSWITCHeR Copyright (c) 2009 The Rubyists (Jayson Vaughn, Tj Vanderpoel, Michael Fellinger, Kevin Berry) Distributed under the terms of the MIT License. ========================================================== About ----- *** STILL UNDER HEAVY DEVELOPMENT *** A ruby library for interacting with the \"FreeSWITCH\" (http://www.freeswitch.org) opensource telephony platform *** STILL UNDER HEAVY DEVELOPMENT *** Requirements ------------ - ruby (>= 1.8) - eventmachine (If you wish to use Outbound and Inbound listener) Usage ----- Example of originating a new call in 'irb' using FSR::CommandSocket#originate: irb(main):001:0> require 'fsr' => true irb(main):002:0> FSR.load_all_commands => [:sofia, :originate] irb(main):003:0> sock = FSR::CommandSocket.new => #<FSR::CommandSocket:0xb7a89104 @server=\"127.0.0.1\", @socket=#<TCPSocket:0xb7a8908c>, @port=\"8021\", @auth=\"ClueCon\"> irb(main):007:0> sock.originate(:target => 'sofia/gateway/carlos/8179395222', :endpoint => FSR::App::Bridge.new(\"user/bougyman\")).run => {\"Job-UUID\"=>\"732075a4-7dd5-4258-b124-6284a82a5ae7\", \"body\"=>\"\", \"Content-Type\"=>\"command/reply\", \"Reply-Text\"=>\"+OK Job-UUID: 732075a4-7dd5-4258-b124-6284a82a5ae7\"} Example of creating an Outbound Eventsocket listener: #!/usr/bin/env ruby require 'fsr' require \"fsr/listener/outbound\" class OesDemo < FSR::Listener::Outbound def session_initiated number = @session.headers[:caller_caller_id_number] # Grab the inbound caller id FSR::Log.info \"*** Answering incoming call from #{number}\" answer # Answer the call set(\"hangup_after_bridge\", \"true\")# Set a variable speak 'Hello, This is your phone switch. Have a great day' # use mod_flite to speak hangup # Hangup the call end end FSR.start_oes!(OesDemo, :port => 1888, :host => \"localhost\") Example of creating an Outbound Eventsocket listener that can read DTMF input and keep state: #!/usr/bin/env ruby require 'fsr' require 'fsr/listener/outbound' FSR.load_all_applications FSR.load_all_commands class DtmfDemo < FSR::Listener::Outbound def session_initiated exten = @session.headers[:caller_caller_id_number] FSR::Log.info \"*** Answering incoming call from #{exten}\" answer # Answer the call end def receive_reply(reply) exten = @session.headers[:caller_caller_id_number] case @step when 1 FSR::Log.info \"*** Reading dtmf for #{exten}\" read \"/home/freeswitch/freeswitch/sounds/music/8000/sweet.wav\",4,10,\"test\",15000 # read test when 2 FSR::Log.info \"*** updating session for #{exten}\" update_session when 3 FSR::Log.info \"** Success, grabbed #{@session.headers[:variable_test].strip} from #{exten}\" FSR::Log.info \"*** Hanging up call\" hangup # Hangup the call end end end FSR.start_oes! DtmfDemo, :port => 8084, :host => \"127.0.0.1\" Example of creating an Inbound Eventsocket listener: #!/usr/bin/env ruby require 'fsr' require 'fsr/listener/inbound' require 'pp' class IesDemo < FSR::Listener::Inbound def on_event(event) pp event.headers pp event.content[:event_name] end end FSR.start_ies!(IesDemo, :host => \"localhost\", :port => 8021) Support ------- Home page at http://code.rubyists.com/projects/fs #rubyists on FreeNode"
|
29
29
|
email: FreeSWITCHeR@rubyists.com
|
30
30
|
executables: []
|
31
31
|
|
@@ -38,12 +38,18 @@ files:
|
|
38
38
|
- NEWS
|
39
39
|
- README
|
40
40
|
- Rakefile
|
41
|
-
-
|
42
|
-
- bin
|
43
|
-
- bin/
|
44
|
-
- bin/
|
45
|
-
- bin/
|
46
|
-
- bin/
|
41
|
+
- examples
|
42
|
+
- examples/bin
|
43
|
+
- examples/bin/cmd_demo.rb
|
44
|
+
- examples/bin/dtmf_test.rb
|
45
|
+
- examples/bin/ies_demo.rb
|
46
|
+
- examples/bin/ies_demo_with_hook.rb
|
47
|
+
- examples/bin/oes_demo.rb
|
48
|
+
- examples/dtmf_test.rb
|
49
|
+
- examples/ies_demo.rb
|
50
|
+
- examples/ies_demo_with_hook.rb
|
51
|
+
- examples/oes_demo.rb
|
52
|
+
- examples/play_and_get_test.rb
|
47
53
|
- lib
|
48
54
|
- lib/fsr
|
49
55
|
- lib/fsr/app
|
@@ -55,12 +61,18 @@ files:
|
|
55
61
|
- lib/fsr/app/fs_sleep.rb
|
56
62
|
- lib/fsr/app/hangup.rb
|
57
63
|
- lib/fsr/app/log.rb
|
64
|
+
- lib/fsr/app/play_and_get_digits.rb
|
58
65
|
- lib/fsr/app/playback.rb
|
66
|
+
- lib/fsr/app/read.rb
|
59
67
|
- lib/fsr/app/set.rb
|
60
68
|
- lib/fsr/app/speak.rb
|
61
69
|
- lib/fsr/app/transfer.rb
|
70
|
+
- lib/fsr/app/uuid_dump.rb
|
71
|
+
- lib/fsr/app/uuid_getvar.rb
|
72
|
+
- lib/fsr/app/uuid_setvar.rb
|
62
73
|
- lib/fsr/app.rb
|
63
74
|
- lib/fsr/cmd
|
75
|
+
- lib/fsr/cmd/calls.rb
|
64
76
|
- lib/fsr/cmd/fsctl.rb
|
65
77
|
- lib/fsr/cmd/originate.rb
|
66
78
|
- lib/fsr/cmd/sofia
|
@@ -88,13 +100,12 @@ files:
|
|
88
100
|
- lib/fsr/listener/outbound.rb
|
89
101
|
- lib/fsr/listener/outbound.rb.orig
|
90
102
|
- lib/fsr/listener.rb
|
103
|
+
- lib/fsr/model
|
104
|
+
- lib/fsr/model/call.rb
|
91
105
|
- lib/fsr.rb
|
92
106
|
- tasks
|
93
107
|
- tasks/package.rake
|
94
|
-
- tasks/ride.rake
|
95
|
-
- tasks/rspec.rake
|
96
108
|
- tasks/spec.rake
|
97
|
-
- tmp
|
98
109
|
has_rdoc: false
|
99
110
|
homepage: http://code.rubyists.com/projects/fs
|
100
111
|
post_install_message: |
|
@@ -144,11 +155,11 @@ post_install_message: |
|
|
144
155
|
|
145
156
|
class OesDemo < FSR::Listener::Outbound
|
146
157
|
|
147
|
-
def session_initiated
|
148
|
-
number = session.headers[:caller_caller_id_number] # Grab the inbound caller id
|
158
|
+
def session_initiated
|
159
|
+
number = @session.headers[:caller_caller_id_number] # Grab the inbound caller id
|
149
160
|
FSR::Log.info "*** Answering incoming call from #{number}"
|
150
161
|
answer # Answer the call
|
151
|
-
set "
|
162
|
+
set("hangup_after_bridge", "true")# Set a variable
|
152
163
|
speak 'Hello, This is your phone switch. Have a great day' # use mod_flite to speak
|
153
164
|
hangup # Hangup the call
|
154
165
|
end
|
@@ -159,12 +170,53 @@ post_install_message: |
|
|
159
170
|
|
160
171
|
|
161
172
|
|
173
|
+
Example of creating an Outbound Eventsocket listener that can read DTMF input and keep state:
|
174
|
+
|
175
|
+
#!/usr/bin/env ruby
|
176
|
+
|
177
|
+
require 'fsr'
|
178
|
+
require 'fsr/listener/outbound'
|
179
|
+
|
180
|
+
FSR.load_all_applications
|
181
|
+
FSR.load_all_commands
|
182
|
+
|
183
|
+
class DtmfDemo < FSR::Listener::Outbound
|
184
|
+
|
185
|
+
def session_initiated
|
186
|
+
exten = @session.headers[:caller_caller_id_number]
|
187
|
+
FSR::Log.info "*** Answering incoming call from #{exten}"
|
188
|
+
answer # Answer the call
|
189
|
+
end
|
190
|
+
|
191
|
+
def receive_reply(reply)
|
192
|
+
exten = @session.headers[:caller_caller_id_number]
|
193
|
+
case @step
|
194
|
+
when 1
|
195
|
+
FSR::Log.info "*** Reading dtmf for #{exten}"
|
196
|
+
read "/home/freeswitch/freeswitch/sounds/music/8000/sweet.wav",4,10,"test",15000 # read test
|
197
|
+
when 2
|
198
|
+
FSR::Log.info "*** updating session for #{exten}"
|
199
|
+
update_session
|
200
|
+
when 3
|
201
|
+
FSR::Log.info "** Success, grabbed #{@session.headers[:variable_test].strip} from #{exten}"
|
202
|
+
FSR::Log.info "*** Hanging up call"
|
203
|
+
hangup # Hangup the call
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
end
|
208
|
+
|
209
|
+
FSR.start_oes! DtmfDemo, :port => 8084, :host => "127.0.0.1"
|
210
|
+
|
211
|
+
|
212
|
+
|
162
213
|
Example of creating an Inbound Eventsocket listener:
|
163
214
|
|
164
215
|
#!/usr/bin/env ruby
|
165
216
|
|
166
217
|
require 'fsr'
|
167
|
-
require
|
218
|
+
require 'fsr/listener/inbound'
|
219
|
+
require 'pp'
|
168
220
|
|
169
221
|
class IesDemo < FSR::Listener::Inbound
|
170
222
|
|
@@ -214,8 +266,15 @@ test_files:
|
|
214
266
|
- spec/fsr/app/bridge.rb
|
215
267
|
- spec/fsr/app/conference.rb
|
216
268
|
- spec/fsr/app/fifo.rb
|
269
|
+
- spec/fsr/app/hangup.rb
|
270
|
+
- spec/fsr/app/log.rb
|
271
|
+
- spec/fsr/app/play_and_get_digits.rb
|
272
|
+
- spec/fsr/app/playback.rb
|
273
|
+
- spec/fsr/app/set.rb
|
274
|
+
- spec/fsr/app/transfer.rb
|
217
275
|
- spec/fsr/app.rb
|
218
276
|
- spec/fsr/cmd
|
277
|
+
- spec/fsr/cmd/calls.rb
|
219
278
|
- spec/fsr/cmd/originate.rb
|
220
279
|
- spec/fsr/cmd/sofia
|
221
280
|
- spec/fsr/cmd/sofia/profile.rb
|