freec 0.2.2 → 0.2.5
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +1 -1
- data/Rakefile +2 -2
- data/lib/freec_base.rb +20 -6
- data/spec/event_parser_spec.rb +29 -1
- data/spec/freec_base_spec.rb +10 -4
- metadata +22 -8
data/README.rdoc
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
Freec is a framework you can build voice applications on top of. It makes use of the Event socket outbound API of Freeswitch.
|
3
3
|
|
4
4
|
= Installation
|
5
|
-
|
5
|
+
gem install freec
|
6
6
|
|
7
7
|
= Usage
|
8
8
|
1. Install Freeswitch and point a chosen extension to the IP where your app will run:
|
data/Rakefile
CHANGED
@@ -9,7 +9,7 @@ end
|
|
9
9
|
|
10
10
|
spec = Gem::Specification.new do |s|
|
11
11
|
s.name = "freec"
|
12
|
-
s.version = '0.2.
|
12
|
+
s.version = '0.2.5'
|
13
13
|
s.author = "Jan Kubr"
|
14
14
|
s.email = "mail@jankubr.com"
|
15
15
|
s.homepage = "http://github.com/jankubr/freec"
|
@@ -23,7 +23,7 @@ spec = Gem::Specification.new do |s|
|
|
23
23
|
s.has_rdoc = false
|
24
24
|
s.extra_rdoc_files = FileList["README*"].to_a
|
25
25
|
s.rdoc_options << '--line-numbers' << '--inline-source'
|
26
|
-
s.
|
26
|
+
s.add_dependency "daemons"
|
27
27
|
s.add_development_dependency 'rspec'
|
28
28
|
end
|
29
29
|
|
data/lib/freec_base.rb
CHANGED
@@ -13,7 +13,8 @@ class Freec
|
|
13
13
|
attr_reader :call_vars, :event_body, :log, :config
|
14
14
|
|
15
15
|
def initialize(io, log, config) #:nodoc:
|
16
|
-
@call_vars
|
16
|
+
@call_vars = {}
|
17
|
+
@want_events_from = []
|
17
18
|
@last_app_executed = 'initial_step'
|
18
19
|
@io = io
|
19
20
|
@log = log
|
@@ -30,9 +31,8 @@ class Freec
|
|
30
31
|
reset_wait_for if waiting_for_this_response?
|
31
32
|
reload_application_code
|
32
33
|
break if disconnect_notice? || !callback(:step)
|
33
|
-
end
|
34
|
-
|
35
|
-
parse_response
|
34
|
+
end
|
35
|
+
read_and_parse_response
|
36
36
|
end
|
37
37
|
callback(:on_hangup)
|
38
38
|
hangup unless @io.closed?
|
@@ -112,6 +112,7 @@ private
|
|
112
112
|
|
113
113
|
def subscribe_to_new_channel_events
|
114
114
|
return unless call_vars[:event_name] == 'CHANNEL_BRIDGE'
|
115
|
+
@want_events_from << call_vars[:other_leg_unique_id]
|
115
116
|
send_and_read("filter Unique-ID #{call_vars[:other_leg_unique_id]}")
|
116
117
|
end
|
117
118
|
|
@@ -133,6 +134,14 @@ private
|
|
133
134
|
read_response
|
134
135
|
end
|
135
136
|
|
137
|
+
def read_and_parse_response
|
138
|
+
my_event = false
|
139
|
+
until my_event
|
140
|
+
read_response
|
141
|
+
my_event = parse_response
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
136
145
|
def read_response
|
137
146
|
return if disconnect_notice?
|
138
147
|
read_response_info
|
@@ -180,12 +189,17 @@ private
|
|
180
189
|
@response.split("\n").each do |line|
|
181
190
|
k,v = line.split(/\s*:\s*/)
|
182
191
|
hash[k.strip.gsub('-', '_').downcase.to_sym] = URI.unescape(v).strip if k && v
|
183
|
-
end
|
192
|
+
end
|
193
|
+
unless @unique_id
|
194
|
+
@unique_id = hash[:unique_id]
|
195
|
+
@want_events_from << @unique_id
|
196
|
+
end
|
197
|
+
return false unless @want_events_from.include?(hash[:unique_id]) || hash[:unique_id].blank?
|
184
198
|
call_vars.merge!(hash)
|
185
|
-
@unique_id ||= call_vars[:unique_id]
|
186
199
|
raise call_vars[:reply_text] if call_vars[:reply_text] =~ /^-ERR/
|
187
200
|
log.debug "\n\tUnique ID: #{call_vars[:unique_id]}\n\tContent-type: #{call_vars[:content_type]}\n\tEvent name: #{call_vars[:event_name]}"
|
188
201
|
@response = ''
|
202
|
+
true
|
189
203
|
end
|
190
204
|
|
191
205
|
end
|
data/spec/event_parser_spec.rb
CHANGED
@@ -9,7 +9,6 @@ describe Freec do
|
|
9
9
|
end
|
10
10
|
|
11
11
|
describe "parses body-less event" do
|
12
|
-
|
13
12
|
before do
|
14
13
|
@freec.instance_variable_set(:@response, EVENT)
|
15
14
|
@freec.send :parse_response
|
@@ -19,6 +18,10 @@ describe Freec do
|
|
19
18
|
@freec.instance_variable_get(:@unique_id).should == 'f3c2d5ee-d064-4f55-9280-5be2a65867e8'
|
20
19
|
end
|
21
20
|
|
21
|
+
it "should include channel unique id to the array of ids event variables are read from" do
|
22
|
+
@freec.instance_variable_get(:@want_events_from).should == ['f3c2d5ee-d064-4f55-9280-5be2a65867e8']
|
23
|
+
end
|
24
|
+
|
22
25
|
it "should parse variables from response" do
|
23
26
|
@freec.call_vars[:call_direction].should == 'inbound'
|
24
27
|
@freec.call_vars[:caller_context].should == 'default'
|
@@ -37,6 +40,31 @@ describe Freec do
|
|
37
40
|
@freec.channel_destination_number.should == '886'
|
38
41
|
end
|
39
42
|
end
|
43
|
+
|
44
|
+
describe "ignores variables from another channel event" do
|
45
|
+
|
46
|
+
it "should not parse variables from event of another channel" do
|
47
|
+
@freec.instance_variable_set(:@response, EVENT)
|
48
|
+
@freec.send(:parse_response).should be_true
|
49
|
+
another_channel_event = EVENT.sub('Unique-ID: f3c2d5ee-d064-4f55-9280-5be2a65867e8', 'Unique-ID: ffff1111-e72d-48bf-9ecf-d71bd4b60617').
|
50
|
+
sub('Application: set', 'Application: bridge')
|
51
|
+
@freec.instance_variable_set(:@response, another_channel_event)
|
52
|
+
@freec.send(:parse_response).should be_false
|
53
|
+
@freec.call_vars[:application].should == 'set'
|
54
|
+
end
|
55
|
+
|
56
|
+
it "parses variables from disconnect notices" do
|
57
|
+
@freec.instance_variable_set(:@response, EVENT)
|
58
|
+
@freec.send(:parse_response).should be_true
|
59
|
+
@freec.call_vars[:content_type].should == 'text/event-plain'
|
60
|
+
disconnect_notice_event = EVENT.sub('Unique-ID: f3c2d5ee-d064-4f55-9280-5be2a65867e8', 'Unique-ID: ').
|
61
|
+
sub('Content-Type: text/event-plain', 'Content-Type: text/disconnect-notice')
|
62
|
+
@freec.instance_variable_set(:@response, disconnect_notice_event)
|
63
|
+
@freec.send(:parse_response).should be_true
|
64
|
+
@freec.call_vars[:content_type].should == 'text/disconnect-notice'
|
65
|
+
end
|
66
|
+
|
67
|
+
end
|
40
68
|
|
41
69
|
describe "parses an event with a body" do
|
42
70
|
before do
|
data/spec/freec_base_spec.rb
CHANGED
@@ -69,14 +69,22 @@ describe Freec do
|
|
69
69
|
|
70
70
|
end
|
71
71
|
|
72
|
+
|
72
73
|
describe "event recognition" do
|
73
74
|
|
75
|
+
it "ignores events for another channel" do
|
76
|
+
@freec.should_receive(:read_response).twice
|
77
|
+
@freec.should_receive(:parse_response).and_return(false, true)
|
78
|
+
@freec.send(:read_and_parse_response)
|
79
|
+
end
|
80
|
+
|
74
81
|
it "should subscribe to events of other leg channel after bridge" do
|
75
82
|
bridge_event = EVENT.sub('CHANNEL_EXECUTE', 'CHANNEL_BRIDGE').sub('Caller-Profile-Index: 1', 'Other-Leg-Unique-ID: 6c75cb42-e72d-48bf-9ecf-d71bd4b60617')
|
76
83
|
@freec.instance_variable_set(:@response, bridge_event)
|
77
84
|
@freec.send(:parse_response)
|
78
85
|
@freec.should_receive(:send_and_read).with("filter Unique-ID 6c75cb42-e72d-48bf-9ecf-d71bd4b60617")
|
79
86
|
@freec.send(:subscribe_to_new_channel_events)
|
87
|
+
@freec.instance_variable_get(:@want_events_from).should == ["f3c2d5ee-d064-4f55-9280-5be2a65867e8", "6c75cb42-e72d-48bf-9ecf-d71bd4b60617"]
|
80
88
|
end
|
81
89
|
|
82
90
|
it "should recognize last event was DTMF to call the on_dtmf callback" do
|
@@ -144,15 +152,13 @@ describe Freec do
|
|
144
152
|
|
145
153
|
end
|
146
154
|
|
147
|
-
describe "callback exception handling" do
|
148
|
-
|
155
|
+
describe "callback exception handling" do
|
149
156
|
it "should catch and log any exception occurred in a callback" do
|
150
157
|
@freec.should_receive(:callback_name).and_raise(RuntimeError)
|
151
158
|
@freec.log.should_receive(:error).with('RuntimeError')
|
152
159
|
@freec.log.should_receive(:error).at_least(1).times #backtrace
|
153
160
|
lambda { @freec.send(:callback, :callback_name) }.should_not raise_error(Exception)
|
154
|
-
end
|
155
|
-
|
161
|
+
end
|
156
162
|
end
|
157
163
|
|
158
164
|
describe "custom waiting conditions" do
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: freec
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 29
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 2
|
9
|
-
-
|
10
|
-
version: 0.2.
|
9
|
+
- 5
|
10
|
+
version: 0.2.5
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Jan Kubr
|
@@ -15,11 +15,11 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2010-10-
|
18
|
+
date: 2010-10-28 00:00:00 +02:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
22
|
-
name:
|
22
|
+
name: daemons
|
23
23
|
prerelease: false
|
24
24
|
requirement: &id001 !ruby/object:Gem::Requirement
|
25
25
|
none: false
|
@@ -30,8 +30,22 @@ dependencies:
|
|
30
30
|
segments:
|
31
31
|
- 0
|
32
32
|
version: "0"
|
33
|
-
type: :
|
33
|
+
type: :runtime
|
34
34
|
version_requirements: *id001
|
35
|
+
- !ruby/object:Gem::Dependency
|
36
|
+
name: rspec
|
37
|
+
prerelease: false
|
38
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ">="
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
hash: 3
|
44
|
+
segments:
|
45
|
+
- 0
|
46
|
+
version: "0"
|
47
|
+
type: :development
|
48
|
+
version_requirements: *id002
|
35
49
|
description:
|
36
50
|
email: mail@jankubr.com
|
37
51
|
executables: []
|
@@ -84,8 +98,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
84
98
|
segments:
|
85
99
|
- 0
|
86
100
|
version: "0"
|
87
|
-
requirements:
|
88
|
-
|
101
|
+
requirements: []
|
102
|
+
|
89
103
|
rubyforge_project: freec
|
90
104
|
rubygems_version: 1.3.7
|
91
105
|
signing_key:
|