adhearsion 0.7.5 → 0.7.6

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/Rakefile CHANGED
@@ -4,8 +4,7 @@ require 'rake/rdoctask'
4
4
  require 'rake/gempackagetask'
5
5
 
6
6
  ADHEARSION_VERSION = File.read('.version').strip
7
- Summary = %{Adhearsion is a professional integration system for
8
- integrating anything and everything.}
7
+ Summary = %{Adhearsion is metaprogramming framework for developing collaboration software.}
9
8
 
10
9
  #task :default => [:test]
11
10
 
@@ -27,14 +26,15 @@ GEM_SPEC = Gem::Specification.new do |s|
27
26
  s.name = 'adhearsion'
28
27
  s.rubyforge_project = 'adhearsion'
29
28
  s.author = 'Jay Phillips'
30
- s.email = 'admin -at- jicksta dot com'
29
+ s.email = 'jay -at- codemecca dot com'
31
30
  s.version = ADHEARSION_VERSION
32
31
  s.summary = Summary
33
32
  s.homepage = 'http://adhearsion.com'
34
33
 
35
34
  s.add_dependency 'activerecord', '>= 1.14.4'
36
35
  s.add_dependency 'rake', '>= 0.7.1'
37
-
36
+ s.add_dependency 'daemons', '>= 1.0.5'
37
+
38
38
  s.platform = Gem::Platform::RUBY
39
39
  s.require_path = 'lib'
40
40
  s.executables = 'ahn'
data/TODO ADDED
@@ -0,0 +1,22 @@
1
+ Port Jason's T2S work into trunk when stable. Jason?
2
+
3
+ Port in new Micromenus browser GUI
4
+
5
+ Support ITAD routing using ENUM lookups.
6
+ Major file structure refactoring!
7
+
8
+ Port in RAI's AMI work.
9
+
10
+ Port in RAI's Rails app initialization and routing integration.
11
+
12
+ Develop a reasonable RSpec testing framework for Adhearsion.
13
+
14
+ Have AGI server optionally powered by mongrel
15
+
16
+ Port Micromenus server over to Camping
17
+
18
+ Adhearsion CLI. Should use the 'breakpoint' library's DRb extension to run an irb session in an external Ruby interpreter (Adhearsion's)
19
+
20
+ Let record() take a block of functionality to record. This feature will probably only be available when an AMI connection is present.
21
+
22
+ Build in hunt-group support into dial()
data/ahn CHANGED
@@ -1,25 +1,24 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- # This is the main executable file of Adhearsion.
4
-
5
- # Copyright (c) 2006 Jay Phillips
6
-
7
- # Permission is hereby granted, free of charge, to any person obtaining a copy of
8
- # this software and associated documentation files (the "Software"), to deal in
9
- # the Software without restriction, including without limitation the rights to
10
- # use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
11
- # of the Software, and to permit persons to whom the Software is furnished to do
12
- # so, subject to the following conditions:
13
-
14
- # The above copyright notice and this permission notice shall be included in all
15
- # copies or substantial portions of the Software.
16
-
17
- # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
- # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
- # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20
- # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
21
- # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22
- # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
3
+ # This is the main executable file.
4
+
5
+ # Adhearsion, open source technology integrator
6
+ # Copyright (C) 2006,2007 Jay Phillips
7
+ #
8
+ # This library is free software; you can redistribute it and/or
9
+ # modify it under the terms of the GNU Lesser General Public
10
+ # License as published by the Free Software Foundation; either
11
+ # version 2.1 of the License, or (at your option) any later version.
12
+ #
13
+ # This library is distributed in the hope that it will be useful,
14
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16
+ # Lesser General Public License for more details.
17
+ #
18
+ # You should have received a copy of the GNU Lesser General Public
19
+ # License along with this library; if not, write to the Free Software
20
+ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21
+ require 'rubygems'
23
22
 
24
23
  usage = "Usage:
25
24
  ahn create /path/to/directory
@@ -33,9 +32,9 @@ Under development:
33
32
  ahn search keyword
