AsteriskRuby 1.0.0

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.
@@ -0,0 +1,139 @@
1
+ =begin rdoc
2
+ Copyright (c) 2007, Vonage Holdings
3
+
4
+ All rights reserved.
5
+
6
+ Redistribution and use in source and binary forms, with or without
7
+ modification, are permitted provided that the following conditions are met:
8
+
9
+ * Redistributions of source code must retain the above copyright
10
+ notice, this list of conditions and the following disclaimer.
11
+ * Redistributions in binary form must reproduce the above copyright
12
+ notice, this list of conditions and the following disclaimer in the
13
+ documentation and/or other materials provided with the distribution.
14
+ * Neither the name of Vonage Holdings nor the names of its
15
+ contributors may be used to endorse or promote products derived from this
16
+ software without specific prior written permission.
17
+
18
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
22
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28
+ POSSIBILITY OF SUCH DAMAGE.
29
+
30
+ Author: Michael Komitee <mkomitee@gmail.com>
31
+ AGIExceptions declares various exception classes for the AGI Framework.
32
+ =end
33
+
34
+ #There are several possible Exceptions that can occur with AGI communication. This file provides custom exception classes that mirror them.
35
+ #= Exceptions:
36
+ #* AGIError
37
+ #* AGIHangupError
38
+ #* AGITimeoutError
39
+ #* AGIChannelError
40
+ #* AGICommandError
41
+ #* AGIInitializeError
42
+
43
+ #AGIError is the base Exception Class from which all other AGI Exceptions inherit.
44
+ #= Children:
45
+ #* AGIHangupError
46
+ #* AGITimeoutError
47
+ #* AGIChannelError
48
+ #* AGICommandError
49
+ #* AGIInitializeError
50
+ class AGIError < Exception
51
+ # This is the raw string returned from Asterisk to the AGI if one was available
52
+ attr_accessor :raw_data
53
+ def initialize(raw_data, *rest)
54
+ @raw_data = raw_data
55
+ super(rest)
56
+ end
57
+ def to_s
58
+ @raw_data
59
+ end
60
+ def to_str
61
+ self.to_s
62
+ end
63
+ end
64
+
65
+ #AGIHangupError signifies that the Asterisk Channel associated with the AGI has been hung up, unexpectedly. It inherits from AGIError.
66
+ class AGIHangupError < AGIError
67
+ end
68
+
69
+ #AGITimeoutError signifies that a Asterisk notified the AGI that a requested command timed out. It inherits from AGIError.
70
+ class AGITimeoutError < AGIError
71
+ end
72
+
73
+ #AGIChannelError signifies that Asterisk notified the AGI of a channel error. It inherits from AGIError.
74
+ class AGIChannelError < AGIError
75
+ end
76
+
77
+ #AGICommandError signifies that Asterisk has notified us that there was an error with the requested Command, usually the syntax. It inherits from AGIError.
78
+ class AGICommandError < AGIError
79
+ end
80
+
81
+ #AGIInitializeError significes that the AGI has been instructed to initialize a channel which had previously been reinitialized. If this is actually intended, it can be accomplished by first calling reinit, which will reset channel parameters beforehand.
82
+ class AGIInitializeError < AGIError
83
+ end
84
+
85
+ #AGIMenuFailure signifies that there was a failure in constructing or playing an AGIMenu
86
+ class AGIMenuFailure < Exception
87
+ def initialize(str)
88
+ @message = str
89
+ end
90
+ def to_s
91
+ @message
92
+ end
93
+ def to_str
94
+ self.to_s
95
+ end
96
+ end
97
+
98
+ class AGIStateFailure < Exception
99
+ def initialize(str)
100
+ @message = str
101
+ end
102
+ def to_s
103
+ @message
104
+ end
105
+ def to_str
106
+ self.to_s
107
+ end
108
+ end
109
+
110
+ =begin
111
+ Copyright (c) 2007, Vonage Holdings
112
+
113
+ All rights reserved.
114
+
115
+ Redistribution and use in source and binary forms, with or without
116
+ modification, are permitted provided that the following conditions are met:
117
+
118
+ * Redistributions of source code must retain the above copyright
119
+ notice, this list of conditions and the following disclaimer.
120
+ * Redistributions in binary form must reproduce the above copyright
121
+ notice, this list of conditions and the following disclaimer in the
122
+ documentation and/or other materials provided with the distribution.
123
+ * Neither the name of Vonage Holdings nor the names of its
124
+ contributors may be used to endorse or promote products derived from this
125
+ software without specific prior written permission.
126
+
127
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
128
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
129
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
130
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
131
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
132
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
133
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
134
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
135
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
136
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
137
+ POSSIBILITY OF SUCH DAMAGE.
138
+
139
+ =end
@@ -0,0 +1,69 @@
1
+ =begin rdoc
2
+ Copyright (c) 2007, Vonage Holdings
3
+
4
+ All rights reserved.
5
+
6
+ Redistribution and use in source and binary forms, with or without
7
+ modification, are permitted provided that the following conditions are met:
8
+
9
+ * Redistributions of source code must retain the above copyright
10
+ notice, this list of conditions and the following disclaimer.
11
+ * Redistributions in binary form must reproduce the above copyright
12
+ notice, this list of conditions and the following disclaimer in the
13
+ documentation and/or other materials provided with the distribution.
14
+ * Neither the name of Vonage Holdings nor the names of its
15
+ contributors may be used to endorse or promote products derived from this
16
+ software without specific prior written permission.
17
+
18
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
22
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28
+ POSSIBILITY OF SUCH DAMAGE.
29
+
30
+ Author: Michael Komitee <mkomitee@gmail.com>
31
+
32
+ This is a meta package for the framework at large.
33
+ =end
34
+
35
+ require 'AGI'
36
+ require 'AGIMenu'
37
+ require 'AGIServer'
38
+ require 'AGIState'
39
+ require 'AGISelection'
40
+
41
+ =begin
42
+ Copyright (c) 2007, Vonage Holdings
43
+
44
+ All rights reserved.
45
+
46
+ Redistribution and use in source and binary forms, with or without
47
+ modification, are permitted provided that the following conditions are met:
48
+
49
+ * Redistributions of source code must retain the above copyright
50
+ notice, this list of conditions and the following disclaimer.
51
+ * Redistributions in binary form must reproduce the above copyright
52
+ notice, this list of conditions and the following disclaimer in the
53
+ documentation and/or other materials provided with the distribution.
54
+ * Neither the name of Vonage Holdings nor the names of its
55
+ contributors may be used to endorse or promote products derived from this
56
+ software without specific prior written permission.
57
+
58
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
59
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
60
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
61
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
62
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
63
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
64
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
65
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
66
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
67
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
68
+ POSSIBILITY OF SUCH DAMAGE.
69
+ =end
@@ -0,0 +1,244 @@
1
+ =begin rdoc
2
+ Copyright (c) 2007, Vonage Holdings
3
+
4
+ All rights reserved.
5
+
6
+ Redistribution and use in source and binary forms, with or without
7
+ modification, are permitted provided that the following conditions are met:
8
+
9
+ * Redistributions of source code must retain the above copyright
10
+ notice, this list of conditions and the following disclaimer.
11
+ * Redistributions in binary form must reproduce the above copyright
12
+ notice, this list of conditions and the following disclaimer in the
13
+ documentation and/or other materials provided with the distribution.
14
+ * Neither the name of Vonage Holdings nor the names of its
15
+ contributors may be used to endorse or promote products derived from this
16
+ software without specific prior written permission.
17
+
18
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
22
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28
+ POSSIBILITY OF SUCH DAMAGE.
29
+
30
+ Author: Michael Komitee <mkomitee@gmail.com>
31
+
32
+ Sometimes when dealing with Asterisk AGI, a generic AGIMenu object can come in handy. Thats where the aptly named AGIMenu object comes into play. With AGIMenu, you can configure a menu of options based on a yaml configuration or a hash. For example:
33
+
34
+ AGIMenu.sounds_dir = 'agimenu-test/sounds/'
35
+ hash = {:introduction=>["welcome", "instructions"],
36
+ :conclusion=>"what-is-your-choice",
37
+ :timeout=>17,
38
+ :choices=>
39
+ [{:dtmf=>"*", :audio=>["to-go-back", "press", "digits/star"]},
40
+ {:dtmf=>1, :audio=>["press", "digits/1", "for-option-1"]},
41
+ {:dtmf=>2, :audio=>["press", "digits/2", "for-option-2"]},
42
+ {:dtmf=>"#", :audio=>["or", "press", "digits/pound", "to-repeat"]}]}
43
+
44
+ menu = AGIMenu.new(hash)
45
+ menu.play(:agi => AGI.new())
46
+
47
+ This results in Asterisk using sounds in it's agimenu-test/sounds directory to play a menu which accepts the DTMF *, 1, 2, or #. It will first play the introduction sound files 'welcome' and 'instructions', then play the menu sound files 'to-go-back' 'press' 'digits/star' 'press' 'digits/1' 'for-option-1' 'press 'digits/2' 'for-option-2' 'or' 'press' 'digits/pound' 'to-repeat', and then play the conslusion sound file 'what-is-your-choice' and then wait 17 seconds.
48
+
49
+ You could hand AGIMenu.new() a filename, a file, a yaml oject, a hash, or nothing at all. You can then modify the menu with the classes various methods.
50
+ =end
51
+
52
+ require 'yaml'
53
+ require 'AGI'
54
+
55
+ class AGIMenu
56
+ @@sounds_dir = ''
57
+ attr_accessor :title
58
+ attr_reader :params
59
+ def initialize(input=nil)
60
+ @title = 'AGIMenu:' + self.object_id.to_s
61
+ @sounds = Hash.new
62
+ @order = []
63
+ @introduction = []
64
+ @conclusion = []
65
+ @default_timeout = 600
66
+ @params=input
67
+ configure(input)
68
+ end
69
+ def add(digit, sound)
70
+ if @order.include?(digit.to_s) then
71
+ raise AGIMenuFailure.new("Duplicate Digit entry (#{digit.to_s}) in AGIMenu: '#{@title}'")
72
+ elsif digit.to_s =~ /[0-9#*]/
73
+ @sounds[digit.to_s] = [ sound ].flatten
74
+ @order.push(digit.to_s)
75
+ else
76
+ raise AGIMenuFailure.new("Invalid Digit entry (#{digit.to_s}) in AGIMenu: '#{@title}'")
77
+ end
78
+ end
79
+ def digits
80
+ @order
81
+ end
82
+ alias :dtmf :digits
83
+ alias :order :digits
84
+ def timeout=(timeout)
85
+ @default_timeout = timeout.to_i
86
+ end
87
+ def timeout
88
+ @default_timeout
89
+ end
90
+ def introduction=(introduction)
91
+ @introduction = [ introduction ].flatten
92
+ end
93
+ def introduction
94
+ @introduction
95
+ end
96
+ def conclusion=(conclusion)
97
+ @conclusion = [ conclusion ].flatten
98
+ end
99
+ def conclusion
100
+ @conclusion
101
+ end
102
+ def reorder(new_order, force=false)
103
+ new_order.collect!{ |dtmf| dtmf.to_s }
104
+ if @order.sort != new_order.sort
105
+ raise AGIMenuFailure.new("New and old order are incompatible in AGIMenu: '#{@title}'") unless force
106
+ end
107
+ @order = new_order
108
+ end
109
+
110
+ def play(conf={})
111
+ defaults = {:introduction => true, :conclusion => true, :timeout => @default_timeout}
112
+ conf = defaults.merge(conf)
113
+ unless conf[:agi].respond_to?(:background) and conf[:agi].respond_to?(:wait_for_digit)
114
+ raise ArgumentError, ":agi required, must be an AsteriskAGI for AGIMenu.play in AGIMenu: '#{@title}'"
115
+ end
116
+ digits = @order.join()
117
+ audio = []
118
+ case
119
+ when conf[:introduction].class == TrueClass
120
+ audio << add_introduction
121
+ when conf[:introduction]
122
+ audio << add_introduction(conf[:introduction])
123
+ end
124
+ audio << add_body
125
+ audio << add_conclusion if conf[:conclusion]
126
+ result = conf[:agi].background(audio.flatten, "'#{digits}'")
127
+ return result unless result.nil?
128
+ return result if conf[:timeout].nil?
129
+ return handle_timeout(conf[:agi], conf[:timeout].to_i)
130
+ end
131
+ alias :background :play
132
+ alias :execute :play
133
+
134
+ def AGIMenu.sounds_dir=(dir)
135
+ @@sounds_dir = dir
136
+ end
137
+ def AGIMenu.sounds_dir
138
+ @@sounds_dir
139
+ end
140
+
141
+ private
142
+ def handle_timeout(agi, timeout)
143
+ begin
144
+ start = Time.now.to_i
145
+ result = agi.wait_for_digit(timeout*1000)
146
+ if self.dtmf.include?(result.data.to_s)
147
+ return result
148
+ else
149
+ raise AGIMenuFailure.new("Invalid DTMF Supplied #{result.data.to_s} in AGIMenu: '#{@title}'")
150
+ end
151
+ rescue AGITimeoutError
152
+ return nil
153
+ rescue AGIMenuFailure => err
154
+ retry if timeout == -1
155
+ elapsed = Time.now.to_i - start.to_i
156
+ timeout = timeout - elapsed
157
+ return nil if timeout <= 0
158
+ retry
159
+ end
160
+ end
161
+
162
+ def add_introduction(introduction=[])
163
+ audio = []
164
+ introduction = @introduction if introduction.empty?
165
+ [introduction].flatten.each { |i| audio << "#{@@sounds_dir}#{i}" }
166
+ return audio
167
+ end
168
+
169
+ def add_body
170
+ audio = []
171
+ @order.each do
172
+ |i|
173
+ begin
174
+ @sounds[i].each { |sound| audio << "#{@@sounds_dir}#{sound}" }
175
+ rescue NoMethodError => err
176
+ raise AGIMenuFailure.new("Invalid Order forced, #{i} an invalid choice in AGIMenu: '#{@title}'")
177
+ puts "Caught #{err.class}: #{err} - #{err.message}"
178
+ end
179
+ end
180
+ return audio
181
+ end
182
+ def add_conclusion
183
+ audio = []
184
+ @conclusion.flatten.each { |i| audio << "#{@@sounds_dir}#{i}" }
185
+ return audio
186
+ end
187
+ def configure(input)
188
+ if input.respond_to?(:read)
189
+ config = YAML::load( input )
190
+ elsif input.respond_to?(:to_hash)
191
+ config = input
192
+ elsif input.respond_to?(:to_s) and File.exists?(input.to_s) and File.readable?(input.to_s)
193
+ config = File.open( input.to_s ) { |f| YAML::load( f ) }
194
+ end
195
+ if config.respond_to?(:to_hash)
196
+ @params = config
197
+ if config.has_key?(:introduction)
198
+ @introduction = [config[:introduction]].flatten
199
+ end
200
+ if config.has_key?(:conclusion)
201
+ @conclusion = [config[:conclusion]].flatten
202
+ end
203
+ if config.has_key?(:timeout)
204
+ @default_timeout = config[:timeout]
205
+ end
206
+ if config.has_key?(:choices)
207
+ config[:choices].each { |choice| add(choice[:dtmf], choice[:audio]) }
208
+ end
209
+ if config.has_key?(:title)
210
+ @title = config[:title]
211
+ end
212
+ end
213
+ end
214
+ end
215
+
216
+ =begin
217
+ Copyright (c) 2007, Vonage Holdings
218
+
219
+ All rights reserved.
220
+
221
+ Redistribution and use in source and binary forms, with or without
222
+ modification, are permitted provided that the following conditions are met:
223
+
224
+ * Redistributions of source code must retain the above copyright
225
+ notice, this list of conditions and the following disclaimer.
226
+ * Redistributions in binary form must reproduce the above copyright
227
+ notice, this list of conditions and the following disclaimer in the
228
+ documentation and/or other materials provided with the distribution.
229
+ * Neither the name of Vonage Holdings nor the names of its
230
+ contributors may be used to endorse or promote products derived from this
231
+ software without specific prior written permission.
232
+
233
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
234
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
235
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
236
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
237
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
238
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
239
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
240
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
241
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
242
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
243
+ POSSIBILITY OF SUCH DAMAGE.
244
+ =end