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/.version +1 -1
- data/CHANGELOG +25 -18
- data/LICENSE +386 -269
- data/Rakefile +4 -4
- data/TODO +22 -0
- data/ahn +72 -56
- data/apps/default/config/adhearsion.sqlite3 +0 -0
- data/apps/default/config/adhearsion.yml +52 -1
- data/apps/default/config/helpers/growler.yml +21 -0
- data/apps/default/config/migration.rb +7 -11
- data/apps/default/helpers/growler.rb +53 -0
- data/apps/default/helpers/lookup.rb +27 -18
- data/apps/default/helpers/manager_proxy.rb +19 -2
- data/apps/default/helpers/micromenus.rb +1 -1
- data/lib/adhearsion.rb +257 -44
- data/lib/constants.rb +15 -12
- data/lib/core_extensions.rb +11 -11
- data/lib/drb_server.rb +101 -0
- data/lib/logging.rb +18 -1
- data/lib/servlet_container.rb +23 -23
- data/test/asterisk_module_test.rb +1 -1
- metadata +35 -23
- data/apps/default/helpers/drb_server.rb +0 -32
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
|
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 = '
|
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
|
4
|
-
|
5
|
-
#
|
6
|
-
|
7
|
-
#
|
8
|
-
#
|
9
|
-
#
|
10
|
-
#
|
11
|
-
# of the
|
12
|
-
#
|
13
|
-
|
14
|
-
#
|
15
|
-
#
|
16
|
-
|
17
|
-
#
|
18
|
-
#
|
19
|
-
#
|
20
|
-
#
|
21
|
-
|
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'
|
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
|
-
|
107
|
-
|
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(
|
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
|
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
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
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
|
-
|
179
|
-
|
180
|
-
|
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
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
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,
|
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
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
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
|