Slightly more progress - warvox - VoIP based wardialing tool, forked from rapid7/warvox.
(DIR) Log
(DIR) Files
(DIR) Refs
(DIR) README
---
(DIR) commit 08a2e4abad16cf7bfd22d010c513ce3429a3342b
(DIR) parent 9cb1016e0f3aa69356bea154884e6f4f16a7041b
(HTM) Author: HD Moore <hd_moore@rapid7.com>
Date: Tue, 2 Aug 2011 07:16:54 +0000
Slightly more progress
Diffstat:
M etc/sigs/01.default.rb | 13 ++++++++-----
M etc/sigs/99.default.rb | 9 +++++++--
M lib/warvox/audio/raw.rb | 101 ++++++++++++++++---------------
M lib/warvox/jobs/analysis.rb | 170 +++++++++++++++++++-------------
M lib/warvox/jobs/dialer.rb | 85 ++++++++++++++++---------------
M web/db/migrate/20090228195925_crea… | 8 ++++----
M web/db/migrate/20090228200035_crea… | 4 ++--
M web/db/migrate/20090228200141_crea… | 5 +++--
M web/db/migrate/20090303204859_add_… | 2 +-
M web/db/migrate/20090303204917_add_… | 2 +-
M web/db/migrate/20090304013815_add_… | 3 ++-
M web/db/migrate/20090304013839_add_… | 2 +-
M web/db/migrate/20090304013909_add_… | 3 ++-
M web/db/migrate/20090304014018_add_… | 2 +-
M web/db/migrate/20090304014033_add_… | 2 +-
M web/db/migrate/20090522202032_add_… | 2 +-
M web/db/migrate/20090526031826_add_… | 4 ++--
A web/db/migrate/20110801000001_add_… | 10 ++++++++++
A web/db/migrate/20110801000002_add_… | 10 ++++++++++
A web/db/migrate/20110801000003_add_… | 20 ++++++++++++++++++++
M web/db/schema.rb | 57 +++++++++++++++++++++-----------
21 files changed, 310 insertions(+), 204 deletions(-)
---
(DIR) diff --git a/etc/sigs/01.default.rb b/etc/sigs/01.default.rb
@@ -23,6 +23,7 @@ maxf = data[:maxf]
#
scnt = 0
ecnt = 0
+=begin
freq.each do |fsec|
scnt += 1
if(fsec.length == 0)
@@ -34,6 +35,7 @@ freq.each do |fsec|
savg = sump / fsec.length
ecnt += 1 if (savg < 100)
end
+=end
# Store these into data for use later on
data[:scnt] = scnt
@@ -44,7 +46,7 @@ data[:ecnt] = ecnt
#
if( (fcnt[2100] > 1.0 or fcnt[2230] > 1.0) and fcnt[2250] > 0.5)
@line_type = 'modem'
- raise Completed
+ raise Completed
end
#
@@ -52,7 +54,7 @@ end
#
if(fcnt[2100] > 1.0 and (maxf > 2245.0 and maxf < 2255.0))
@line_type = 'modem'
- raise Completed
+ raise Completed
end
#
@@ -60,15 +62,15 @@ end
#
if(fcnt[2100] > 1.0 and (maxf > 2995.0 and maxf < 3005.0))
@line_type = 'modem'
- raise Completed
+ raise Completed
end
#
# Look for faxes by checking for a handful of tones (min two)
#
fax_sum = 0
-[
- fcnt[1625], fcnt[1660], fcnt[1825], fcnt[2100],
+[
+ fcnt[1625], fcnt[1660], fcnt[1825], fcnt[2100],
fcnt[600], fcnt[1855], fcnt[1100], fcnt[2250],
fcnt[2230], fcnt[2220], fcnt[1800], fcnt[2095],
fcnt[2105]
@@ -92,3 +94,4 @@ end
# 99 and greater than 01.
#
#
+
(DIR) diff --git a/etc/sigs/99.default.rb b/etc/sigs/99.default.rb
@@ -19,7 +19,7 @@ scnt = data[:scnt]
# is often a different frequency entirely.
if(fcnt[1000] >= 1.0)
@line_type = 'voicemail'
- raise Completed
+ raise Completed
end
# Look for voicemail by detecting a peak frequency of
@@ -30,6 +30,8 @@ if(maxf > 995 and maxf < 1005)
raise Completed
end
+=begin
+
#
# Look for silence by checking the frequency signature
#
@@ -38,14 +40,17 @@ if(freq.map{|f| f.length}.inject(:+) == 0)
raise Completed
end
+
if(ecnt == scnt)
@line_type = 'silence'
raise Completed
end
+=end
#
# Fall back to 'voice' if nothing else has been matched
-# This should be the last signature file processed
+# This should be the last signature file processed
#
@line_type = 'voice'
+
(DIR) diff --git a/lib/warvox/audio/raw.rb b/lib/warvox/audio/raw.rb
@@ -1,14 +1,14 @@
module WarVOX
module Audio
class Raw
-
+
@@kissfft_loaded = false
begin
require 'kissfft'
@@kissfft_loaded = true
rescue ::LoadError
end
-
+
require 'zlib'
##
@@ -17,50 +17,50 @@ class Raw
##
# Static methods
- ##
-
+ ##
+
def self.from_str(str)
self.class.new(str)
end
-
+
def self.from_file(path)
if(not path)
raise Error, "No audio path specified"
end
-
+
if(path == "-")
return self.new($stdin.read)
end
-
+
if(not File.readable?(path))
raise Error, "The specified audio file does not exist"
end
-
+
if(path =~ /\.gz$/)
return self.new(Zlib::GzipReader.open(path).read)
end
-
+
self.new(File.read(path, File.size(path)))
end
##
# Class methods
- ##
-
+ ##
+
attr_accessor :samples
-
+
def initialize(data)
- self.samples = data.unpack('v*').map do |s|
+ self.samples = data.unpack('v*').map do |s|
(s > 0x7fff) ? (0x10000 - s) * -1 : s
end
end
-
+
def to_flow(opts={})
lo_lim = (opts[:lo_lim] || 100).to_i
lo_min = (opts[:lo_min] || 5).to_i
hi_min = (opts[:hi_min] || 5).to_i
- lo_cnt = 0
+ lo_cnt = 0
hi_cnt = 0
data = self.samples.map {|c| c.abs}
@@ -90,7 +90,7 @@ class Raw
while(idx < data.length and data[idx] > lo_lim)
buff << data[idx]
idx += 1
- end
+ end
# Ignore any sequence that is too small
fprint << [:hi, buff.length, buff] if buff.length > hi_min
@@ -123,7 +123,7 @@ class Raw
#
# Process results
- #
+ #
sig = ""
final.each do |f|
@@ -132,7 +132,7 @@ class Raw
avg = (sum == 0) ? 0 : sum / f[2].length
sig << "#{f[0].to_s.upcase[0,1]},#{f[1]},#{avg} "
end
-
+
# Return the results
return sig
end
@@ -141,16 +141,16 @@ class Raw
if(not @@kissfft_loaded)
raise RuntimeError, "The KissFFT module is not availabale, raw.to_freq() failed"
- end
-
+ end
+
freq_cnt = opts[:frequency_count] || 20
-
+
# Perform a DFT on the samples
ffts = KissFFT.fftr(8192, 8000, 1, self.samples)
self.class.fft_to_freq_sig(ffts, freq_cnt)
end
-
+
def to_freq_sig(opts={})
fcnt = opts[:frequency_count] || 5
@@ -173,10 +173,10 @@ class Raw
end
# Map each slice of the audio's FFT with each FFT chunk (8k samples) and then work on it
- tops = ffts.map{|x| x.map{|y| y.map{|z|
+ tops = ffts.map{|x| x.map{|y| y.map{|z|
frq,pwr = z
-
+
# Toss any signals with a strength under 100
if pwr < 100.0
frq,pwr = [0,0]
@@ -184,19 +184,19 @@ class Raw
else
frq = barker.call(frq)
end
-
+
# Make sure the strength is an integer
pwr = pwr.to_i
# Sort by signal strength and take the top fcnt items
- [frq, pwr]}.sort{|a,b|
+ [frq, pwr]}.sort{|a,b|
b[1] <=> a[1]
- }[0, fcnt].map{|w|
+ }[0, fcnt].map{|w|
# Grab just the frequency (drop the strength)
w[0]
# Remove any duplicates due to hz mapping
}.uniq
-
+
} }
# Track the generated 4-second chunk signatures
@@ -210,17 +210,17 @@ class Raw
# Dump any duplicate signatures
sigs = sigs.uniq
-
+
# Convert each signature into a single 32-bit integer
# This is essentially [0-40, 0-40, 0-40, 0-40]
sigs.map{|x| x.map{|y| y / 100}.pack("C4").unpack("N")[0] }
end
-
+
+ # Converts a signature to a postgresql integer array (text) format
def to_freq_sig_txt(opts={})
- # Convert this to a text file
- to_freq_sig(opts).sort.join("\n")
+ "{" + to_freq_sig(opts).sort.join(",") + "}"
end
-
+
def self.fft_to_freq_sig(ffts, freq_cnt)
sig = []
ffts.each do |s|
@@ -231,34 +231,34 @@ class Raw
if( f[1] > maxp )
maxf,maxp = f
end
-
+
if(maxf > 0 and f[1] < maxp and (maxf + 4.5 < f[0]))
res << [maxf, maxp]
maxf,maxp = [0,0]
end
end
-
- sig << res.sort{ |a,b| # sort by signal strength
- a[1] <=> b[1]
+
+ sig << res.sort{ |a,b| # sort by signal strength
+ a[1] <=> b[1]
}.reverse[0,freq_cnt].sort { |a,b| # take the top 20 and sort by frequency
- a[0] <=> b[0]
- }.map {|a| [a[0].round, a[1].round ] } # round to whole numbers
+ a[0] <=> b[0]
+ }.map {|a| [a[0].round, a[1].round ] } # round to whole numbers
end
-
- sig
+
+ sig
end
-
+
# Find pattern inside of sample
- def self.compare_freq_sig(pat, zam, opts)
-
+ def self.compare_freq_sig(pat, zam, opts)
+
fuzz_f = opts[:fuzz_f] || 7
fuzz_p = opts[:fuzz_p] || 10
final = []
-
+
0.upto(zam.length - 1) do |si|
- res = []
+ res = []
sam = zam[si, zam.length]
-
+
0.upto(pat.length - 1) do |pi|
diff = []
next if not pat[pi]
@@ -295,14 +295,15 @@ class Raw
end
prev = len
end
-
+
final << [ (rsum / res.length.to_f), res.map {|x| x.length}]
end
-
+
final
end
-
+
end
end
end
+
(DIR) diff --git a/lib/warvox/jobs/analysis.rb b/lib/warvox/jobs/analysis.rb
@@ -1,33 +1,33 @@
module WarVOX
module Jobs
-class Analysis < Base
+class Analysis < Base
require 'fileutils'
require 'tempfile'
require 'yaml'
require 'open3'
-
+
@@kissfft_loaded = false
begin
require 'kissfft'
@@kissfft_loaded = true
rescue ::LoadError
end
-
+
class SignalProcessor
-
+
class Completed < RuntimeError
end
-
+
attr_accessor :line_type
attr_accessor :signatures
attr_accessor :data
-
+
def initialize
@signatures = []
@data = {}
end
-
+
def proc(str)
begin
eval(str)
@@ -35,80 +35,89 @@ class Analysis < Base
end
end
end
-
+
def type
'analysis'
end
-
+
def initialize(job_id)
@name = job_id
if(not @@kissfft_loaded)
- raise RuntimeError, "The KissFFT module is not availabale, analysis failed"
+ raise RuntimeError, "The KissFFT module is not available, analysis failed"
end
end
-
+
def get_job
::DialJob.find(@name)
end
-
+
def start
@status = 'active'
-
+
begin
start_processing()
-
+
model = get_job
model.processed = true
db_save(model)
-
+
stop()
-
+
rescue ::Exception => e
$stderr.puts "Exception in the job queue: #{e.class} #{e} #{e.backtrace}"
end
end
-
+
def stop
@status = 'completed'
end
-
+
def start_processing
todo = ::DialResult.find_all_by_dial_job_id(@name)
jobs = []
todo.each do |r|
next if r.processed
next if not r.completed
- next if r.busy
+ next if r.busy
jobs << r
end
-
+
max_threads = WarVOX::Config.analysis_threads
-
+
while(not jobs.empty?)
threads = []
output = []
- 1.upto(max_threads) do
- j = jobs.shift || break
+ 1.upto(max_threads) do
+ j = jobs.shift || break
output << j
threads << Thread.new { run_analyze_call(j) }
end
# Wait for the threads to complete
threads.each {|t| t.join}
-
+
# Save the results to the database
output.each {|r| db_save(r) if r.processed }
end
end
-
+
def run_analyze_call(r)
$stderr.puts "DEBUG: Processing audio for #{r.number}..."
-
+
+
+
bin = File.join(WarVOX::Base, 'bin', 'analyze_result.rb')
- pfd = IO.popen("#{bin} '#{r.rawfile}'")
+ tmp = Tempfile.new("Analysis")
+ begin
+
+ ::File.open(tmp, "wb") do |fd|
+ fd.write(r.audio)
+ end
+
+ pfd = IO.popen("#{bin} '#{tmp.path}'")
out = YAML.load(pfd.read)
pfd.close
-
+
return if not out
out.each_key do |k|
@@ -117,35 +126,39 @@ class Analysis < Base
r.send(setter, out[k])
end
end
-
+
r.processed_at = Time.now
- r.processed = true
+ r.processed = true
+
+ rescue ::Interrupt
+ ensure
+ tmp.close
+ tmp.unlink
+ end
+
true
end
-
+
# Takes the raw file path as an argument, returns a hash
def analyze_call(input)
return if not input
return if not File.exist?(input)
- bname = input.gsub(/\..*/, '')
- num = File.basename(bname)
+ bname = File.expand_path(File.dirname(input))
+ num = File.basename(input)
res = {}
#
# Create the signature database
- #
+ #
raw = WarVOX::Audio::Raw.from_file(input)
- fft = KissFFT.fftr(8192, 8000, 1, raw.samples)
-
+ fft = KissFFT.fftr(8192, 8000, 1, raw.samples)
+
freq = raw.to_freq_sig_txt()
- fd = File.new("#{bname}.sig", "wb")
- fd.write freq
- fd.close
# Save the signature data
- res[:sig_data] = freq
+ res[:fprint] = freq
#
# Create a raw decompressed file
@@ -153,7 +166,7 @@ class Analysis < Base
# Decompress the audio file
rawfile = Tempfile.new("rawfile")
- datfile = Tempfile.new("datfile")
+ datfile = Tempfile.new("datfile")
# Data files for audio processing and signal graph
cnt = 0
@@ -220,11 +233,11 @@ class Analysis < Base
fcnt[fdx] += 0.1
end
end
-
+
#
# Signature processing
#
-
+
sproc = SignalProcessor.new
sproc.data =
{
@@ -253,39 +266,45 @@ class Analysis < Base
# Save any matched signatures
res[:signatures] = sproc.signatures.map{|s| "#{s[0]}:#{s[1]}:#{s[2]}" }.join("\n")
-
+
+ png_big = Tempfile.new("big")
+ png_big_dots = Tempfile.new("bigdots")
+ png_big_freq = Tempfile.new("bigfreq")
+ png_sig = Tempfile.new("signal")
+ png_sig_freq = Tempfile.new("sigfreq")
+
# Plot samples to a graph
plotter = Tempfile.new("gnuplot")
plotter.puts("set ylabel \"Signal\"")
plotter.puts("set xlabel \"Seconds\"")
plotter.puts("set terminal png medium size 640,480 transparent")
- plotter.puts("set output \"#{bname}_big.png\"")
+ plotter.puts("set output \"#{png_big.path}\"")
plotter.puts("plot \"#{datfile.path}\" using 1:2 title \"#{num}\" with lines")
- plotter.puts("set output \"#{bname}_big_dots.png\"")
+ plotter.puts("set output \"#{png_big_dots.path}\"")
plotter.puts("plot \"#{datfile.path}\" using 1:2 title \"#{num}\" with dots")
plotter.puts("set terminal png medium size 640,480 transparent")
plotter.puts("set ylabel \"Power\"")
plotter.puts("set xlabel \"Frequency\"")
- plotter.puts("set output \"#{bname}_freq_big.png\"")
+ plotter.puts("set output \"#{png_big_freq.path}\"")
plotter.puts("plot \"#{frefile.path}\" using 1:2 title \"#{num} - Peak #{maxf.round}hz\" with lines")
plotter.puts("set ylabel \"Signal\"")
plotter.puts("set xlabel \"Seconds\"")
plotter.puts("set terminal png small size 160,120 transparent")
plotter.puts("set format x ''")
- plotter.puts("set format y ''")
- plotter.puts("set output \"#{bname}.png\"")
+ plotter.puts("set format y ''")
+ plotter.puts("set output \"#{png_sig.path}\"")
plotter.puts("plot \"#{datfile.path}\" using 1:2 notitle with lines")
plotter.puts("set ylabel \"Power\"")
- plotter.puts("set xlabel \"Frequency\"")
+ plotter.puts("set xlabel \"Frequency\"")
plotter.puts("set terminal png small size 160,120 transparent")
plotter.puts("set format x ''")
- plotter.puts("set format y ''")
- plotter.puts("set output \"#{bname}_freq.png\"")
- plotter.puts("plot \"#{frefile.path}\" using 1:2 notitle with lines")
+ plotter.puts("set format y ''")
+ plotter.puts("set output \"#{png_sig_freq.path}\"")
+ plotter.puts("plot \"#{frefile.path}\" using 1:2 notitle with lines")
plotter.flush
system("#{WarVOX::Config.tool_path('gnuplot')} #{plotter.path}")
@@ -296,6 +315,14 @@ class Analysis < Base
datfile.close
frefile.path
+ ::File.open(png_big.path, 'rb') { |fd| res[:png_big] = fd.read }
+ ::File.open(png_big_dots.path, 'rb') { |fd| res[:png_big_dots] = fd.read }
+ ::File.open(png_big_freq.path, 'rb') { |fd| res[:png_big_freq] = fd.read }
+ ::File.open(png_sig.path, 'rb') { |fd| res[:png_sig] = fd.read }
+ ::File.open(png_sig_freq.path, 'rb') { |fd| res[:png_sig_freq] = fd.read }
+
+ [png_big, png_big_dots, png_big_freq, png_sig, png_sig_freq ].map {|x| x.unlink; x.close }
+
# Detect DTMF and MF tones
dtmf = ''
@@ -310,23 +337,29 @@ class Analysis < Base
if(line.strip =~ /^- DTMF numbers:\s+(.*)/)
next if $1 == 'none'
dtmf = $1
- end
+ end
end
pfd.close
res[:dtmf] = dtmf
res[:mf] = mf
+ tmp_wav = Tempfile.new("wav")
+ tmp_mp3 = Tempfile.new("mp3")
+
# Generate a MP3 audio file
- system("#{WarVOX::Config.tool_path('sox')} -s -2 -r 8000 -t raw -c 1 #{rawfile.path} #{bname}.wav")
-
+ system("#{WarVOX::Config.tool_path('sox')} -s -2 -r 8000 -t raw -c 1 #{rawfile.path} -t wav #{tmp_wav.path}")
+
# Default samples at 8k, bump it to 32k to get better quality
- system("#{WarVOX::Config.tool_path('lame')} -b 32 #{bname}.wav #{bname}.mp3 >/dev/null 2>&1")
-
- File.unlink("#{bname}.wav")
+ system("#{WarVOX::Config.tool_path('lame')} -b 32 #{tmp_wav.path} #{tmp_mp3.path} >/dev/null 2>&1")
+
File.unlink(rawfile.path)
rawfile.close
+ ::File.open(tmp_wav.path, "rb") { |fd| res[:mp3] = fd.read }
+
+ [tmp_wav, tmp_mp3].map {|x| x.unlink; x.close }
+
clear_zombies()
res
@@ -335,44 +368,44 @@ end
class CallAnalysis < Analysis
-
+
@@kissfft_loaded = false
begin
require 'kissfft'
@@kissfft_loaded = true
rescue ::LoadError
end
-
+
def type
'call_analysis'
end
-
+
def initialize(result_id)
@name = result_id
if(not @@kissfft_loaded)
raise RuntimeError, "The KissFFT module is not available, analysis failed"
end
end
-
+
def get_job
::DialResult.find(@name)
end
-
+
def start
@status = 'active'
-
+
begin
start_processing()
- stop()
+ stop()
rescue ::Exception => e
$stderr.puts "Exception in the job queue: #{e.class} #{e} #{e.backtrace}"
end
end
-
+
def stop
@status = 'completed'
end
-
+
def start_processing
r = get_job()
return if not r.completed
@@ -383,3 +416,4 @@ end
end
end
+
(DIR) diff --git a/lib/warvox/jobs/dialer.rb b/lib/warvox/jobs/dialer.rb
@@ -1,25 +1,25 @@
module WarVOX
module Jobs
-class Dialer < Base
+class Dialer < Base
require 'fileutils'
-
+
def type
'dialer'
end
-
+
def initialize(job_id)
@name = job_id
- model = get_job
- @range = model.range
- @seconds = model.seconds
- @lines = model.lines
+ @job = get_job
+ @range = @job.range
+ @seconds = @job.seconds
+ @lines = @job.lines
@nums = shuffle_a(WarVOX::Phone.crack_mask(@range))
-
+
# CallerID modes (SELF or a mask)
- @cid_self = model.cid_mask == 'SELF'
+ @cid_self = @job.cid_mask == 'SELF'
if(not @cid_self)
- @cid_range = WarVOX::Phone.crack_mask(model.cid_mask)
+ @cid_range = WarVOX::Phone.crack_mask(@job.cid_mask)
end
end
@@ -56,31 +56,31 @@ class Dialer < Base
}
1.upto(prov.lines) {|i| res.push(info) }
end
-
+
shuffle_a(res)
end
-
+
def get_job
::DialJob.find(@name)
end
-
+
def start
begin
-
+
model = get_job
model.status = 'active'
model.started_at = Time.now
db_save(model)
-
+
start_dialing()
-
+
stop()
-
+
rescue ::Exception => e
$stderr.puts "Exception in the job queue: #{$e.class} #{e} #{e.backtrace}"
end
end
-
+
def stop
@status = 'completed'
model = get_job
@@ -88,11 +88,11 @@ class Dialer < Base
model.completed_at = Time.now
db_save(model)
end
-
+
def start_dialing
- dest = File.join(WarVOX::Config.data_path, "#{@name}")
+ dest = File.join(WarVOX::Config.data_path, @name.to_s)
FileUtils.mkdir_p(dest)
-
+
# Scrub all numbers matching the blacklist
list = WarVOX::Config.blacklist_load
list.each do |b|
@@ -104,26 +104,26 @@ class Dialer < Base
end
end
end
-
+
@nums_total = @nums.length
while(@nums.length > 0)
@calls = []
@provs = get_providers
tasks = []
max_tasks = [@provs.length, @lines].min
-
+
1.upto(max_tasks) do
tasks << Thread.new do
-
+
Thread.current.kill if @nums.length == 0
Thread.current.kill if @provs.length == 0
-
+
num = @nums.shift
prov = @provs.shift
-
+
Thread.current.kill if not num
Thread.current.kill if not prov
-
+
out = File.join(dest, num+".raw")
begin
@@ -134,7 +134,7 @@ class Dialer < Base
byte = 0
path = ''
cid = @cid_self ? num : @cid_range[ rand(@cid_range.length) ]
-
+
IO.popen(
[
WarVOX::Config.tool_path('iaxrecord'),
@@ -152,8 +152,8 @@ class Dialer < Base
num,
"-l",
@seconds
- ].map{|i|
- "'" + i.to_s.gsub("'",'') +"'"
+ ].map{|i|
+ "'" + i.to_s.gsub("'",'') +"'"
}.join(" ")).each_line do |line|
$stderr.puts "DEBUG: #{line.strip}"
if(line =~ /^COMPLETED/)
@@ -161,12 +161,12 @@ class Dialer < Base
busy = info[1].to_i if info[0] == 'BUSY'
fail = info[1].to_i if info[0] == 'FAIL'
ring = info[1].to_i if info[0] == 'RINGTIME'
- byte = info[1].to_i if info[0] == 'BYTES'
+ byte = info[1].to_i if info[0] == 'BYTES'
path = info[1] if info[0] == 'FILE'
end
end
end
-
+
res = ::DialResult.new
res.number = num
res.cid = cid
@@ -177,21 +177,21 @@ class Dialer < Base
res.seconds = (byte / 16000) # 8khz @ 16-bit
res.ringtime = ring
res.processed = false
- res.created_at = Time.now
- res.updated_at = Time.now
-
+
if(File.exists?(out))
- system("gzip -9 #{out}")
- res.rawfile = out + ".gz"
+ File.open(out, "rb") do |fd|
+ res.audio = fd.read(fd.stat.size)
+ end
+ File.unlink(out)
end
-
+
@calls << res
-
+
rescue ::Exception => e
$stderr.puts "ERROR: #{e.class} #{e} #{e.backtrace} #{num} #{prov.inspect}"
end
end
-
+
# END NEW THREAD
end
# END SPAWN THREADS
@@ -206,13 +206,14 @@ class Dialer < Base
model = get_job
model.progress = ((@nums_total - @nums.length) / @nums_total.to_f) * 100
db_save(model)
-
+
clear_zombies()
end
-
+
# ALL DONE
end
end
end
end
+
(DIR) diff --git a/web/db/migrate/20090228195925_create_providers.rb b/web/db/migrate/20090228195925_create_providers.rb
@@ -1,11 +1,11 @@
class CreateProviders < ActiveRecord::Migration
def self.up
create_table :providers do |t|
- t.string :name
- t.string :host
+ t.text :name
+ t.text :host
t.integer :port
- t.string :user
- t.string :pass
+ t.text :user
+ t.text :pass
t.integer :lines
t.timestamps
(DIR) diff --git a/web/db/migrate/20090228200035_create_dial_jobs.rb b/web/db/migrate/20090228200035_create_dial_jobs.rb
@@ -1,10 +1,10 @@
class CreateDialJobs < ActiveRecord::Migration
def self.up
create_table :dial_jobs do |t|
- t.string :range
+ t.text :range
t.integer :seconds
t.integer :lines
- t.string :status
+ t.text :status
t.integer :progress
t.datetime :started_at
t.datetime :completed_at
(DIR) diff --git a/web/db/migrate/20090228200141_create_dial_results.rb b/web/db/migrate/20090228200141_create_dial_results.rb
@@ -1,14 +1,14 @@
class CreateDialResults < ActiveRecord::Migration
def self.up
create_table :dial_results do |t|
- t.integer :number
+ t.text :number
t.integer :dial_job_id
t.integer :provider_id
t.boolean :completed
t.boolean :busy
t.integer :seconds
t.integer :ringtime
- t.string :rawfile
+ t.text :rawfile
t.boolean :processed
t.timestamps
@@ -19,3 +19,4 @@ class CreateDialResults < ActiveRecord::Migration
drop_table :dial_results
end
end
+
(DIR) diff --git a/web/db/migrate/20090303204859_add_cid_mask_to_dial_jobs.rb b/web/db/migrate/20090303204859_add_cid_mask_to_dial_jobs.rb
@@ -1,6 +1,6 @@
class AddCidMaskToDialJobs < ActiveRecord::Migration
def self.up
- add_column :dial_jobs, :cid_mask, :string
+ add_column :dial_jobs, :cid_mask, :text
end
def self.down
(DIR) diff --git a/web/db/migrate/20090303204917_add_cid_to_dial_results.rb b/web/db/migrate/20090303204917_add_cid_to_dial_results.rb
@@ -1,6 +1,6 @@
class AddCidToDialResults < ActiveRecord::Migration
def self.up
- add_column :dial_results, :cid, :string
+ add_column :dial_results, :cid, :text
end
def self.down
(DIR) diff --git a/web/db/migrate/20090304013815_add_peak_freq_to_dial_results.rb b/web/db/migrate/20090304013815_add_peak_freq_to_dial_results.rb
@@ -1,9 +1,10 @@
class AddPeakFreqToDialResults < ActiveRecord::Migration
def self.up
- add_column :dial_results, :peak_freq, :number
+ add_column :dial_results, :peak_freq, :float
end
def self.down
remove_column :dial_results, :peak_freq
end
end
+
(DIR) diff --git a/web/db/migrate/20090304013839_add_peak_freq_data_to_dial_results.rb b/web/db/migrate/20090304013839_add_peak_freq_data_to_dial_results.rb
@@ -1,6 +1,6 @@
class AddPeakFreqDataToDialResults < ActiveRecord::Migration
def self.up
- add_column :dial_results, :peak_freq_data, :string
+ add_column :dial_results, :peak_freq_data, :text
end
def self.down
(DIR) diff --git a/web/db/migrate/20090304013909_add_sig_data_to_dial_results.rb b/web/db/migrate/20090304013909_add_sig_data_to_dial_results.rb
@@ -1,9 +1,10 @@
class AddSigDataToDialResults < ActiveRecord::Migration
def self.up
- add_column :dial_results, :sig_data, :string
+ add_column :dial_results, :sig_data, :text
end
def self.down
remove_column :dial_results, :sig_data
end
end
+
(DIR) diff --git a/web/db/migrate/20090304014018_add_line_type_to_dial_results.rb b/web/db/migrate/20090304014018_add_line_type_to_dial_results.rb
@@ -1,6 +1,6 @@
class AddLineTypeToDialResults < ActiveRecord::Migration
def self.up
- add_column :dial_results, :line_type, :string
+ add_column :dial_results, :line_type, :text
end
def self.down
(DIR) diff --git a/web/db/migrate/20090304014033_add_notes_to_dial_results.rb b/web/db/migrate/20090304014033_add_notes_to_dial_results.rb
@@ -1,6 +1,6 @@
class AddNotesToDialResults < ActiveRecord::Migration
def self.up
- add_column :dial_results, :notes, :string
+ add_column :dial_results, :notes, :text
end
def self.down
(DIR) diff --git a/web/db/migrate/20090522202032_add_signatures_to_dial_results.rb b/web/db/migrate/20090522202032_add_signatures_to_dial_results.rb
@@ -1,6 +1,6 @@
class AddSignaturesToDialResults < ActiveRecord::Migration
def self.up
- add_column :dial_results, :signatures, :string
+ add_column :dial_results, :signatures, :text
end
def self.down
(DIR) diff --git a/web/db/migrate/20090526031826_add_mf_and_dtmf_to_dial_results.rb b/web/db/migrate/20090526031826_add_mf_and_dtmf_to_dial_results.rb
@@ -1,7 +1,7 @@
class AddMfAndDtmfToDialResults < ActiveRecord::Migration
def self.up
- add_column :dial_results, :dtmf, :string
- add_column :dial_results, :mf, :string
+ add_column :dial_results, :dtmf, :text
+ add_column :dial_results, :mf, :text
end
def self.down
(DIR) diff --git a/web/db/migrate/20110801000001_add_fprint_to_dial_result.rb b/web/db/migrate/20110801000001_add_fprint_to_dial_result.rb
@@ -0,0 +1,10 @@
+class AddFprintToDialResult < ActiveRecord::Migration
+ def self.up
+ add_column :dial_results, :fprint, 'int[]'
+ end
+
+ def self.down
+ remove_column :dial_results, :fprint
+ end
+end
+
(DIR) diff --git a/web/db/migrate/20110801000002_add_audio_to_dial_result.rb b/web/db/migrate/20110801000002_add_audio_to_dial_result.rb
@@ -0,0 +1,10 @@
+class AddAudioToDialResult < ActiveRecord::Migration
+ def self.up
+ add_column :dial_results, :audio, :binary
+ end
+
+ def self.down
+ remove_column :dial_results, :audio
+ end
+end
+
(DIR) diff --git a/web/db/migrate/20110801000003_add_media_to_dial_result.rb b/web/db/migrate/20110801000003_add_media_to_dial_result.rb
@@ -0,0 +1,20 @@
+class AddMediaToDialResult < ActiveRecord::Migration
+ def self.up
+ add_column :dial_results, :mp3, :binary
+ add_column :dial_results, :png_big, :binary
+ add_column :dial_results, :png_big_dots, :binary
+ add_column :dial_results, :png_big_freq, :binary
+ add_column :dial_results, :png_sig, :binary
+ add_column :dial_results, :png_sig_freq, :binary
+ end
+
+ def self.down
+ remove_column :dial_results, :mp3
+ remove_column :dial_results, :png_big
+ remove_column :dial_results, :png_big_dots
+ remove_column :dial_results, :png_big_freq
+ remove_column :dial_results, :png_sig
+ remove_column :dial_results, :png_sig_freq
+ end
+end
+
(DIR) diff --git a/web/db/schema.rb b/web/db/schema.rb
@@ -10,56 +10,75 @@
#
# It's strongly recommended to check this file into your version control system.
-ActiveRecord::Schema.define(:version => 20090526031826) do
+ActiveRecord::Schema.define(:version => 20110801000003) do
create_table "dial_jobs", :force => true do |t|
- t.string "range"
+ t.text "range"
t.integer "seconds"
t.integer "lines"
- t.string "status"
+ t.text "status"
t.integer "progress"
t.datetime "started_at"
t.datetime "completed_at"
t.boolean "processed"
t.datetime "created_at"
t.datetime "updated_at"
- t.string "cid_mask"
+ t.text "cid_mask"
end
create_table "dial_results", :force => true do |t|
- t.integer "number"
+ t.text "number"
t.integer "dial_job_id"
t.integer "provider_id"
t.boolean "completed"
t.boolean "busy"
t.integer "seconds"
t.integer "ringtime"
- t.string "rawfile"
+ t.text "rawfile"
t.boolean "processed"
t.datetime "created_at"
t.datetime "updated_at"
t.datetime "processed_at"
- t.string "cid"
- t.decimal "peak_freq"
- t.string "peak_freq_data"
- t.string "sig_data"
- t.string "line_type"
- t.string "notes"
- t.string "signatures"
- t.string "dtmf"
- t.string "mf"
+ t.text "cid"
+ t.float "peak_freq"
+ t.text "peak_freq_data"
+ t.text "sig_data"
+ t.text "line_type"
+ t.text "notes"
+ t.text "signatures"
+ t.text "dtmf"
+ t.text "mf"
+ t.string "fprint", :limit => nil
+ t.binary "audio"
+ t.binary "mp3"
+ t.binary "png_big"
+ t.binary "png_big_dots"
+ t.binary "png_big_freq"
+ t.binary "png_sig"
+ t.binary "png_sig_freq"
end
create_table "providers", :force => true do |t|
- t.string "name"
- t.string "host"
+ t.text "name"
+ t.text "host"
t.integer "port"
- t.string "user"
- t.string "pass"
+ t.text "user"
+ t.text "pass"
t.integer "lines"
t.datetime "created_at"
t.datetime "updated_at"
t.boolean "enabled"
end
+ create_table "signatures", :force => true do |t|
+ t.datetime "created_at"
+ t.datetime "updated_at"
+ t.string "name"
+ t.string "category"
+ t.text "description"
+ t.string "mode"
+ t.string "print", :limit => nil
+ t.text "rules"
+ end
+
end