fugalh-batphone 0.2.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.
Files changed (4) hide show
  1. data/ChangeLog +2 -0
  2. data/README +71 -0
  3. data/lib/agi.rb +121 -0
  4. metadata +55 -0
data/ChangeLog ADDED
@@ -0,0 +1,2 @@
1
+ Thu Jan 17 21:20:59 MST 2008
2
+ - added AGI#args
data/README ADDED
@@ -0,0 +1,71 @@
1
+ = Batphone
2
+
3
+ link:../theme/batphone.png
4
+
5
+ Batphone is an Asterisk Gateway Interface (AGI) library for Ruby. It is
6
+ well-suited to simple bat-tasks, with a small learning curve. (I promise you'll
7
+ spend more time figuring out AGI than batphone). It is also perfectly capable
8
+ of making all your wildest AGI dreams come true. It won't get in your way.
9
+
10
+ 1. http://www.voip-info.org/wiki-Asterisk+AGI
11
+
12
+ == Synopsis
13
+
14
+ In extensions.conf:
15
+
16
+ exten => batphone,1,AGI(batphone.agi)
17
+
18
+ batphone.agi:
19
+
20
+ #!/usr/bin/ruby
21
+ require 'agi'
22
+
23
+ agi = AGI.new
24
+ agi.answer
25
+ agi.stream_file('batman_help_the_monkeys_are_everywhere', nil)
26
+ begin
27
+ # press pound to make them stop!
28
+ r = agi.stream_file('tt-monkeys', '#')
29
+ end while r.result != ?#
30
+ agi.stream_file('POW', nil)
31
+ agi.hangup
32
+
33
+ == Requirements
34
+ Gee, Batman, all you need is Ruby. You might want Asterisk[http://asterisk.org]
35
+ too.
36
+
37
+ == Installation
38
+ Get it from GitHub[http://github.com/fugalh/batphone] and put it somewhere
39
+ batty.
40
+
41
+ sudo rake install
42
+ or
43
+ sudo ruby setup.rb
44
+
45
+ == Details
46
+ An AGI object serves as your proxy to Asterisk. Each time you send a command to
47
+ Asterisk using AGI#send or using the metaprogrammed interface, you get an
48
+ AGI::Response back.
49
+
50
+ == TODO
51
+ - 5xx errors span multiple lines and should be handled by the lib (probably an
52
+ exception raised too)
53
+ - It might be nice to have convenience methods that match up with regular
54
+ Asterisk Applications (commands), e.g. Playback, Background, etc.
55
+ - I'm inclined to make an OpenStruct-like interface to the Asterisk
56
+ environment, but I need to make sure there won't be any metaprogramming
57
+ conflitcs
58
+
59
+ == License
60
+ Copyright:: Copyright (C) 2007 Hans Fugal <mailto:hans@fugal.net>.
61
+ License:: Distributed under the same terms as Ruby.
62
+
63
+ == Colophon
64
+ Holy red phones, Batman! Asterisk is about phones. Rubies are red. Batphones
65
+ are really swell red phones.
66
+
67
+ No relation to batsman[http://eigenclass.org/], though I think he's swell too.
68
+
69
+ The image is from an
70
+ article[http://www.millionaireplayboy.com/toys/batphone.php] on building your
71
+ own physical batphone at Millionaire Playboy.
data/lib/agi.rb ADDED
@@ -0,0 +1,121 @@
1
+ require 'logger'
2
+ require 'ostruct'
3
+
4
+ class AGI
5
+ # Create a new AGI object and parse the Asterisk environment. Usually you
6
+ # will call this without arguments, but you might have your bat-reasons to
7
+ # provide +io_in+ and +io_out+.
8
+ #
9
+ # Also sets up a default SIGHUP trap, logging the event and calling exit. If
10
+ # you want to do some cleanup on SIGHUP instead, override it, e.g.:
11
+ # trap('SIGHUP') { cleanup }
12
+ def initialize(io_in=STDIN, io_out=STDOUT)
13
+ @io_in = io_in
14
+ @io_out = io_out
15
+
16
+ # read vars
17
+ @env = {}
18
+ while (line = @io_in.readline.strip) != ''
19
+ k,v = line.split(':')
20
+ k.strip! if k
21
+ v.strip! if v
22
+ k = $1 if k =~ /^agi_(.*)$/
23
+ @env[k] = v
24
+ end
25
+
26
+ @log = Logger.new(STDERR)
27
+
28
+ @args = ARGV
29
+
30
+ # default trap for SIGHUP, which is what Asterisk sends us when the other
31
+ # end hangs up. An uncaught SIGHUP exception pollutes STDERR needlessly.
32
+ trap('SIGHUP') { @log.debug('Holy SIGHUP, Batman!'); exit }
33
+ end
34
+
35
+ # Logger object, defaults to <tt>Logger.new(STDERR)</tt>. By default nothing
36
+ # is logged, but if you turn up the log level to +DEBUG+ you'll see the
37
+ # behind-the-scenes communication.
38
+ attr_accessor :log
39
+
40
+ # A Hash with the initial environment. Leave off the +agi_+ prefix
41
+ attr_accessor :env
42
+ alias :environment :env
43
+
44
+ # The arguments passed in the Asterisk AGI application, so
45
+ # _X,1,AGI(foo.agi|one|two|three)
46
+ # will give agi.args as ["one","two","three"].
47
+ attr_reader :args
48
+ alias :argv :args
49
+
50
+ # Environment access shortcut. Use strings or symbols as keys.
51
+ def [](key)
52
+ @env[key.to_s]
53
+ end
54
+
55
+ # Send the given command and arguments. Converts +nil+ and "" in
56
+ # +args+ to literal empty quotes
57
+ def send(cmd, *args)
58
+ args.map! {|a| (a.nil? or a == '') ? '""' : a}
59
+ msg = [cmd, *args].join(' ')
60
+ @log.debug ">> "+msg
61
+ @io_out.puts msg
62
+ @io_out.flush # I'm not sure if this is necessary, but just in case
63
+ resp = @io_in.readline
64
+ @log.debug "<< "+resp
65
+ Response.new(resp)
66
+ end
67
+
68
+ # Shortcut for send. e.g.
69
+ # a.say_time(Time.now.to_i, nil)
70
+ # is the same as
71
+ # a.send("SAY TIME",Time.now.to_i,'""')
72
+ def method_missing(symbol, *args)
73
+ cmd = symbol.to_s.upcase.tr('_',' ')
74
+ send(cmd, *args)
75
+ end
76
+
77
+ # Repeat this menu followed by the timeout, with the given digits expected.
78
+ # Use break to exit this menu.
79
+ def menu(audio,digits,timeout=3000, &block)
80
+ while true # (until the block breaks)
81
+ r = self.stream_file(audio,digits)
82
+
83
+ if r.result == 0
84
+ # nothing was dialed yet, let's wait timeout milliseconds longer
85
+ r = self.wait_for_digit(timeout)
86
+ end
87
+ yield(r) # if the block breaks, we go on with life
88
+ end
89
+ end
90
+
91
+ # The answer to every AGI#send is one of these.
92
+ class Response
93
+ # Raw response string
94
+ attr_accessor :raw
95
+ # The return code, usually (almost always) 200
96
+ attr_accessor :code
97
+ # The result value (a string)
98
+ attr_accessor :result
99
+ # The note in parentheses (if any), stripped of parentheses
100
+ attr_accessor :parenthetical
101
+ alias :note :parenthetical
102
+ # The endpos value (if any)
103
+ attr_accessor :endpos
104
+
105
+ # raw:: A string of the form "200 result=0 [(foo)] [endpos=1234]"
106
+ #
107
+ # The variables are populated as you would think. The parenthetical note is
108
+ # stripped of its parentheses.
109
+ #
110
+ # Don't forget that result is often an ASCII value rather than an integer
111
+ # value. In that case you should test against ?d where d is a digit.
112
+ def initialize(raw)
113
+ @raw = raw
114
+ @raw =~ /^(\d+)\s+result=(-?[^\s]*)(?:\s+\((.*)\))?(?:\s+endpos=(-?\d+))?/
115
+ @code = ($1 and $1.to_i)
116
+ @result = $2
117
+ @parenthetical = $3
118
+ @endpos = ($4 and $4.to_i)
119
+ end
120
+ end
121
+ end
metadata ADDED
@@ -0,0 +1,55 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: fugalh-batphone
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.0
5
+ platform: ruby
6
+ authors:
7
+ - Hans Fugal
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2008-07-14 00:00:00 -07:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description: Very simple and easy to learn bridge to AGI (Asterisk Gateway Interface)
17
+ email: hans@fugal.net
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files:
23
+ - README
24
+ files:
25
+ - README
26
+ - ChangeLog
27
+ - lib/agi.rb
28
+ has_rdoc: true
29
+ homepage: http://hans.fugal.net/src/batphone/doc/files/README.html
30
+ post_install_message:
31
+ rdoc_options: []
32
+
33
+ require_paths:
34
+ - lib
35
+ required_ruby_version: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ">="
38
+ - !ruby/object:Gem::Version
39
+ version: "0"
40
+ version:
41
+ required_rubygems_version: !ruby/object:Gem::Requirement
42
+ requirements:
43
+ - - ">="
44
+ - !ruby/object:Gem::Version
45
+ version: "0"
46
+ version:
47
+ requirements: []
48
+
49
+ rubyforge_project:
50
+ rubygems_version: 1.2.0
51
+ signing_key:
52
+ specification_version: 2
53
+ summary: Very simple and easy to learn bridge to AGI (Asterisk Gateway Interface)
54
+ test_files: []
55
+