34
33
  ahn uninstall/remove helpername"
35
34
 
36
- $: << File.join(File.dirname(__FILE__), 'lib')
35
+ $: << File.join(File.expand_path(File.dirname(__FILE__)), 'lib')
37
36
  ADHEARSION_VERSION = File.read(File.join(File.dirname(__FILE__), '.version')).strip
38
- ARGV.unshift 'start' if ARGV.empty? # Set the default operation
37
+ ARGV.unshift 'start' if ARGV.empty? # Set the default operation
39
38
 
40
39
  require 'yaml'
41
40
 
@@ -103,15 +102,17 @@ Adhearsion project generated!
103
102
 
104
103
  Start your new app with "ahn start #{dest_dir_relative}"
105
104
 
106
- For dial plan management, change the appropriate contexts
107
- in your /etc/asterisk/extensions.conf file to the following:
105
+ If you wish to use Adhearsion to control Asterisk's dialplan,
106
+ change the contexts you wish to be affected in your
107
+ /etc/asterisk/extensions.conf file to the following:
108
108
 
109
109
  [your_context_name]
110
110
  exten => _X.,1,AGI(agi://1.2.3.4) ; This IP here
111
111
 
112
- To use databases edit config/database.yml for the
112
+ To use databases, edit config/database.yml for the
113
113
  connection information and, optionally, config/database.rb
114
- to change the default database object models.
114
+ to change the default database object models. To create your
115
+ tables, you may wish to use config/migration.rb.
115
116
 
116
117
  Asterisk Manager interface integration is highly recommended.
117
118
  Edit your /etc/asterisk/manager.conf file and enable the
@@ -131,12 +132,23 @@ when 'start'
131
132
  target = Dir.pwd
132
133
 
133
134
  arg = ARGV.shift
134
- if arg =~ /daemon(ize)?/
135
+ if arg =~ /daemon(ized)?/
135
136
  $DAEMON = true
136
137
  arg = ARGV.shift
137
138
  end
138
139
  target = File.expand_path(arg || target)
139
140
 
141
+ puts %{\nStarting Adhearsion v#{ADHEARSION_VERSION}
142
+ Written by Jay Phillips of Codemecca LLC, et al.
143
+ http://adhearsion.com\n\n}
144
+
145
+ if $DAEMON
146
+ require 'rubygems'
147
+ require 'daemons'
148
+ puts "Daemonizing now!"
149
+ Daemons.daemonize
150
+ end
151
+
140
152
  Dir.chdir target
141
153
 
142
154
  adhearsion_config = File.join('config', 'adhearsion.yml')
@@ -146,10 +158,7 @@ when 'start'
146
158
  register_logger StandardLogger.new(STDOUT)
147
159
 
148
160
  register_logger StandardLogger.new('logs/adhearsion.log')
149
-
150
- puts %{\nStarting Adhearsion v#{ADHEARSION_VERSION}
151
- Written by Jay Phillips of Codemecca LLC, et al.
152
- http://adhearsion.com\n\n}
161
+
153
162
 
154
163
  %w(rubygems uri open-uri abbrev thread).each { |lib| require lib }
155
164
 
@@ -158,45 +167,52 @@ when 'start'
158
167
  require 'adhearsion'
159
168
  require 'database' if CONFIG['enable_database']
160
169
  require 'servlet_container'
161
- require "constants"
170
+ require 'constants'
171
+
172
+ if CONFIG['drb'] && CONFIG['drb']['enabled']
173
+ require 'drb_server'
174
+ DRbServerManager.start
175
+ end
162
176
 
163
177
  # Load appropriate helpers
164
178
  $HELPERS = {}
165
179
  Contexts::Container.new.run_inside do
166
180
  # Start with compiled helpers
167
- class << Object
168
- aliens = Dir[File.join('helpers', '*.alien.*')]
169
- aliens.each do |f|
170
- f = File.basename f
171
- config_file = File.join %W(config helpers #{f}.yml)
172
- config = File.readable?(config_file) ? YAML.load_file(config_file) : {}
173
- if config.delete('enabled') != false
174
- require 'inline'
175
- lang = f[f.rindex('.')+1..-1]
176
- log "Loading helper #{f} as #{lang.upcase}"
181
+ class Object
182
+ class << self
183
+ aliens = Dir[File.join('helpers', '*.alien.*')]
184
+ aliens.each do |f|
185
+ f = File.basename f
186
+ config_file = File.join %W(config helpers #{f}.yml)
187
+ config = File.readable?(config_file) ? YAML.load_file(config_file) : {}
188
+ if config.delete('enabled') != false
189
+ require 'inline'
190
+ lang = f[f.rindex('.') + 1..-1]
191
+ log "Loading helper #{f} as #{lang.upcase}"
177
192
 
178
- $HELPERS[f] = config
179
- inline do |builder|
180
- builder.send lang, File.read(File.join('helpers', f))
193
+ $HELPERS[f] = config
194
+ inline do |builder|
195
+ builder.send lang, File.read(File.join('helpers', f))
196
+ end
181
197
  end
182
198
  end
183
199
  end
184
- end
185
200
 
186
- # Load Ruby helpers
187
- Dir[File.join('helpers', '*.rb')].each do |f|
188
- name = File.basename(f)[/^[^.]+/]
189
- config_file = File.join %W(config helpers #{name}.yml)
190
- config = File.readable?(config_file) ? YAML.load_file(config_file) : {}
191
- if config.delete('enabled') != false
192
- log "Parsing helper #{name}"
193
- $HELPERS[name] = config
194
- eval File.read(f)
201
+ # Load Ruby helpers
202
+ Dir[File.join('helpers', '*.rb')].each do |f|
203
+ name = File.basename(f)[/^[^.]+/]
204
+ config_file = File.join %W(config helpers #{name}.yml)
205
+ config = File.readable?(config_file) ? YAML.load_file(config_file) : {}
206
+ if config.delete('enabled') != false
207
+ log "Parsing helper #{name}"
208
+ $HELPERS[name] = config
209
+ eval File.read(f)
210
+ end
195
211
  end
196
212
  end
197
213
  end
198
214
 
199
- sc = ServletContainer.new(CONFIG['port'] || 4573)
215
+ sc = ServletContainer.new((CONFIG['port'] || 4573), (CONFIG['host'] || '0.0.0.0'))
200
216
  $HUTDOWN.hook { sc.shutdown }
201
217
 
202
218
  log "Dallas, we have liftoff!"
Binary file
@@ -1,6 +1,7 @@
1
1
  answer_before_call: true
2
2
  hangup_after_call: true
3
3
  enable_database: false
4
+ host: 0.0.0.0
4
5
  port: 4573
5
6
 
6
7
  # This information is completely optional. It may be the
@@ -17,7 +18,57 @@ port: 4573
17
18
  # zip: 77777
18
19
  # country: United States
19
20
 
21
+
22
+ # If you wish to use named conferences in your dial plan,
23
+ # uncomment the lines below. To use, pass the name to
24
+ # the join() method as a Symbol. e.g. join :management
25
+ #
20
26
  # conferences:
21
27
  # management: 1000
22
28
  # marketing: 1001
23
- # development: 1002
29
+ # development: 1002
30
+
31
+ drb:
32
+ enabled: false
33
+ host: 127.0.0.1
34
+ port: 9050
35
+
36
+ deny: all
37
+ allow:
38
+ - 127.0.0.1
39
+ - 192.168.1.*
40
+
41
+ # Set your access control permissions above.
42
+ # Values for deny and allow can be several
43
+ # things:
44
+ #
45
+ # * The 'all' keyword can be used to match
46
+ # everything.
47
+ # * A single IP can be given right after
48
+ # the colon.
49
+ # * A single IP with wildcards can be given
50
+ # * Or, combining all of these, a YAML list
51
+ # can be used to specify many policies.
52
+ # See the comments below for more examples.
53
+ #
54
+ # Also note, the "host" field above may also
55
+ # affect the ability for DRb clients to connect
56
+ # to the server. If you wish you receive
57
+ # connections from the 192.168.1.*, listen on
58
+ # the IP associated with this machine on that
59
+ # subnet.
60
+ #
61
+ #
62
+ # USING YAML LISTS
63
+ #
64
+ # YAML allows lists of items to be created by
65
+ # prepending a hyphen to each list element.
66
+ # These lists can be used to refine your
67
+ # access control list better. Example:
68
+ #
69
+ # deny: all
70
+ # allow:
71
+ # - 192.168.1.123
72
+ # - 192.168.1.99
73
+ # - 66.199.34.44
74
+
@@ -0,0 +1,21 @@
1
+ enabled: false
2
+
3
+ # This is how growl identifies this client.
4
+ app_name: Adhearsion
5
+
6
+ # When dealing with only a single machine, set this
7
+ # to your desktop's IP. If you want multiple servers,
8
+ # you can manually pass the IP address as the second
9
+ # argument to growl() and password as the third.
10
+
11
+ # Leave ip empty if you intend to specify it manually
12
+ ip: localhost
13
+ password: # Leave as-is if none
14
+
15
+ # This is a list of the different types of notifications
16
+ # Growl should expect from this client. These can be
17
+ # anything you want. Names are case sensitive. Note: At
18
+ # least one must exist!
19
+ notifications:
20
+ - Standard Notification
21
+ - Incoming Call
@@ -5,7 +5,8 @@ require 'active_record'
5
5
 
6
6
  # A migration script uses a database configuration and creates tables
7
7
  # very conveniently in a database-agnostic way. Below, add any customizations
8
- # to the sample schema or leave it as-is. When done, execute this script.
8
+ # to the sample schema or leave it as-is. When done, type "rake migrate" to
9
+ # have this schema generated.
9
10
 
10
11
  ActiveRecord::Base.establish_connection YAML.load_file('config/database.yml')
11
12
 
@@ -15,15 +16,14 @@ class CreateUsers < ActiveRecord::Migration
15
16
  def self.up
16
17
  create_table :users do |t|
17
18
  t.column :name, :string
18
- t.column :callerid_name, :string
19
- t.column :callerid_num, :string
20
19
  t.column :group_id, :integer # Foreign key
21
- t.column :ivr_extension, :string
22
20
  t.column :extension, :string
23
- t.column :email, :string
24
- t.column :im_username, :string
25
- t.column :im_provider, :string
26
21
  # t.column :billed_time, :integer, :null => false
22
+
23
+ # Feel free to remove or change this to "email". Gmail offers email,
24
+ # instant messaging, calendars, and so forth -- all of which you
25
+ # can integrate with using one simple username.
26
+ t.column :gmail, :string
27
27
  end
28
28
  end
29
29
 
@@ -47,7 +47,3 @@ class CreateGroups < ActiveRecord::Migration
47
47
  drop_table :groups
48
48
  end
49
49
  end
50
-
51
- # Run "rake migrate" to run this script properly.
52
- # CreateUsers.up
53
- # CreateGroups.up
@@ -0,0 +1,53 @@
1
+ =begin Adhearsion metadata
2
+ name: Adhearsion Growler
3
+ author:
4
+ name: Phil Kates
5
+ email: hawk684 -at- gmail.com
6
+ modified-by: Jay Phillips
7
+ gems:
8
+ - ruby-growl
9
+ =end
10
+
11
+ require 'ruby-growl'
12
+
13
+ GROWL_SERVER = unless $HELPERS['growler']['ip'] then nil else
14
+ Growl.new $HELPERS['growler']['ip'] || 'localhost',
15
+ $HELPERS['growler']['app_name'] || "Adhearsion",
16
+ $HELPERS['growler']['notifications'],
17
+ nil, $HELPERS['growler']['password']
18
+ end
19
+
20
+ # Sends a message to an OSX desktop's Growl notification server. If you
21
+ # intend to only notify a single machine, you can specify the parameters
22
+ # in growler.yml.
23
+ #
24
+ # == Usage:
25
+ #
26
+ # - message: The notification or message you wish to send!
27
+ # - type (optional): The type of notification as specified in the growler.yml
28
+ # config file. This defaults to the first "notifications" entry. If you want
29
+ # growl() to automatically set this for you, simply send it nil.
30
+ # - ip (optional): The desktop's IP address you wish to notify. This
31
+ # by default uses what's in growler.yml or, if unavailable, "localhost".
32
+ # - password (optional): a password if one is needed. Defaults to nothing.
33
+ #
34
+ # == Examples:
35
+ # - growl "Isn't it about time you debugged me?"
36
+ # - growl "Call from #{callerid}!", "Incoming Call"
37
+ # - growl "The caller queue size is #{queue.size}", nil, "192.168.1.133"
38
+ # - growl "Join conference 1234!", nil, "192.168.50.151", "Secretz!"
39
+ def growl message, type=nil, ip=nil, password=nil
40
+ type = $HELPERS['growler']['notifications'].first unless type
41
+
42
+ # Create a new Growl client if an IP was specified, otherwise use
43
+ # our server created when Adhearsion booted.
44
+ svr = unless ip then GROWL_SERVER else
45
+ Growl.new ip, $HELPERS['growler']['app_name'] || "Adhearsion",
46
+ $HELPERS['growler']['notifications'], nil,
47
+ $HELPERS['growler']['password']
48
+ end
49
+
50
+ # TODO support priorities and stickies. May need to use hash-key argments?
51
+ # TODO handle unreachable desktops
52
+ svr.notify type, type, message
53
+ end
@@ -10,25 +10,34 @@ def lookup number
10
10
  hash = {}
11
11
  url = "http://www.whitepages.com/9901/search/ReversePhone?phone=#{number}"
12
12
  doc = Hpricot open(url)
13
+
14
+ # This div contains all the information we need, unless it's an unlisted number
15
+ if (results = doc.at "#results_single_listing") then
16
+ # This div's h3 contains the name of the caller
17
+ hash[:first_name], hash[:last_name] = results.at('h3').inner_html.split(/,\s*/).reverse
18
+
19
+ # Now we just need the rest of the information contained in p's.
20
+ meta = results/'p'
21
+ meta.pop # Discard the useless p element
22
+
23
+ hash[:number] = meta.pop.inner_html
24
+ city_info = meta.pop.inner_html
25
+ city_info = city_info.match /(.+), ([A-Za-z]{2}) (\d{5})/
26
+ hash[:city] = city_info[1]
27
+ hash[:state] = city_info[2]
28
+ hash[:zip] = city_info[3]
29
+
30
+ hash[:address] = meta.map(&:inner_html) * " "
31
+ elsif (results = doc.at "#results_single_phone_info") then
32
+ meta = results/'span'
33
+ hash[:location] = (meta.pop.inner_html.match /Location: (.*)/)[1]
34
+ end
13
35
 
14
- # This div contains all the information we need
15
- results = doc.at "#results_single_listing"
16
-
17
- # This div's h3 contains the name of the caller
18
- hash[:first_name], hash[:last_name] = results.at('h3').inner_html.split(/,\s*/).reverse
19
-
20
- # Now we just need the rest of the information contained in p's.
21
- meta = results/'p'
22
- meta.pop # Discard the useless p element
23
-
24
- hash[:number] = meta.pop.inner_html
25
- city_info = meta.pop.inner_html
26
- city_info = city_info.match /(.+), ([A-Za-z]{2}) (\d{5})/
27
- hash[:city] = city_info[1]
28
- hash[:state] = city_info[2]
29
- hash[:zip] = city_info[3]
30
-
31
- hash[:address] = meta.map(&:inner_html) * " "
36
+ if hash[:first_name] or hash[:last_name] then
37
+ hash[:composite] = "#{hash[:first_name]} #{hash[:last_name]}"
38
+ else
39
+ hash[:composite] = hash[:location]
40
+ end
32
41
 
33
42
  hash
34
43
  end