Sync recent changes - warvox - VoIP based wardialing tool, forked from rapid7/warvox.
(DIR) Log
(DIR) Files
(DIR) Refs
(DIR) README
---
(DIR) commit ef6496ad1da956df421e15ce6c2eadc06044f3d7
(DIR) parent aa07abc9e7aaabc1723625d72daac6dd9e1edfcd
(HTM) Author: HD Moore <hd_moore@rapid7.com>
Date: Tue, 1 Jan 2013 21:07:16 -0600
Sync recent changes
Diffstat:
M app/assets/stylesheets/application… | 1 +
M app/assets/stylesheets/bootstrap_a… | 32 +++++++++++++++++++++----------
M app/controllers/analyze_controller… | 34 ++++++++++++++++----------------
M app/controllers/application_contro… | 9 ++++++---
D app/controllers/dial_jobs_controll… | 107 -------------------------------
D app/controllers/dial_results_contr… | 179 -------------------------------
M app/controllers/home_controller.rb | 8 ++++----
M app/controllers/projects_controlle… | 13 ++++++-------
M app/controllers/providers_controll… | 41 ++++++++++---------------------
M app/helpers/application_helper.rb | 29 +++++++++++++++++++++++++++++
D app/helpers/dial_jobs_helper.rb | 2 --
D app/helpers/dial_results_helper.rb | 2 --
M app/models/call.rb | 2 +-
M app/models/call_medium.rb | 1 +
D app/models/dial_job.rb | 49 -------------------------------
M app/models/job.rb | 74 ++++++++++++++++++++++++++++++-
M app/models/line.rb | 15 ++++++++++++++-
M app/models/line_attribute.rb | 1 +
M app/models/project.rb | 12 +++++++++---
M app/views/analyze/index.html.erb | 25 ++++++++++++-------------
M app/views/analyze/view.html.erb | 28 ++++++++++++++--------------
M app/views/analyze/view_matches.htm… | 56 ++++++++++++++++----------------
D app/views/dial_jobs/edit.html.erb | 24 ------------------------
D app/views/dial_jobs/index.html.erb | 81 ------------------------------
D app/views/dial_jobs/new.html.erb | 35 -------------------------------
D app/views/dial_jobs/run.html.erb | 5 -----
D app/views/dial_jobs/show.html.erb | 39 -------------------------------
D app/views/dial_results/analyze.htm… | 27 ---------------------------
D app/views/dial_results/edit.html.e… | 48 -------------------------------
D app/views/dial_results/index.html.… | 57 -------------------------------
D app/views/dial_results/new.html.erb | 43 ------------------------------
D app/views/dial_results/show.html.e… | 48 -------------------------------
D app/views/dial_results/view.html.e… | 58 ------------------------------
M app/views/home/about.html.erb | 8 ++++----
M app/views/home/check.html.erb | 8 ++++----
M app/views/home/index.html.erb | 6 +++---
M app/views/layouts/application.html… | 33 ++++++++++++++++++-------------
M app/views/projects/edit.html.erb | 9 ++++-----
M app/views/projects/index.html.erb | 10 ++++++++--
M app/views/projects/new.html.erb | 10 +---------
M app/views/providers/edit.html.erb | 47 ++++++++-----------------------
M app/views/providers/index.html.erb | 32 +++++++++++++------------------
M app/views/providers/new.html.erb | 41 ++++++++-----------------------
D app/views/providers/show.html.erb | 38 -------------------------------
M app/views/user_sessions/new.html.e… | 2 +-
M bin/export_audio.rb | 80 ++++++++++++++++++++-----------
M bin/iaxrecord.rb | 37 ++++++++++++++++++-------------
M bin/import_audio.rb | 9 ++++-----
M bin/warvox.rb | 14 +++++++++++++-
M config/routes.rb | 48 ++++++++++++++++---------------
M db/migrate/20121228171549_initial_… | 3 ++-
M db/schema.rb | 6 ++++--
M lib/warvox.rb | 5 ++++-
M lib/warvox/config.rb | 8 ++++++++
M lib/warvox/jobs/dialer.rb | 8 ++++----
55 files changed, 466 insertions(+), 1181 deletions(-)
---
(DIR) diff --git a/app/assets/stylesheets/application.css.scss b/app/assets/stylesheets/application.css.scss
@@ -6,5 +6,6 @@
*= require_self
*= require formtastic
*= require formtastic-bootstrap
+ *= require formtastic-overrides
*= require dataTables/jquery.dataTables.bootstrap
*/
(DIR) diff --git a/app/assets/stylesheets/bootstrap_and_overrides.css.less b/app/assets/stylesheets/bootstrap_and_overrides.css.less
@@ -39,6 +39,28 @@ body {
@navbarBackgroundHighlight: #4A1C04;
+.progress_pct {
+ color: @darkGray;
+ margin-left: 10px;
+}
+
+.task_args_formatted {
+ width: 400px;
+ margin: 5px;
+}
+
+.task_args_var {
+ font-size: 14px;
+ float: left;
+ width: 100px;
+ overflow: hidden;
+ font-weight: bold;
+ text-align: right;
+}
+.task_args_val {
+ font-size: 14px;
+ text-align: left;
+}
.check-item {
font-size: 18px;
margin-bottom: 10px;
@@ -49,13 +71,6 @@ body {
font-size: 16px;
}
-.project-title {
- font-size: 18px;
- color: @white;
- margin-top: 10px;
- margin-right: 50px;
-
-}
// Hacks to override active drop-down item background color and hover
.dropdown-menu .active > a {
@@ -80,9 +95,6 @@ body {
width: 400px;
}
-.fbtn {
-
-}
.project_description {
height: 100px;
(DIR) diff --git a/app/controllers/analyze_controller.rb b/app/controllers/analyze_controller.rb
@@ -1,7 +1,7 @@
class AnalyzeController < ApplicationController
def index
- @jobs = DialJob.paginate(
+ @jobs = Job.paginate(
:page => params[:page],
:order => 'id DESC',
:per_page => 30
@@ -10,30 +10,30 @@ class AnalyzeController < ApplicationController
def view
@job_id = params[:id]
- @dial_job = DialJob.find(@job_id)
+ @job = Job.find(@job_id)
@shown = params[:show]
- ltypes = DialResult.find( :all, :select => 'DISTINCT line_type', :conditions => ["dial_job_id = ?", @job_id] ).map{|r| r.line_type}
+ ltypes = Call.find( :all, :select => 'DISTINCT line_type', :conditions => ["job_id = ?", @job_id] ).map{|r| r.line_type}
res_types = {}
ltypes.each do |k|
next if not k
- res_types[k.capitalize.to_sym] = DialResult.count(
- :conditions => ['dial_job_id = ? and line_type = ?', @job_id, k]
+ res_types[k.capitalize.to_sym] = Call.count(
+ :conditions => ['job_id = ? and line_type = ?', @job_id, k]
)
end
@lines_by_type = res_types
if(@shown and @shown != 'all')
- @results = DialResult.where(:dial_job_id => @job_id).paginate(
+ @results = Call.where(:job_id => @job_id).paginate(
:page => params[:page],
:order => 'number ASC',
:per_page => 10,
:conditions => [ 'completed = ? and processed = ? and busy = ? and line_type = ?', true, true, false, @shown ]
)
else
- @results = DialResult.where(:dial_job_id => @job_id).paginate(
+ @results = Call.where(:job_id => @job_id).paginate(
:page => params[:page],
:order => 'number ASC',
:per_page => 10,
@@ -51,30 +51,30 @@ class AnalyzeController < ApplicationController
def show
@job_id = params[:id]
- @dial_job = DialJob.find(@job_id)
+ @job = Job.find(@job_id)
@shown = params[:show]
- ltypes = DialResult.find( :all, :select => 'DISTINCT line_type', :conditions => ["dial_job_id = ?", @job_id] ).map{|r| r.line_type}
+ ltypes = Call.find( :all, :select => 'DISTINCT line_type', :conditions => ["job_id = ?", @job_id] ).map{|r| r.line_type}
res_types = {}
ltypes.each do |k|
next if not k
- res_types[k.capitalize.to_sym] = DialResult.count(
- :conditions => ['dial_job_id = ? and line_type = ?', @job_id, k]
+ res_types[k.capitalize.to_sym] = Call.count(
+ :conditions => ['job_id = ? and line_type = ?', @job_id, k]
)
end
@lines_by_type = res_types
if(@shown and @shown != 'all')
- @results = DialJob.where(:id => @job_id).paginate(
+ @results = Job.where(:id => @job_id).paginate(
:page => params[:page],
:order => 'number ASC',
:per_page => 20,
:conditions => [ 'completed = ? and processed = ? and busy = ? and line_type = ?', true, true, false, @shown ]
)
else
- @results = DialJob.where(:id => @job_id).paginate(
+ @results = Job.where(:id => @job_id).paginate(
:page => params[:page],
:order => 'number ASC',
:per_page => 20,
@@ -91,13 +91,13 @@ class AnalyzeController < ApplicationController
end
- # GET /dial_results/1/resource?id=XXX&type=YYY
+ # GET /calls/1/resource?id=XXX&type=YYY
def resource
ctype = 'text/html'
cpath = nil
cdata = "File not found"
- res = DialResultMedium.where(:dial_result_id => params[:result_id].to_i).first
+ res = CallMedium.where(:call_id => params[:result_id].to_i).first
if res
case params[:type]
@@ -133,8 +133,8 @@ class AnalyzeController < ApplicationController
def view_matches
- @result = DialResult.find(params[:dial_result_id])
- @job_id = @result.dial_job_id
+ @result = Call.find(params[:call_id])
+ @job_id = @result.job_id
@results = @result.matches.select{|x| x.matchscore.to_f > 10.0 }
end
end
(DIR) diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb
@@ -45,14 +45,17 @@ private
end
def load_project
+ # Only load this when we are logged in
+ return true unless current_user
+
if params[:project_id]
- @project = Project.find(params[:project_id])
+ @project = Project.where(:id => params[:project_id].to_i).first
elsif session[:project_id]
- @project = Project.find(session[:project_id])
+ @project = Project.where(:id => session[:project_id].to_i).first
end
if @project and @project.id and not (session[:project_id] and session[:project_id] == @project.id)
- session[:project_id] = @project
+ session[:project_id] = @project.id
end
true
(DIR) diff --git a/app/controllers/dial_jobs_controller.rb b/app/controllers/dial_jobs_controller.rb
@@ -1,107 +0,0 @@
-class DialJobsController < ApplicationController
-
- # GET /dial_jobs
- # GET /dial_jobs.xml
- def index
- @submitted_jobs = DialJob.find_all_by_status('submitted')
- @active_jobs = DialJob.find_all_by_status('active')
- @new_job = DialJob.new
- respond_to do |format|
- format.html # index.html.erb
- format.xml { render :xml => @active_jobs + @submitted_jobs }
- end
- end
-
- # GET /dial_jobs/new
- # GET /dial_jobs/new.xml
- def new
- @dial_job = DialJob.new
- respond_to do |format|
- format.html # new.html.erb
- format.xml { render :xml => @dial_job }
- end
- end
-
- # GET /dial_jobs/1/run
- def run
- @dial_job = DialJob.find(params[:id])
-
- if(@dial_job.status != 'submitted')
- flash[:notice] = 'Job is already running or completed'
- return
- end
-
- WarVOX::JobManager.schedule(::WarVOX::Jobs::Dialer, @dial_job.id)
- redirect_to :action => 'index'
- end
-
- def stop
- @dial_job = DialJob.find(params[:id])
-
- @dial_job.stop
-
- if(@dial_job.status != 'submitted')
- flash[:notice] = 'Job is already running or completed'
- return
- end
- format.html { redirect_to :action => 'index' }
- end
-
-
- # POST /dial_jobs
- # POST /dial_jobs.xml
- def create
-
- @dial_job = DialJob.new(params[:dial_job])
-
- if(Provider.find_all_by_enabled(true).length == 0)
- @dial_job.errors.add(:base, "No providers have been configured or enabled, this job cannot be run")
- respond_to do |format|
- format.html { render :action => "new" }
- format.xml { render :xml => @dial_job.errors, :status => :unprocessable_entity }
- end
- return
- end
-
- @dial_job.status = 'submitted'
- @dial_job.progress = 0
- @dial_job.started_at = nil
- @dial_job.completed_at = nil
- @dial_job.range.gsub!(/[^0-9X:,\n]/, '')
- @dial_job.cid_mask.gsub!(/[^0-9X]/, '') if @dial_job.cid_mask != "SELF"
-
- if(@dial_job.range_file.to_s != "")
- @dial_job.range = @dial_job.range_file.read.gsub!(/[^0-9X:,\n]/, '')
- end
-
- respond_to do |format|
- if @dial_job.save
- flash[:notice] = 'Job was successfully created.'
-
- res = @dial_job.schedule(:dialer)
- unless res
- flash[:error] = "Unable to launch dialer job"
- end
-
- format.html { redirect_to :action => 'index' }
- format.xml { render :xml => @dial_job, :status => :created, :location => @dial_job }
- else
- format.html { render :action => "new" }
- format.xml { render :xml => @dial_job.errors, :status => :unprocessable_entity }
- end
- end
- end
-
- # DELETE /dial_jobs/1
- # DELETE /dial_jobs/1.xml
- def destroy
- @dial_job = DialJob.find(params[:id])
- @dial_job.destroy
-
- respond_to do |format|
- format.html { redirect_to(dial_jobs_url) }
- format.xml { head :ok }
- end
- end
-
-end
(DIR) diff --git a/app/controllers/dial_results_controller.rb b/app/controllers/dial_results_controller.rb
@@ -1,179 +0,0 @@
-class DialResultsController < ApplicationController
-
- # GET /dial_results
- # GET /dial_results.xml
- def index
- @jobs = DialJob.where(:status => 'completed').paginate(
- :page => params[:page],
- :order => 'id DESC',
- :per_page => 30
-
- )
-
- respond_to do |format|
- format.html # index.html.erb
- format.xml { render :xml => @dial_results }
- end
- end
-
- # GET /dial_results/1/reanalyze
- def reanalyze
- DialResult.update_all(['processed = ?', false], ['dial_job_id = ?', params[:id]])
- j = DialJob.find(params[:id])
- j.processed = false
- j.save
-
- redirect_to :action => 'analyze'
- end
-
- # GET /dial_results/1/process
- # GET /dial_results/1/process.xml
- def analyze
- @job_id = params[:id]
- @job = DialJob.find(@job_id)
-
- if(@job.processed)
- redirect_to :controller => 'analyze', :action => 'view', :id => @job_id
- return
- end
-
- @dial_data_total = DialResult.count(
- :conditions => [ 'dial_job_id = ? and completed = ?', @job_id, true ]
- )
-
- @dial_data_done = DialResult.count(
- :conditions => [ 'dial_job_id = ? and processed = ?', @job_id, true ]
- )
-
- ltypes = DialResult.find( :all, :select => 'DISTINCT line_type', :conditions => ["dial_job_id = ?", @job_id] ).map{|r| r.line_type}
- res_types = {}
-
- ltypes.each do |k|
- next if not k
- res_types[k.capitalize.to_sym] = DialResult.count(
- :conditions => ['dial_job_id = ? and line_type = ?', @job_id, k]
- )
- end
-
- @lines_by_type = res_types
-
- @dial_data_todo = DialResult.where(:dial_job_id => @job_id).paginate(
- :page => params[:page],
- :order => 'number ASC',
- :per_page => 50,
- :conditions => [ 'completed = ? and processed = ? and busy = ?', true, false, false ]
- )
-
- if @dial_data_todo.length > 0
- res = @job.schedule(:analysis)
- unless res
- flash[:error] = "Unable to launch analysis job"
- end
- end
- end
-
- # GET /dial_results/1/view
- # GET /dial_results/1/view.xml
- def view
- @dial_results = DialResult.where(:dial_job_id => params[:id]).paginate(
- :page => params[:page],
- :order => 'number ASC',
- :per_page => 30
- )
-
- unless @dial_results and @dial_results.length > 0
- redirect_to :action => :index
- return
- end
- @call_results = {
- :Timeout => DialResult.count(:conditions =>['dial_job_id = ? and completed = ?', params[:id], false]),
- :Busy => DialResult.count(:conditions =>['dial_job_id = ? and busy = ?', params[:id], true]),
- :Answered => DialResult.count(:conditions =>['dial_job_id = ? and completed = ?', params[:id], true]),
- }
-
- respond_to do |format|
- format.html # index.html.erb
- format.xml { render :xml => @dial_results }
- end
- end
-
- # GET /dial_results/1
- # GET /dial_results/1.xml
- def show
- @dial_result = DialResult.find(params[:id])
-
- unless @dial_result
- redirect_to :action => :index
- return
- end
-
- respond_to do |format|
- format.html # show.html.erb
- format.xml { render :xml => @dial_result }
- end
- end
-
- # GET /dial_results/new
- # GET /dial_results/new.xml
- def new
- @dial_result = DialResult.new
-
- respond_to do |format|
- format.html # new.html.erb
- format.xml { render :xml => @dial_result }
- end
- end
-
- # GET /dial_results/1/edit
- def edit
- @dial_result = DialResult.find(params[:id])
- end
-
- # POST /dial_results
- # POST /dial_results.xml
- def create
- @dial_result = DialResult.new(params[:dial_result])
-
- respond_to do |format|
- if @dial_result.save
- flash[:notice] = 'DialResult was successfully created.'
- format.html { redirect_to(@dial_result) }
- format.xml { render :xml => @dial_result, :status => :created, :location => @dial_result }
- else
- format.html { render :action => "new" }
- format.xml { render :xml => @dial_result.errors, :status => :unprocessable_entity }
- end
- end
- end
-
- # PUT /dial_results/1
- # PUT /dial_results/1.xml
- def update
- @dial_result = DialResult.find(params[:id])
-
- respond_to do |format|
- if @dial_result.update_attributes(params[:dial_result])
- flash[:notice] = 'DialResult was successfully updated.'
- format.html { redirect_to(@dial_result) }
- format.xml { head :ok }
- else
- format.html { render :action => "edit" }
- format.xml { render :xml => @dial_result.errors, :status => :unprocessable_entity }
- end
- end
- end
-
- # DELETE /dial_results/1
- # DELETE /dial_results/1.xml
- def destroy
-
- @job = DialJob.find(params[:id])
- @job.destroy
-
- respond_to do |format|
- format.html { redirect_to :action => 'index' }
- format.xml { head :ok }
- end
- end
-
-end
(DIR) diff --git a/app/controllers/home_controller.rb b/app/controllers/home_controller.rb
@@ -18,10 +18,10 @@ class HomeController < ApplicationController
def check
@has_project = ( Project.count > 0 )
- @has_provider = ( Provider.count > 0 )
- @has_job = ( DialJob.count > 0 )
- @has_result = ( DialResult.where(:completed => true ).count > 0 )
- @has_analysis = ( DialResult.where(:processed => true ).count > 0 )
+ @has_provider = ( Provider.where(:enabled => true).count > 0 )
+ @has_job = ( Job.where(:task => 'dialer').count > 0 )
+ @has_result = ( Call.where(:answered => true ).count > 0 )
+ @has_analysis = ( Call.where('analysis_completed_at IS NOT NULL').count > 0 )
end
end
(DIR) diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb
@@ -29,7 +29,6 @@ class ProjectsController < ApplicationController
# GET /projects/new.xml
def new
@new_project = Project.new
-
respond_to do |format|
format.html # new.html.erb
format.xml { render :xml => @new_project }
@@ -44,17 +43,17 @@ class ProjectsController < ApplicationController
# POST /projects
# POST /projects.xml
def create
- @project = Project.new(params[:project])
- @project.created_by = current_user.login
+ @new_project = Project.new(params[:project])
+ @new_project.created_by = current_user.login
respond_to do |format|
- if @project.save
+ if @new_project.save
flash[:notice] = 'Project was successfully created.'
- format.html { redirect_to(project_path(@project)) }
- format.xml { render :xml => @project, :status => :created, :location => @project }
+ format.html { redirect_to(project_path(@new_project)) }
+ format.xml { render :xml => @project, :status => :created, :location => @new_project }
else
format.html { render :action => "new" }
- format.xml { render :xml => @project.errors, :status => :unprocessable_entity }
+ format.xml { render :xml => @new_project.errors, :status => :unprocessable_entity }
end
end
end
(DIR) diff --git a/app/controllers/providers_controller.rb b/app/controllers/providers_controller.rb
@@ -1,9 +1,13 @@
class ProvidersController < ApplicationController
- # GET /providers
- # GET /providers.xml
def index
- @providers = Provider.find(:all)
+
+ @providers = Provider.paginate(
+ :page => params[:page],
+ :order => 'id DESC',
+ :per_page => 10
+ )
+
@new_provider = Provider.new
@new_provider.enabled = true
@@ -13,23 +17,10 @@ class ProvidersController < ApplicationController
end
end
- # GET /providers/1
- # GET /providers/1.xml
- def show
- @provider = Provider.find(params[:id])
- @provider.pass = "********"
-
- respond_to do |format|
- format.html # show.html.erb
- format.xml { render :xml => @provider }
- end
- end
-
- # GET /providers/new
- # GET /providers/new.xml
def new
@provider = Provider.new
@provider.enabled = true
+ @provider.port = 4569
respond_to do |format|
format.html # new.html.erb
@@ -37,14 +28,11 @@ class ProvidersController < ApplicationController
end
end
- # GET /providers/1/edit
def edit
@provider = Provider.find(params[:id])
@provider.pass = "********"
end
- # POST /providers
- # POST /providers.xml
def create
@provider = Provider.new(params[:provider])
@provider.enabled = true
@@ -52,8 +40,8 @@ class ProvidersController < ApplicationController
respond_to do |format|
if @provider.save
flash[:notice] = 'Provider was successfully created.'
- format.html { redirect_to(@provider) }
- format.xml { render :xml => @provider, :status => :created, :location => @provider }
+ format.html { redirect_to providers_path }
+ format.xml { render :xml => @provider, :status => :created, :location => providers_path }
else
format.html { render :action => "new" }
format.xml { render :xml => @provider.errors, :status => :unprocessable_entity }
@@ -61,8 +49,7 @@ class ProvidersController < ApplicationController
end
end
- # PUT /providers/1
- # PUT /providers/1.xml
+
def update
@provider = Provider.find(params[:id])
@@ -74,7 +61,7 @@ class ProvidersController < ApplicationController
respond_to do |format|
if @provider.update_attributes(params[:provider])
flash[:notice] = 'Provider was successfully updated.'
- format.html { redirect_to(@provider) }
+ format.html { redirect_to providers_path }
format.xml { head :ok }
else
format.html { render :action => "edit" }
@@ -83,14 +70,12 @@ class ProvidersController < ApplicationController
end
end
- # DELETE /providers/1
- # DELETE /providers/1.xml
def destroy
@provider = Provider.find(params[:id])
@provider.destroy
respond_to do |format|
- format.html { redirect_to(providers_url) }
+ format.html { redirect_to providers_path }
format.xml { head :ok }
end
end
(DIR) diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb
@@ -21,4 +21,33 @@ module ApplicationHelper
def set_focus(element_id)
javascript_tag(" $elem = $(\"#{element_id}\"); if (null !== $elem && $elem.length > 0){$elem.focus()}")
end
+
+ def format_job_details(job)
+ begin
+ info = Marshal.load(job.args.to_s)
+
+ ttip = raw("<div class='task_args_formatted'>")
+ info.each_pair do |k,v|
+ ttip << raw("<div class='task_args_var'>") + k.to_s.html_safe + raw(": </div> ")
+ ttip << raw("<div class='task_args_val'>") + v.to_s.html_safe + raw(" </div>")
+ end
+ ttip << raw("</div>\n")
+ outp = raw("<a href='#' rel='tooltip' title=\"#{ttip}\" data-html='true'>#{job.task.capitalize.html_safe}</a>")
+ outp
+ rescue ::Exception => e
+ job.status.to_s.capitalize
+ end
+ end
+
+ def format_job_status(job)
+ case job.status
+ when 'error'
+ ttip = job.error.to_s.html_safe
+ outp = raw("<a href='#' rel='tooltip' title=\"#{ttip}\" data-html='true'>#{job.status.capitalize.html_safe}</a>")
+ outp
+ else
+ job.status.to_s.capitalize
+ end
+
+ end
end
(DIR) diff --git a/app/helpers/dial_jobs_helper.rb b/app/helpers/dial_jobs_helper.rb
@@ -1,2 +0,0 @@
-module DialJobsHelper
-end
(DIR) diff --git a/app/helpers/dial_results_helper.rb b/app/helpers/dial_results_helper.rb
@@ -1,2 +0,0 @@
-module DialResultsHelper
-end
(DIR) diff --git a/app/models/call.rb b/app/models/call.rb
@@ -27,7 +27,7 @@ class Call < ActiveRecord::Base
def media
- CallMedium.find_or_create_by_call_id(self[:id])
+ CallMedium.find_or_create_by_call_id_and_project_id(self[:id], self[:project_id])
end
def media_fields
(DIR) diff --git a/app/models/call_medium.rb b/app/models/call_medium.rb
@@ -1,3 +1,4 @@
class CallMedium < ActiveRecord::Base
belongs_to :call
+ belongs_to :project
end
(DIR) diff --git a/app/models/dial_job.rb b/app/models/dial_job.rb
@@ -1,49 +0,0 @@
-class DialJob < ActiveRecord::Base
- attr_accessor :range_file
-
- has_many :dial_results, :dependent => :destroy
-
- validates_presence_of :range, :lines, :seconds
- validates_numericality_of :lines, :less_than => 256, :greater_than => 0
- validates_numericality_of :seconds, :less_than => 301, :greater_than => 0
-
-
- validate :validate_range
-
- def validate_range
- return if range == "IMPORTED"
-
- if range.gsub(/[^0-9X:,\n]/, '').empty?
- errors.add(:range, "must be at least 1 character long and made up of 0-9 and X as the mask.")
- end
-
- if(range.scan(/X/).length > 5)
- errors.add(:range, "must contain no more than 5 mask digits.")
- end
-
- if(cid_mask != "SELF" and cid_mask.gsub(/[^0-9X]/, '').empty?)
- errors.add(:range, "The Caller ID must be at least 1 character long and made up of 0-9 and X as the mask.")
- end
-
- if(cid_mask != "SELF" and cid_mask.scan(/X/).length > 5)
- errors.add(:range, "The Caller ID must contain no more than 5 mask digits.")
- end
- end
-
- attr_accessible :range, :seconds, :lines, :cid_mask
-
-
- def schedule(jtype)
- res = nil
- case jtype
- when :dialer
- res = WarVOX::JobManager.schedule(::WarVOX::Jobs::Dialer, self[:id])
- when :analysis
- res = WarVOX::JobManager.schedule(::WarVOX::Jobs::Analysis, self[:id])
- else
- raise RuntimeError, "Unknown task type: #{jtype} for Job #{self[:id]}"
- end
- res
- end
-
-end
(DIR) diff --git a/app/models/job.rb b/app/models/job.rb
@@ -1,12 +1,84 @@
class Job < ActiveRecord::Base
+
+ class JobValidator < ActiveModel::Validator
+ def validate(record)
+ case record.task
+ when 'dialer'
+
+ cracked_range = WarVOX::Phone.crack_mask(record.range) rescue []
+ unless cracked_range.length > 0
+ record.errors[:range] << "No valid ranges were specified"
+ end
+
+ cracked_mask = WarVOX::Phone.crack_mask(record.cid_mask) rescue []
+ unless cracked_mask.length > 0
+ record.errors[:cid_mask] << "No valid Caller ID mask was specified"
+ end
+
+ unless record.seconds.to_i > 0 and record.seconds.to_i < 300
+ record.errors[:seconds] << "Seconds should be between 1 and 300"
+ end
+
+ unless record.lines.to_i > 0 and record.lines.to_i < 10000
+ record.errors[:lines] << "Lines should be between 1 and 10,000"
+ end
+ when 'analysis'
+ when 'import'
+ else
+ record.errors[:base] << "Invalid task specified"
+ end
+ end
+ end
+
+
has_many :calls
belongs_to :project
+ validates_with JobValidator
+
+ def stop
+ self.class.update_all({ :status => 'cancelled'}, { :id => self.id })
+ end
def update_progress(pct)
if pct >= 100
- self.class.update_all({ :progress => pct, :completed_at => Time.now.utc }, { :id => self.id })
+ self.class.update_all({ :progress => pct, :completed_at => Time.now.utc, :status => 'completed' }, { :id => self.id })
else
self.class.update_all({ :progress => pct }, { :id => self.id })
end
end
+
+
+ validates_presence_of :project_id
+
+ attr_accessible :project_id
+
+
+ # Allow the base Job class to be used for Dial Jobs
+ attr_accessor :range
+ attr_accessor :range_file
+ attr_accessor :lines
+ attr_accessor :seconds
+ attr_accessor :cid_mask
+
+ attr_accessible :range, :seconds, :lines, :cid_mask
+
+
+ def schedule
+ case task
+ when 'dialer'
+ self.status = 'submitted'
+ self.args = Marshal.dump({
+ :range => self.range,
+ :lines => self.lines.to_i,
+ :seconds => self.seconds.to_i,
+ :cid_mask => self.cid_mask
+ })
+ return self.save
+ when 'analysis'
+ #
+ else
+ raise ::RuntimeError, "Unsupported Job type"
+ end
+ end
+
end
(DIR) diff --git a/app/models/line.rb b/app/models/line.rb
@@ -1,3 +1,16 @@
class Line < ActiveRecord::Base
- has_many :line_attributes
+ has_many :line_attributes, :dependent => :delete_all
+ belongs_to :project
+
+ def set_attribute(name, value, ctype='text/plain')
+ la = LineAttribute.find_or_create_by_line_id_and_project_id_and_name(self[:id], self[:project_id], name)
+ la.value = value
+ la.ctype = ctype
+ la.save
+ la
+ end
+
+ def get_attribute(name)
+ LineAttribute.where(:line_id => self[:id], :name => name).first
+ end
end
(DIR) diff --git a/app/models/line_attribute.rb b/app/models/line_attribute.rb
@@ -1,3 +1,4 @@
class LineAttribute < ActiveRecord::Base
belongs_to :line
+ belongs_to :project
end
(DIR) diff --git a/app/models/project.rb b/app/models/project.rb
@@ -1,9 +1,15 @@
class Project < ActiveRecord::Base
+
+
+ validates :name, :uniqueness => true
validates_presence_of :name
attr_accessible :name, :description, :included, :excluded
- has_many :lines
- has_many :calls
- has_many :jobs
+ # This is optimized for fast project deletion, even with thousands of calls/jobs/lines
+ has_many :lines, :dependent => :delete_all
+ has_many :line_attributes, :dependent => :delete_all
+ has_many :calls, :dependent => :delete_all
+ has_many :call_media, :dependent => :delete_all
+ has_many :jobs, :dependent => :delete_all
end
(DIR) diff --git a/app/views/analyze/index.html.erb b/app/views/analyze/index.html.erb
@@ -15,29 +15,28 @@
</thead>
<tbody>
-<% @jobs.sort{|a,b| b.id <=> a.id}.each do |dial_job| %>
+<% @jobs.sort{|a,b| b.id <=> a.id}.each do |job| %>
<tr>
- <td><%=h dial_job.id %></td>
- <td><%=h dial_job.range %></td>
- <td><%=h dial_job.cid_mask %></td>
+ <td><%=h job.id %></td>
+ <td><%=h job.range %></td>
+ <td><%=h job.cid_mask %></td>
<td><%=h (
- DialResult.count(:conditions => ['dial_job_id = ? and processed = ?', dial_job.id, true]).to_s +
+ job.calls.where("analysis_completed_at IS NOT NULL").count.to_s +
"/" +
- DialResult.count(:conditions => ['dial_job_id = ?', dial_job.id]).to_s
+ job.calls.count.to_s
)%></td>
- <td><%=h dial_job.started_at.localtime.strftime("%Y-%m-%d %H:%M:%S") %></td>
+ <td><%=h job.started_at.localtime.strftime("%Y-%m-%d %H:%M:%S") %></td>
<td>
- <a class="btn btn-mini" href="<%= view_dial_result_path(dial_job) %>"><i class="icon-bar-chart"></i></a>
- <% if(dial_job.processed) %>
- <a class="btn btn-mini" href="<%= analyze_dial_result_path(dial_job) %>"><i class="icon-eye-open"></i></a>
- <a class="btn btn-mini" href="<%= reanalyze_dial_result_path(dial_job) %>" data-confirm="Reprocess this job?" rel="nofollow"><i class="icon-refresh"></i></a>
+ <% if job.calls.where("analysis_completed_at IS NOT NULL").count > 0 %>
+ <a class="btn btn-mini" href="<%= analyze_call_path(job) %>"><i class="icon-eye-open"></i></a>
+ <a class="btn btn-mini" href="<%= reanalyze_call_path(job) %>" data-confirm="Reprocess this job?" rel="nofollow"><i class="icon-refresh"></i></a>
<% else %>
- <a class="btn btn-mini" href="<%= analyze_dial_result_path(dial_job) %>"><i class="icon-bolt"></i></a>
+ <a class="btn btn-mini" href="<%= analyze_call_path(job) %>"><i class="icon-bolt"></i></a>
<% end %>
- <a class="btn btn-mini" href="<%= dial_result_path(dial_job) %>" data-confirm="Delete all data for this job?" data-method="delete" rel="nofollow"><i class="icon-trash"></i></a>
+ <a class="btn btn-mini" href="<%= call_path(job) %>" data-confirm="Delete all data for this job?" data-method="delete" rel="nofollow"><i class="icon-trash"></i></a>
</td>
</tr>
(DIR) diff --git a/app/views/analyze/view.html.erb b/app/views/analyze/view.html.erb
@@ -21,40 +21,40 @@
</thead>
<tbody>
-<% @results.each do |dial_result| %>
+<% @results.each do |call| %>
<tr>
<td align='center'>
<object
type="application/x-shockwave-flash"
- data="/assets/musicplayer.swf?song_url=<%=resource_analyze_path(@job_id, dial_result.id, "mp3")%>"
+ data="/assets/musicplayer.swf?song_url=<%=resource_analyze_path(@job_id, call.id, "mp3")%>"
width="20"
height="17"
style="margin-bottom: -5px;"
>
- <param name="movie" value="/assets/musicplayer.swf?song_url=<%=resource_analyze_path(@job_id, dial_result.id, "mp3")%>"></param>
+ <param name="movie" value="/assets/musicplayer.swf?song_url=<%=resource_analyze_path(@job_id, call.id, "mp3")%>"></param>
<param name="wmode" value="transparent"></param>
</object>
- <b><%= dial_result.number %></b>
+ <b><%= call.number %></b>
<hr width='100%' size='1'/>
- CallerID: <%= dial_result.cid%><br/>
- Provider: <%=h dial_result.provider.name %><br/>
- Audio: <%=h dial_result.seconds %> Seconds<br/>
- Ringer: <%=h dial_result.ringtime %> Seconds<br/>
+ CallerID: <%= call.cid%><br/>
+ Provider: <%=h call.provider.name %><br/>
+ Audio: <%=h call.seconds %> Seconds<br/>
+ Ringer: <%=h call.ringtime %> Seconds<br/>
</td>
<td align='center'>
- <b><%=h dial_result.line_type.upcase %></b><br/>
- <a href="<%=resource_analyze_path(@job_id, dial_result.id, "big_sig_dots")%>" class="lightbox"><img src="<%=resource_analyze_path(@job_id, dial_result.id, "small_sig")%>" /></a>
- <a href="<%=resource_analyze_path(@job_id, dial_result.id, "big_freq")%>" class="lightbox"><img src="<%=resource_analyze_path(@job_id, dial_result.id, "small_freq")%>" /></a><br/>
- <% (dial_result.signatures||"").split("\n").each do |s|
+ <b><%=h call.line_type.upcase %></b><br/>
+ <a href="<%=resource_analyze_path(@job_id, call.id, "big_sig_dots")%>" class="lightbox"><img src="<%=resource_analyze_path(@job_id, call.id, "small_sig")%>" /></a>
+ <a href="<%=resource_analyze_path(@job_id, call.id, "big_freq")%>" class="lightbox"><img src="<%=resource_analyze_path(@job_id, call.id, "small_freq")%>" /></a><br/>
+ <% (call.signatures||"").split("\n").each do |s|
sid,mat,name = s.split(':', 3)
str = [mat.to_i * 6.4, 255].min
col = ("%.2x" % (255 - str)) * 3
%>
<div style="color: #<%= col%>;"><%=h name%> (<%=h sid %>@<%=h mat %>)</div>
<% end %>
- <% if dial_result.fprint and dial_result.fprint.length > 0 %>
- <a href="<%=view_matches_path(dial_result.id)%>">View Matches</a>
+ <% if call.fprint and call.fprint.length > 0 %>
+ <a href="<%=view_matches_path(call.id)%>">View Matches</a>
<% end %>
</td>
</tr>
(DIR) diff --git a/app/views/analyze/view_matches.html.erb b/app/views/analyze/view_matches.html.erb
@@ -1,6 +1,6 @@
-<% dial_result = @result %>
+<% call = @result %>
-<h1 class='title'><%= @result.number %> (<a href="<%=view_analyze_path(dial_result.dial_job_id)%>">Back to Job</a>)</h1>
+<h1 class='title'><%= @result.number %> (<a href="<%=view_analyze_path(call.job_id)%>">Back to Job</a>)</h1>
<table class='table table-striped table-bordered' width='90%'>
<tr>
<th>Number</th>
@@ -12,27 +12,27 @@
<object
type="application/x-shockwave-flash"
- data="/assets/musicplayer.swf?song_url=<%=resource_analyze_path(@job_id, dial_result.id, "mp3")%>"
+ data="/assets/musicplayer.swf?song_url=<%=resource_analyze_path(@job_id, call.id, "mp3")%>"
width="20"
height="17"
style="margin-bottom: -5px;"
>
- <param name="movie" value="/assets/musicplayer.swf?song_url=<%=resource_analyze_path(@job_id, dial_result.id, "mp3")%>"></param>
+ <param name="movie" value="/assets/musicplayer.swf?song_url=<%=resource_analyze_path(@job_id, call.id, "mp3")%>"></param>
<param name="wmode" value="transparent"></param>
</object>
- <b><%= dial_result.number %></b>
+ <b><%= call.number %></b>
<hr width='100%' size='1'/>
- CallerID: <%= dial_result.cid%><br/>
- Provider: <%=h dial_result.provider.name %><br/>
- Audio: <%=h dial_result.seconds %> Seconds<br/>
- Ringer: <%=h dial_result.ringtime %> Seconds<br/>
+ CallerID: <%= call.cid%><br/>
+ Provider: <%=h call.provider.name %><br/>
+ Audio: <%=h call.seconds %> Seconds<br/>
+ Ringer: <%=h call.ringtime %> Seconds<br/>
</td>
<td align='center'>
- <b><%=h dial_result.line_type.upcase %></b><br/>
- <a href="<%=resource_analyze_path(@job_id, dial_result.id, "big_sig_dots")%>" rel="lightbox"><img src="<%=resource_analyze_path(@job_id, dial_result.id, "small_sig")%>" /></a>
- <a href="<%=resource_analyze_path(@job_id, dial_result.id, "big_freq")%>" rel="lightbox"><img src="<%=resource_analyze_path(@job_id, dial_result.id, "small_freq")%>" /></a><br/>
- <% (dial_result.signatures||"").split("\n").each do |s|
+ <b><%=h call.line_type.upcase %></b><br/>
+ <a href="<%=resource_analyze_path(@job_id, call.id, "big_sig_dots")%>" rel="lightbox"><img src="<%=resource_analyze_path(@job_id, call.id, "small_sig")%>" /></a>
+ <a href="<%=resource_analyze_path(@job_id, call.id, "big_freq")%>" rel="lightbox"><img src="<%=resource_analyze_path(@job_id, call.id, "small_freq")%>" /></a><br/>
+ <% (call.signatures||"").split("\n").each do |s|
sid,mat,name = s.split(':', 3)
str = [mat.to_i * 6.4, 255].min
col = ("%.2x" % (255 - str)) * 3
@@ -55,43 +55,43 @@
</thead>
<tbody>
-<% @results.each do |dial_result| %>
+<% @results.each do |call| %>
<tr>
<td align='center'>
- <br/><%= raw(fwd_match_html(dial_result.matchscore)) %><br/><br/>
+ <br/><%= raw(fwd_match_html(call.matchscore)) %><br/><br/>
<object
type="application/x-shockwave-flash"
- data="/assets/musicplayer.swf?song_url=<%=resource_analyze_path(@job_id, dial_result.id, "mp3")%>"
+ data="/assets/musicplayer.swf?song_url=<%=resource_analyze_path(@job_id, call.id, "mp3")%>"
width="20"
height="17"
style="margin-bottom: -5px;"
>
- <param name="movie" value="/assets/musicplayer.swf?song_url=<%=resource_analyze_path(@job_id, dial_result.id, "mp3")%>"></param>
+ <param name="movie" value="/assets/musicplayer.swf?song_url=<%=resource_analyze_path(@job_id, call.id, "mp3")%>"></param>
<param name="wmode" value="transparent"></param>
</object>
- <b><%= dial_result.number %></b>
+ <b><%= call.number %></b>
<hr width='100%' size='1'/>
- CallerID: <%= dial_result.cid%><br/>
- Provider: <%=h dial_result.provider.name %><br/>
- Audio: <%=h dial_result.seconds %> Seconds<br/>
- Ringer: <%=h dial_result.ringtime %> Seconds<br/>
+ CallerID: <%= call.cid%><br/>
+ Provider: <%=h call.provider.name %><br/>
+ Audio: <%=h call.seconds %> Seconds<br/>
+ Ringer: <%=h call.ringtime %> Seconds<br/>
</td>
<td align='center'>
- <b><%=h dial_result.line_type.upcase %></b><br/>
- <a href="<%=resource_analyze_path(@job_id, dial_result.id, "big_sig_dots")%>" class="lightbox"><img src="<%=resource_analyze_path(@job_id, dial_result.id, "small_sig")%>" /></a>
- <a href="<%=resource_analyze_path(@job_id, dial_result.id, "big_freq")%>" class="lightbox"><img src="<%=resource_analyze_path(@job_id, dial_result.id, "small_freq")%>" /></a><br/>
- <% (dial_result.signatures||"").split("\n").each do |s|
+ <b><%=h call.line_type.upcase %></b><br/>
+ <a href="<%=resource_analyze_path(@job_id, call.id, "big_sig_dots")%>" class="lightbox"><img src="<%=resource_analyze_path(@job_id, call.id, "small_sig")%>" /></a>
+ <a href="<%=resource_analyze_path(@job_id, call.id, "big_freq")%>" class="lightbox"><img src="<%=resource_analyze_path(@job_id, call.id, "small_freq")%>" /></a><br/>
+ <% (call.signatures||"").split("\n").each do |s|
sid,mat,name = s.split(':', 3)
str = [mat.to_i * 6.4, 255].min
col = ("%.2x" % (255 - str)) * 3
%>
<div style="color: #<%= col%>;"><%=h name%> (<%=h sid %>@<%=h mat %>)</div>
<% end %>
- <% if dial_result.fprint %>
- <a href="<%=view_matches_path(dial_result.id)%>">View Matches</a>
+ <% if call.fprint %>
+ <a href="<%=view_matches_path(call.id)%>">View Matches</a>
<% end %>
</td>
</tr>
(DIR) diff --git a/app/views/dial_jobs/edit.html.erb b/app/views/dial_jobs/edit.html.erb
@@ -1,24 +0,0 @@
-<h1 class='title'>Modify Job</h1>
-
-<%= form_for(@dial_job) do |f| %>
- <%= f.error_messages %>
-
- <p>
- <%= f.label :range %><br />
- <%= f.text_area :range, :size => "35x5" %>
- </p>
- <p>
- <%= f.label :seconds %><br />
- <%= f.text_field :seconds %>
- </p>
- <p>
- <%= f.label :lines %><br />
- <%= f.text_field :lines %>
- </p>
- <p>
- <%= f.submit "Update" %>
- </p>
-<% end %>
-
-<%= link_to 'Show', @dial_job %> |
-<%= link_to 'Back', dial_jobs_path(@project) %>
(DIR) diff --git a/app/views/dial_jobs/index.html.erb b/app/views/dial_jobs/index.html.erb
@@ -1,81 +0,0 @@
-<% if(@submitted_jobs.length > 0) %>
-
-<h1 class='title'>Submitted Jobs</h1>
-
-<table class='table table-striped table-bordered' width='90%'>
- <tr>
- <th>ID</th>
- <th>Range</th>
- <th>CallerID</th>
- <th>Seconds</th>
- <th>Lines</th>
- <th>Submitted Time</th>
- <th>Actions</th>
- </tr>
-
-<% @submitted_jobs.each do |dial_job| %>
- <tr>
- <td><%=h dial_job.id %></td>
- <td><%=h dial_job.range %></td>
- <td><%=h dial_job.cid_mask %></td>
- <td><%=h dial_job.seconds %></td>
- <td><%=h dial_job.lines %></td>
- <td><%=h dial_job.created_at.localtime.strftime("%Y-%m-%d %H:%M:%S %Z") %></td>
-
- <td>
- <a class="btn btn-mini" href="<%= run_dial_job_path(@project, dial_job) %>" data-confirm="Launch this job?" rel="nofollow tooltip" title="Launch Job"><i class="icon-play"></i></a>
- <a class="btn btn-mini" href="<%= dial_job %>" data-confirm="Remove this job?" data-method="delete" rel="nofollow tooltip" title="Remove Job"><i class="icon-trash"></i></a>
- </td>
- </tr>
-<% end %>
-</table>
-<br />
-<% end %>
-
-<% if(@active_jobs.length > 0) %>
-
-<h1 class='title'>Active Jobs</h1>
-
-<table class='table table-striped table-bordered' width='90%'>
- <tr>
- <th>ID</th>
- <th>Range</th>
- <th>CallerID</th>
- <th>Seconds</th>
- <th>Lines</th>
- <th>Status</th>
- <th>Progress</th>
- <th>Start Time</th>
- <th>Actions</th>
- </tr>
-
-<% @active_jobs.each do |dial_job| %>
- <tr class='active_job_row'>
- <td><%=h dial_job.id %></td>
- <td><%=h dial_job.range %></td>
- <td><%=h dial_job.cid_mask %></td>
- <td><%=h dial_job.seconds %></td>
- <td><%=h dial_job.lines %></td>
- <td><%=h dial_job.status %></td>
- <td><%=h dial_job.progress %>%</td>
- <td><%=h dial_job.started_at.localtime.strftime("%Y-%m-%d %H:%M:%S %Z") %></td>
- <td>
- <a class="btn btn-mini" href="<%= stop_dial_job_path(@project, dial_job) %>" data-confirm="Terminate this job?" rel="nofollow tooltip" title="Terminate Job"><i class="icon-stop"></i></a>
- </td>
- </tr>
-<% end %>
-</table>
-<br />
-
-<script language="javascript">
- setTimeout("location.reload(true);", 20000);
-</script>
-
-<% end %>
-
-<% if (@active_jobs.length + @submitted_jobs.length == 0) %>
-<h1 class='title'>No Active Jobs</h1>
-<br/>
-<a class="btn" href="<%= new_dial_job_path(@project) %>"><i class="icon-plus"></i> Start Job </a>
-
-<% end %>
(DIR) diff --git a/app/views/dial_jobs/new.html.erb b/app/views/dial_jobs/new.html.erb
@@ -1,35 +0,0 @@
-<h1 class='title'>Submit a New Job</h1>
-
-<%= form_for(@dial_job, :html => { :multipart => true }) do |f| %>
- <%= f.error_messages %>
- <p>
- <%= f.label :range, 'Specify target telephone range(s) (1-123-456-7890 or 1-123-456-XXXX or 1-123-300-1000:1-123-400-2000)' %><br />
- <%= f.text_area :range, :size => "35x5" %>
- </p>
-
- <p>
- <%= f.label :range_file, 'Or upload a file containing the target ranges' %><br />
- <%= f.file_field :range_file %>
- </p>
-
- <p>
- <%= f.label :seconds, 'Seconds of audio to capture' %><br />
- <%= f.text_field :seconds, :value => 53 %>
- </p>
-
- <p>
- <%= f.label :lines, 'Maximum number of outgoing lines' %><br />
- <%= f.text_field :lines, :value => 10 %>
- </p>
-
- <p>
- <%= f.label :lines, 'The source Caller ID range (1-555-555-55XX or SELF)' %><br />
- <%= f.text_field :cid_mask, :value => '1-123-456-XXXX' %>
- </p>
-
- <p>
- <%= f.submit "Create" %>
- </p>
-<% end %>
-
-<%= link_to 'Back', dial_jobs_path(@project) %>
(DIR) diff --git a/app/views/dial_jobs/run.html.erb b/app/views/dial_jobs/run.html.erb
@@ -1,5 +0,0 @@
-<h1 class='title'>Run Job</h1>
-
-Running this job...<br/>
-
-<%= link_to 'Back', dial_jobs_path %>
(DIR) diff --git a/app/views/dial_jobs/show.html.erb b/app/views/dial_jobs/show.html.erb
@@ -1,39 +0,0 @@
-<h1 class='title'>Show Job</h1>
-<p>
- <b>Range:</b>
- <%=h @dial_job.range %>
-</p>
-
-<p>
- <b>Seconds:</b>
- <%=h @dial_job.seconds %>
-</p>
-
-<p>
- <b>Lines:</b>
- <%=h @dial_job.lines %>
-</p>
-
-<p>
- <b>Status:</b>
- <%=h @dial_job.status %>
-</p>
-
-<p>
- <b>Progress:</b>
- <%=h @dial_job.progress %>
-</p>
-
-<p>
- <b>Started at:</b>
- <%=h @dial_job.started_at %>
-</p>
-
-<p>
- <b>Completed at:</b>
- <%=h @dial_job.completed_at %>
-</p>
-
-
-<%= link_to 'Edit', edit_dial_job_path(@dial_job) %> |
-<%= link_to 'Back', dial_jobs_path %>
(DIR) diff --git a/app/views/dial_results/analyze.html.erb b/app/views/dial_results/analyze.html.erb
@@ -1,27 +0,0 @@
-<% if @dial_data_todo.length > 0 %>
-
-<h1 class='title'>
- Analyzing Audio for <%= @dial_data_total-@dial_data_done %> of <%= @dial_data_total %> Calls...
-</h1>
-
-<table width='100%' align='center' border=0 cellspacing=0 cellpadding=6>
-<tr>
-<% if @dial_data_done > 0 %>
- <td align='center'>
- <%= render :partial => 'shared/graphs/lines_by_type' %>
- </td>
-<% end %>
-</tr>
-</table>
-
-<script language="javascript">
- setTimeout("location.reload(true);", 10000);
-</script>
-
-<% else %>
-
-<h1 class='title'>No Completed Calls Found</h1>
-
-<% end %>
-
-<br />
(DIR) diff --git a/app/views/dial_results/edit.html.erb b/app/views/dial_results/edit.html.erb
@@ -1,48 +0,0 @@
-<h1>Editing dial_result</h1>
-
-<%= form_for(@dial_result) do |f| %>
- <%= f.error_messages %>
-
- <p>
- <%= f.label :number %><br />
- <%= f.text_field :number %>
- </p>
- <p>
- <%= f.label :cid %><br />
- <%= f.text_field :cid %>
- </p>
- <p>
- <%= f.label :dial_job_id %><br />
- <%= f.text_field :dial_job_id %>
- </p>
- <p>
- <%= f.label :provider %><br />
- <%= f.text_field :provider %>
- </p>
- <p>
- <%= f.label :completed %><br />
- <%= f.check_box :completed %>
- </p>
- <p>
- <%= f.label :busy %><br />
- <%= f.check_box :busy %>
- </p>
- <p>
- <%= f.label :seconds %><br />
- <%= f.text_field :seconds %>
- </p>
- <p>
- <%= f.label :ringtime %><br />
- <%= f.text_field :ringtime %>
- </p>
- <p>
- <%= f.label :rawfile %><br />
- <%= f.text_field :rawfile %>
- </p>
- <p>
- <%= f.submit "Update" %>
- </p>
-<% end %>
-
-<%= link_to 'Show', @dial_result %> |
-<%= link_to 'Back', dial_results_path(@project) %>
(DIR) diff --git a/app/views/dial_results/index.html.erb b/app/views/dial_results/index.html.erb
@@ -1,57 +0,0 @@
-<% if @jobs.length > 0 %>
-<h1 class='title'>Completed Jobs</h1>
-
-<%= raw(will_paginate @jobs) %>
-<table class='table table-striped table-bordered' width='90%'>
- <thead>
- <tr>
- <th>ID</th>
- <th>Range</th>
- <th>CallerID</th>
- <th>Connected</th>
- <th>Date</th>
- <th>Actions</th>
- </tr>
- </thead>
- <tbody>
-
-<% @jobs.sort{|a,b| b.id <=> a.id}.each do |dial_job| %>
- <tr>
- <td><%=h dial_job.id %></td>
- <td><%=h dial_job.range %></td>
- <td><%=h dial_job.cid_mask %></td>
- <td><%=h (
- DialResult.count(:conditions => ['dial_job_id = ? and processed = ?', dial_job.id, true]).to_s +
- "/" +
- DialResult.count(:conditions => ['dial_job_id = ?', dial_job.id]).to_s
- )%></td>
- <td><%=h dial_job.started_at.localtime.strftime("%Y-%m-%d %H:%M:%S") %></td>
-
- <td>
- <a class="btn btn-mini" href="<%= view_dial_result_path(@project,dial_job) %>" rel="tooltip" title="View Call Connections" ><i class="icon-bar-chart"></i></a>
-
- <% if(dial_job.processed) %>
- <a class="btn btn-mini" href="<%= analyze_dial_result_path(@project,dial_job) %>" rel="tooltip" title="View Call Analysis"><i class="icon-eye-open"></i></a>
- <a class="btn btn-mini" href="<%= reanalyze_dial_result_path(@project,dial_job) %>" data-confirm="Reprocess this job?" rel="nofollow tooltip" title="Rerun Call Analysis"><i class="icon-refresh"></i></a>
- <% else %>
- <a class="btn btn-mini" href="<%= analyze_dial_result_path(@project,dial_job) %>" data-confirm="Analyze this job?" rel="nofollow tooltip" title="Run Call Analysis"><i class="icon-bolt"></i></a>
- <% end %>
-
- <a class="btn btn-mini" href="<%= dial_result_path(@project,dial_job) %>" data-confirm="Delete all data for this job?" data-method="delete" rel="nofollow tooltip" title="Delete Call Data"><i class="icon-trash"></i></a>
- </td>
- </tr>
-
-<% end %>
-</tbody>
-</table>
-
-<%= raw(will_paginate @jobs) %>
-
-<% else %>
-
-<h1 class='title'>No Completed Jobs</h1>
-<br/>
-
-<% end %>
-
-<a class="btn" href="<%= new_dial_job_path(@project) %>"><i class="icon-plus"></i> Start Job </a>
(DIR) diff --git a/app/views/dial_results/new.html.erb b/app/views/dial_results/new.html.erb
@@ -1,43 +0,0 @@
-<h1>New dial_result</h1>
-
-<%= form_for(@dial_result) do |f| %>
- <%= f.error_messages %>
-
- <p>
- <%= f.label :number %><br />
- <%= f.text_field :number %>
- </p>
- <p>
- <%= f.label :dial_job_id %><br />
- <%= f.text_field :dial_job_id %>
- </p>
- <p>
- <%= f.label :provider %><br />
- <%= f.text_field :provider %>
- </p>
- <p>
- <%= f.label :completed %><br />
- <%= f.check_box :completed %>
- </p>
- <p>
- <%= f.label :busy %><br />
- <%= f.check_box :busy %>
- </p>
- <p>
- <%= f.label :seconds %><br />
- <%= f.text_field :seconds %>
- </p>
- <p>
- <%= f.label :ringtime %><br />
- <%= f.text_field :ringtime %>
- </p>
- <p>
- <%= f.label :rawfile %><br />
- <%= f.text_field :rawfile %>
- </p>
- <p>
- <%= f.submit "Create" %>
- </p>
-<% end %>
-
-<%= link_to 'Back', dial_results_path(@project) %>
(DIR) diff --git a/app/views/dial_results/show.html.erb b/app/views/dial_results/show.html.erb
@@ -1,48 +0,0 @@
-<p>
- <b>Number:</b>
- <%=h @dial_result.number %>
-</p>
-
-<p>
- <b>CallerID:</b>
- <%=h @dial_result.cid %>
-</p>
-
-<p>
- <b>Dial job:</b>
- <%=h @dial_result.dial_job_id %>
-</p>
-
-<p>
- <b>Provider:</b>
- <%=h @dial_result.provider %>
-</p>
-
-<p>
- <b>Completed:</b>
- <%=h @dial_result.completed %>
-</p>
-
-<p>
- <b>Busy:</b>
- <%=h @dial_result.busy %>
-</p>
-
-<p>
- <b>Seconds:</b>
- <%=h @dial_result.seconds %>
-</p>
-
-<p>
- <b>Ringtime:</b>
- <%=h @dial_result.ringtime %>
-</p>
-
-<p>
- <b>Rawfile:</b>
- <%=h @dial_result.rawfile %>
-</p>
-
-
-<%= link_to 'Edit', edit_dial_result_path(@project, @dial_result) %> |
-<%= link_to 'Back', dial_results_path(@project) %>
(DIR) diff --git a/app/views/dial_results/view.html.erb b/app/views/dial_results/view.html.erb
@@ -1,58 +0,0 @@
-<% if @dial_results %>
-
-
-<h1 class='title'>Dial Results for Job <%=@dial_results[0].dial_job_id%></h1>
-
-<%= raw(will_paginate @dial_results) %>
-<table width='100%' align='center' border=0 cellspacing=0 cellpadding=6>
-<tr>
- <td align='center'>
- <%= render :partial => 'shared/graphs/call_results' %>
- </td>
-</tr>
-</table>
-
-<br/>
-
-<table class='table table-striped table-bordered' width='90%' id='results'>
- <thead>
- <tr>
- <th>Number</th>
- <th>CallerID</th>
- <th>Provider</th>
- <th>Completed</th>
- <th>Busy</th>
- <th>Seconds</th>
- <th>Ring Time</th>
- </tr>
- </thead>
- <tbody>
-<% for dial_result in @dial_results.sort{|a,b| a.number <=> b.number } %>
- <tr>
- <td><%= dial_result.number %></td>
- <td><%= dial_result.cid %></td>
- <td><%= dial_result.provider.name %></td>
- <td><%= dial_result.completed %></td>
- <td><%= dial_result.busy %></td>
- <td><%= dial_result.seconds %></td>
- <td><%= dial_result.ringtime.to_i %></td>
- </tr>
-<% end %>
- </tbody>
-</table>
-<%= raw(will_paginate @dial_results) %>
-
-<% else %>
-
-<h1 class='title'>No Dial Results</h1>
-
-<% end %>
-<br />
-
-<%= javascript_tag do %>
-// For fixed width containers
-$('#results').dataTable({
- "sDom": "<'row'<'span6'l><'span6'f>r>t<'row'<'span6'i><'span6'p>>",
- "sPaginationType": "bootstrap"
-});
-<% end %>
(DIR) diff --git a/app/views/home/about.html.erb b/app/views/home/about.html.erb
@@ -43,21 +43,21 @@ and research purposes only. The latest version of WarVOX can be found in <i clas
<td>
Active Jobs
</td>
- <td><%= DialJob.count(:conditions => ['status = ?', 'active']) %></td>
+ <td><%= Job.count(:conditions => { :completed_at => nil }) %></td>
</tr>
<tr>
<td>
Total Jobs
</td>
- <td><%= DialJob.count %></td>
+ <td><%= Job.count %></td>
</tr>
<tr>
<td>
- Results
+ Calls
</td>
- <td><%= DialResult.count %></td>
+ <td><%= Call.count %></td>
</tr>
</table>
</div>
(DIR) diff --git a/app/views/home/check.html.erb b/app/views/home/check.html.erb
@@ -4,9 +4,9 @@
<!--
@has_project = ( Project.count > 0 )
@has_provider = ( Provider.count > 0 )
- @has_job = ( DialJob.count > 0 )
- @has_result = ( DialResult.where(:completed => true ).count > 0 )
- @has_analysis = ( DialResult.where(:processed => true ).count > 0 )
+ @has_job = ( Job.count > 0 )
+ @has_result = ( Call.where(:completed => true ).count > 0 )
+ @has_analysis = ( Call.where(:processed => true ).count > 0 )
-->
<br/>
@@ -54,7 +54,7 @@
<div class="alert alert-error">
<strong>Ring Ring!</strong>
<% if @has_project %>
- <p>You need to <a href="<%= new_dial_job_path(Project.last) %>">dial your target range</a> to gather audio data.</p>
+ <p>You need to <a href="<%= new_job_path(Project.last) %>">dial your target range</a> to gather audio data.</p>
<% else %>
<p>You need to <a href="<%= new_project_path %>">create a project</a>.</p>
<% end %>
(DIR) diff --git a/app/views/home/index.html.erb b/app/views/home/index.html.erb
@@ -26,7 +26,7 @@ connected to modems, allowing for a comprehensive audit of a telephone system.
In order to make phone calls, WarVOX needs to be configured with one or more service providers. For a list of compatible VoIP ISPs, please see the <a href="http://warvox.org/#Providers">Service Providers</a> section of the WarVOX web site. To add a new provider to WarVOX, access the web interface, click the <a href="/providers">Providers</a> link, and fill in the <b>New Provider</b> form. This form allows you to specify a nickname for the provider and indicate how many concurrent outbound calls can be made using this account. WarVOX can make use of multiple service providers and multiple outbuond calls per provider when processing jobs.
</p>
-<p>Once one or more service providers have been configured, click the <a href="/dial_jobs/">Jobs</a> link. This will present a form that asks for the phone number range to dial, the number of seconds of audio to capture, and the maximum number of outgoing lines to use for this job.
+<p>Once one or more service providers have been configured, click the <a href="/jobs/">Jobs</a> link. This will present a form that asks for the phone number range to dial, the number of seconds of audio to capture, and the maximum number of outgoing lines to use for this job.
</p>
<p>The phone number range is specified by entering the phone number (including country code), with numbers replaced by X's where an entire range should be dialed. For example, the value 1-512-555-XXXX will make 10,000 calls, one to each number within the 512-555 exchange. In contrast, the value 1-512-555-555X will only make 10 calls, covering 5550 to 5559. Only 5 digits of the phone number range can be masked.
@@ -44,11 +44,11 @@ The outgoing line count is limited by the number of providers available and the
</p>
<p>
-Once the job parameters have been specified, click the <b>Create</b> button to start dialing. If you return the main <a href="/dial_jobs/">Jobs</a> screen you can track the progress of the job via the percentage value in the active jobs table. The amount of time a given job takes depends on the number of phone numbers within the range, the number of seconds of audio to record, and the number of concurrent outbound lines. A 1,000 number range with 53 seconds of audio and 10 outbound lines would take approximately 100 minutes to complete.
+Once the job parameters have been specified, click the <b>Create</b> button to start dialing. If you return the main <a href="/jobs/">Jobs</a> screen you can track the progress of the job via the percentage value in the active jobs table. The amount of time a given job takes depends on the number of phone numbers within the range, the number of seconds of audio to record, and the number of concurrent outbound lines. A 1,000 number range with 53 seconds of audio and 10 outbound lines would take approximately 100 minutes to complete.
</p>
<p>
-After the job completes, access the <a href="/dial_results/">Results</a> link to view a listing of finished jobs. Click the <b>View</b> link to look at the raw call breakdown. To analyze the call data, click on the Results link, and then click the <b>Analyze Calls</b> link. Depending on the speed of your server, this can take up to 60 seconds per connected call to process all of the data. Once the data has been processed, the results will now be listed under the <a href="/analyze/">Analysis</a> link. Viewing the results will provide the signal graph, spectrum graph, and an audio player to hear the actual call.
+After the job completes, access the <a href="/calls/">Results</a> link to view a listing of finished jobs. Click the <b>View</b> link to look at the raw call breakdown. To analyze the call data, click on the Results link, and then click the <b>Analyze Calls</b> link. Depending on the speed of your server, this can take up to 60 seconds per connected call to process all of the data. Once the data has been processed, the results will now be listed under the <a href="/analyze/">Analysis</a> link. Viewing the results will provide the signal graph, spectrum graph, and an audio player to hear the actual call.
</p>
(DIR) diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb
@@ -32,20 +32,29 @@
<%= menu_group :pull => :right do %>
<% if @project and @project.id %>
- <li class="project-title"><%= truncate(@project.name, :length => 20) %></li>
- <%= menu_item "Dial", new_dial_job_path(@project) %>
- <%= menu_item "Jobs", dial_jobs_path(@project) %>
- <%= menu_item "Results", dial_results_path(@project) %>
+ <li>
+ <%= link_to(
+ raw(
+ '<i class="icon-chevron-left icon-white"></i> ' +
+ truncate(@project.name, :length => 20).html_safe +
+ ' <i class="icon-chevron-right icon-white"></i>'), project_path(@project), :class => 'project-title') %>
+ </li>
+ <%= menu_item "Results", calls_path(@project) %>
<%= menu_item "Analysis", analyze_path(@project)%>
<% end %>
+ <%= menu_item "Jobs", jobs_path %>
<%= drop_down "Projects" do %>
- <%= menu_item raw('<i class="icon-list"></i> Browse Projects'),projects_path %>
+ <% if Project.count > 0 %>
+ <%= menu_item raw('<i class="icon-list"></i> Browse Projects'),projects_path %>
+ <% end %>
<%= menu_item raw('<i class="icon-plus"></i> Create Project'), new_project_path %>
- <%= drop_down_divider %>
- <%= drop_down_header "Recent Projects" %>
- <% Project.find(:all, :order => 'ID DESC', :limit => 5).each do |project| %>
- <%= menu_item raw('<i class="icon-chevron-right"></i> ' + truncate(project.name, :length => 15).html_safe),project_path(project) %>
+ <% if Project.count > 0 %>
+ <%= drop_down_divider %>
+ <%= drop_down_header "Recent Projects" %>
+ <% Project.find(:all, :order => 'ID DESC', :limit => 5).each do |project| %>
+ <%= menu_item raw('<i class="icon-chevron-right"></i> ' + truncate(project.name, :length => 15).html_safe),project_path(project) %>
+ <% end %>
<% end %>
<% end %>
@@ -65,13 +74,9 @@
<div class="row">
<div class="span12 content">
-<% # render_breadcrumbs %>
<div class="content">
-
-
-<p style="color: green"><%= flash[:notice] %></p>
-
+ <p style="color: green"><%= flash[:notice] %></p>
<%= yield %>
</div>
(DIR) diff --git a/app/views/projects/edit.html.erb b/app/views/projects/edit.html.erb
@@ -1,11 +1,10 @@
<h1 class='title'>Update Project</h1>
<%= semantic_form_for(@project) do |f| %>
- <%= f.input :name, :as => :string, :label => 'Project Name' %>
+ <%= f.input :name, :as => :string, :label => 'Name' %>
<%= f.input :description, :as => :text, :input_html => { :class => 'project_description' } %>
- <%= f.input :included, :as => :text, :label => 'Default phone numbers to include', :input_html => { :class => 'project_includes' } %>
- <%= f.input :excluded, :as => :text, :label => 'Default phone numbers to exclude', :input_html => { :class => 'project_includes' } %>
- <%= f.actions :submit, :label => 'Update' %>
+ <%= f.action :submit, :label => 'Update', :button_html => { :class => 'btn btn-large fbtn' } %>
+ <a class="btn btn-link" href="<%= projects_path %>"rel="tooltip" title="Return to projects"><i class="icon-return"></i>Cancel</a>
<% end %>
-<%= link_to 'Back', projects_path %>
+<%= set_focus('project_name') %>
(DIR) diff --git a/app/views/projects/index.html.erb b/app/views/projects/index.html.erb
@@ -7,17 +7,23 @@
<tr>
<th>Name</th>
<th>Description</th>
+ <th>Jobs</th>
+ <th>Calls</th>
+ <th>Analyzed</th>
<th>Date</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
-<% @projects.sort{|a,b| b.id <=> a.id}.each do |project| %>
+<% @projects.each do |project| %>
<tr>
<td><%= link_to( h(project.name), project_path(project)) %></td>
<td><%=truncate(project.description, :length => 40, :separator => '') %></td>
- <td><%=h project.updated_at.localtime.strftime("%Y-%m-%d %H:%M:%S") %></td>
+ <td><%= project.jobs.count %></td>
+ <td><%= project.calls.count %></td>
+ <td><%= project.calls.where('analysis_completed_at IS NOT NULL').count %></td>
+ <td><%= project.updated_at.localtime.strftime("%Y-%m-%d %H:%M:%S") %></td>
<td>
<a class="btn btn-mini" href="<%= edit_project_path(project) %>"rel="tooltip" title="Update Project Information"><i class="icon-pencil"></i></a>
<a class="btn btn-mini" href="<%= project_path(project) %>" data-confirm="Delete this project?" data-method="delete" rel="nofollow tooltip" title="Delete Project"><i class="icon-trash"></i></a>
(DIR) diff --git a/app/views/projects/new.html.erb b/app/views/projects/new.html.erb
@@ -1,18 +1,10 @@
<h1 class='title'>New Project</h1>
-<div class='fconstrained'>
-
<%= semantic_form_for(@new_project) do |f| %>
- <%= f.input :name, :as => :string, :label => 'Name' %>
+ <%= f.input :name, :as => :string, :label => 'Name', :input_html => { :autofocus => true } %>
<%= f.input :description, :as => :text, :input_html => { :class => 'project_description' } %>
- <%= f.input :included, :as => :text, :label => 'Default phone numbers to include', :input_html => { :class => 'project_includes' } %>
- <%= f.input :excluded, :as => :text, :label => 'Default phone numbers to exclude', :input_html => { :class => 'project_includes' } %>
-
<%= f.action :submit, :label => 'Create', :button_html => { :class => 'btn btn-large fbtn' } %>
-
<a class="btn btn-link" href="<%= projects_path %>"rel="tooltip" title="Return to projects"><i class="icon-return"></i>Cancel</a>
<% end %>
-</div>
-
<%= set_focus('project_name') %>
(DIR) diff --git a/app/views/providers/edit.html.erb b/app/views/providers/edit.html.erb
@@ -1,38 +1,13 @@
-<h1 class='title'>Edit Provider</h1>
+<h1 class='title'>Update Provider</h1>
-<%= form_for(@provider) do |f| %>
- <%= f.error_messages %>
- <p>
- <%= f.label :enabled %><br />
- <%= f.check_box :enabled %>
- </p>
- <p>
- <%= f.label :name %><br />
- <%= f.text_field :name %>
- </p>
- <p>
- <%= f.label :host %><br />
- <%= f.text_field :host %>
- </p>
- <p>
- <%= f.label :port %><br />
- <%= f.text_field :port %>
- </p>
- <p>
- <%= f.label :user %><br />
- <%= f.text_field :user %>
- </p>
- <p>
- <%= f.label :pass %><br />
- <%= f.text_field :pass %>
- </p>
- <p>
- <%= f.label :lines %><br />
- <%= f.text_field :lines %>
- </p>
- <p>
- <%= f.submit "Update" %>
- </p>
-<% end %>
+<%= semantic_form_for(@provider) do |f| %>
+ <%= f.input :name, :as => :string, :label => 'Name', :hint => 'A friendly name for this provider', :autofocus => true %>
+ <%= f.input :host, :as => :string, :label => 'IAX2 Server', :hint => 'The IP address or hostname of the IAX2 service' %>
+ <%= f.input :port, :as => :number, :label => 'IAX2 Port', :hint => 'The port of the IAX2 service' %>
+ <%= f.input :user, :as => :string, :label => 'Username' %>
+ <%= f.input :pass, :as => :string, :label => 'Password', :input_html => { :autocomplete => false } %>
+ <%= f.input :lines, :as => :number, :label => 'Maximum Lines', :hint => 'Maximum concurrent outbound lines' %>
-<%= link_to 'Back', providers_path %>
+ <%= f.action :submit, :label => 'Update', :button_html => { :class => 'btn btn-large fbtn' } %>
+ <a class="btn btn-link" href="<%= providers_path %>" rel="tooltip" title="Return to providers"><i class="icon-return"></i>Cancel</a>
+<% end %>
(DIR) diff --git a/app/views/providers/index.html.erb b/app/views/providers/index.html.erb
@@ -1,27 +1,29 @@
<% if @providers.length > 0 %>
<h1 class='title'>VoIP Providers (IAX)</h1>
+
+<%= will_paginate @providers, :renderer => BootstrapPagination::Rails %>
<table class='table table-striped table-bordered' width='90%'>
<tr>
<th>Active</th>
<th>Provider Name</th>
- <th>IAX Server</th>
- <th>IAX Port</th>
+ <th>IAX2 Server</th>
+ <th>IAX2 Port</th>
<th>Username</th>
<th>Lines</th>
<th>Actions</th>
</tr>
-<% for provider in @providers %>
+<% @providers.each do |provider| %>
<tr>
<td>
<i class="icon-<%= provider.enabled ? "ok" : "remove" %>"></i>
</td>
- <td><%=h provider.name %></td>
- <td><%=h provider.host %></td>
- <td><%=h provider.port %></td>
- <td><%=h provider.user %></td>
- <td><%=h provider.lines %></td>
+ <td><%= provider.name %></td>
+ <td><%= provider.host %></td>
+ <td><%= provider.port %></td>
+ <td><%= provider.user %></td>
+ <td><%= provider.lines %></td>
<td>
<a class="btn btn-mini" href="<%= edit_provider_path(provider) %>"rel="tooltip" title="Update Provider Information"><i class="icon-pencil"></i></a>
<a class="btn btn-mini" href="<%= provider_path(provider) %>" data-confirm="Remove this provider?" data-method="delete" rel="nofollow tooltip" title="Remove Provider"><i class="icon-trash"></i></a>
@@ -29,18 +31,10 @@
</tr>
<% end %>
</table>
-
-<br />
-
-
-<a class="btn" href="<%= new_provider_path %>"><i class="icon-plus"></i> Add Provider </a>
-
+<%= will_paginate @providers, :renderer => BootstrapPagination::Rails %>
<% else %>
-
<h1 class='title'>No Configured Providers</h1>
-<br/>
+<% end %>
+<br/>
<a class="btn" href="<%= new_provider_path %>"><i class="icon-plus"></i> Add Provider </a>
-
-
-<% end %>
(DIR) diff --git a/app/views/providers/new.html.erb b/app/views/providers/new.html.erb
@@ -1,34 +1,13 @@
<h1 class='title'>New Provider</h1>
-<%= form_for(@provider) do |f| %>
- <%= f.error_messages %>
- <p>
- <%= f.label :name, 'The nickname for this provider' %><br />
- <%= f.text_field :name %>
- </p>
- <p>
- <%= f.label :host, 'The IAX2 server name' %><br />
- <%= f.text_field :host %>
- </p>
- <p>
- <%= f.label :port, 'The IAX2 port (normally 4569)' %><br />
- <%= f.text_field :port, :value => 4569 %>
- </p>
- <p>
- <%= f.label :user, 'The username to access the provider' %><br />
- <%= f.text_field :user %>
- </p>
- <p>
- <%= f.label :pass, 'The password to access the provider' %><br />
- <%= f.text_field :pass %>
- </p>
- <p>
- <%= f.label :lines, 'The number of available outbound lines' %><br />
- <%= f.text_field :lines, :value => 1 %>
- </p>
- <p>
- <%= f.submit "Create" %>
- </p>
-<% end %>
+<%= semantic_form_for(@provider) do |f| %>
+ <%= f.input :name, :as => :string, :label => 'Name', :hint => 'A friendly name for this provider', :autofocus => true %>
+ <%= f.input :host, :as => :string, :label => 'IAX2 Server', :hint => 'The IP address or hostname of the IAX2 service' %>
+ <%= f.input :port, :as => :number, :label => 'IAX2 Port', :hint => 'The port of the IAX2 service' %>
+ <%= f.input :user, :as => :string, :label => 'Username' %>
+ <%= f.input :pass, :as => :password, :label => 'Password' %>
+ <%= f.input :lines, :as => :number, :label => 'Maximum Lines', :hint => 'Maximum concurrent outbound lines' %>
-<%= link_to 'Back', providers_path %>
+ <%= f.action :submit, :label => 'Create', :button_html => { :class => 'btn btn-large fbtn' } %>
+ <a class="btn btn-link" href="<%= providers_path %>" rel="tooltip" title="Return to providers"><i class="icon-return"></i>Cancel</a>
+<% end %>
(DIR) diff --git a/app/views/providers/show.html.erb b/app/views/providers/show.html.erb
@@ -1,38 +0,0 @@
-<h1 class='title'>View Provider</h1>
-<p>
- <b>Enabled:</b>
- <%=h @provider.enabled %>
-</p>
-<p>
- <b>Name:</b>
- <%=h @provider.name %>
-</p>
-
-<p>
- <b>Host:</b>
- <%=h @provider.host %>
-</p>
-
-<p>
- <b>Port:</b>
- <%=h @provider.port %>
-</p>
-
-<p>
- <b>User:</b>
- <%=h @provider.user %>
-</p>
-
-<p>
- <b>Pass:</b>
- ********
-</p>
-
-<p>
- <b>Lines:</b>
- <%=h @provider.lines %>
-</p>
-
-
-<%= link_to 'Edit', edit_provider_path(@provider) %> |
-<%= link_to 'Back', providers_path %>
(DIR) diff --git a/app/views/user_sessions/new.html.erb b/app/views/user_sessions/new.html.erb
@@ -6,7 +6,7 @@
<% if @user_session.errors.any? %>
<div class="alert"><%= @user_session.errors.full_messages.first %></div>
<% end %>
- <p><div class="login-label"><h3>Username</h3></div><%= f.text_field :login, :spellcheck => false %></p>
+ <p><div class="login-label"><h3>Username</h3></div><%= f.text_field :login, :spellcheck => false, :autofocus => true %></p>
<p><div class="login-label"><h3>Password</h3></div><%= f.password_field :password, :autocomplete => 'off' %></p>
<%= f.submit "Sign in", :class => "btn-login btn btn-warning" %>
<% end %>
(DIR) diff --git a/bin/export_audio.rb b/bin/export_audio.rb
@@ -12,16 +12,13 @@ $:.unshift(File.join(File.expand_path(File.dirname(base)), '..', 'lib'))
require 'warvox'
require 'fileutils'
-
+require 'yaml'
ENV['RAILS_ENV'] ||= 'production'
-
$:.unshift(File.join(File.expand_path(File.dirname(base)), '..'))
-require 'config/boot'
-require 'config/environment'
def usage
- $stderr.puts "Usage: #{$0} [Output Dir] [Job ID] <Type>"
+ $stderr.puts "Usage: #{$0} [Output Dir] [Project ID] <Line Type>"
exit
end
@@ -29,41 +26,66 @@ end
# Script
#
-dir = ARGV.shift
-job = ARGV.shift
-typ = ARGV.shift
+output = ARGV.shift
+project_id = ARGV.shift
+line_type = ARGV.shift
-if(job and job == "-h")
+if(output and output == "-h") or (! output)
usage()
end
-if(not job)
- $stderr.puts "Listing all available jobs"
- $stderr.puts "=========================="
- DialJob.all.each do |j|
- puts "#{j.id}\t#{j.started_at} --> #{j.completed_at}"
+require 'config/boot'
+require 'config/environment'
+
+if(not project_id)
+ $stderr.puts "Listing all projects"
+ $stderr.puts "===================="
+ Project.find(:all).each do |j|
+ puts "#{j.id}\t#{j.name}\t#{j.created_at}"
end
exit
end
-
-::FileUtils.mkdir_p(dir)
+FileUtils.mkdir_p(output)
begin
- cnt = 0
- DialResult.where(:dial_job_id => job.to_i).find_each do |r|
- next if not r.number
+ cond = { :project_id => project_id.to_i, :answered => true, :busy => false }
+ if line_type
+ cond[:line_type] = line_type.downcase
+ end
+
+ Call.where(cond).find(:order => :number) do |r|
m = r.media
- next if not m
- next if m.audio.to_s.length == 0
- out = ::File.join(dir, "#{r.number}.raw")
- ::File.open(out, "wb") do |fd|
- fd.write( m.audio )
+ if m and m.audio
+
+ ::File.open(File.join(output, "#{r.number}.raw"), "wb") do |fd|
+ fd.write(m.audio)
+ end
+
+ ::File.open(File.join(output, "#{r.number}.yml"), "wb") do |fd|
+ fd.write(r.to_yaml)
+ end
+
+ if m.mp3
+ ::File.open(File.join(output, "#{r.number}.mp3"), "wb") do |fd|
+ fd.write(m.mp3)
+ end
+ end
+
+ if m.png_big
+ ::File.open(File.join(output, "#{r.number}_wave.png"), "wb") do |fd|
+ fd.write(m.png_big)
+ end
+ end
+
+ if m.png_big_freq
+ ::File.open(File.join(output, "#{r.number}_freq.png"), "wb") do |fd|
+ fd.write(m.png_big_freq)
+ end
+ end
+
+ $stderr.puts "[*] Exported #{r.number}..."
+
end
- cnt += 1
end
- $stderr.puts "Wrote #{cnt} audio files to #{dir}"
-rescue ActiveRecord::RecordNotFound
- $stderr.puts "Job not found"
- exit
end
(DIR) diff --git a/bin/iaxrecord.rb b/bin/iaxrecord.rb
@@ -2,23 +2,31 @@
$:.unshift(::File.join(::File.dirname(__FILE__), "..", "lib"))
+
+def stop
+ exit(0)
+end
+
+trap("SIGINT") { stop() }
+trap("SIGTERM") { stop() }
+
require 'rubygems'
require "rex/proto/iax2"
require "optparse"
parser = OptionParser.new
-opts = {
- :recording_time => 52
+opts = {
+ :recording_time => 52
}
parser.banner = "Usage: #{$0} [options]"
parser.on("-s server") do |v|
opts[:server_host] = v
end
-
+
parser.on("-u user") do |v|
opts[:username] = v
-end
+end
parser.on("-p pass") do |v|
opts[:password] = v
@@ -26,34 +34,34 @@ end
parser.on("-o output") do |v|
opts[:output] = v
-end
+end
parser.on("-n number") do |v|
- opts[:called_number] = v
+ opts[:called_number] = v
end
parser.on("-c cid") do |v|
- opts[:caller_number] = v
-end
+ opts[:caller_number] = v
+end
parser.on("-l seconds") do |v|
opts[:recording_time] = v.to_i
-end
+end
parser.on("-d") do |v|
opts[:debugging] = true
-end
+end
parser.on("-h") do
$stderr.puts parser
exit(1)
end
-
+
parser.parse!(ARGV)
if not (opts[:server_host] and opts[:username] and opts[:password] and opts[:called_number] and opts[:output])
$stderr.puts parser
- exit(1)
+ exit(1)
end
@@ -61,7 +69,7 @@ cli = Rex::Proto::IAX2::Client.new(opts)
reg = cli.create_call
r = reg.register
-if not r
+if not r
$stderr.puts "ERROR: Unable to register with the IAX server"
exit(0)
end
@@ -75,7 +83,7 @@ end
begin
-::Timeout.timeout( opts[:recording_time] ) do
+::Timeout.timeout( opts[:recording_time] ) do
while (c.state != :hangup)
case c.state
when :ringing
@@ -102,4 +110,3 @@ end
fd.close
$stdout.puts "COMPLETED: BYTES=#{cnt} RINGTIME=#{c.ring_time} FILE=#{ ::File.expand_path( opts[:output] ) } BUSY=#{c.busy ? 1 : 0} FAIL=#{cnt == 0 ? 1 : 0}"
-
(DIR) diff --git a/bin/import_audio.rb b/bin/import_audio.rb
@@ -17,8 +17,6 @@ require 'fileutils'
ENV['RAILS_ENV'] ||= 'production'
$:.unshift(File.join(File.expand_path(File.dirname(base)), '..'))
-require 'config/boot'
-require 'config/environment'
def usage
$stderr.puts "Usage: #{$0} [Input Directory] <Project ID> <Provider ID>"
@@ -34,6 +32,8 @@ if (dir and dir =="-h") or (! dir)
usage()
end
+require 'config/boot'
+require 'config/environment'
project_id = ARGV.shift
provider_id = ARGV.shift
@@ -66,7 +66,7 @@ end
unless project
project = Project.create(
- :name => "Import from #{dir}",
+ :name => "Import from #{dir} at #{Time.now.utc.to_s}",
:created_by => "importer"
)
end
@@ -87,7 +87,6 @@ end
job = Job.new
job.project_id = project.id
-job.name = "Import Audio Job"
job.locked_by = "importer"
job.locked_at = Time.now.utc
job.started_at = Time.now.utc
@@ -95,7 +94,7 @@ job.created_by = "importer"
job.task = "import"
job.args = Marshal.dump({ :directory => dir, :project_id => project.id, :provider_id => provider.id })
job.status = "running"
-job.save
+job.save!
pct = 0
cnt = 0
(DIR) diff --git a/bin/warvox.rb b/bin/warvox.rb
@@ -12,10 +12,15 @@ while File.symlink?(base)
base = File.expand_path(File.readlink(base), File.dirname(base))
end
+$:.unshift(File.join(File.expand_path(File.dirname(base)), '..', 'lib'))
+
voxroot = File.expand_path(File.join(File.dirname(base), '..'))
voxserv = File.expand_path(File.join(File.expand_path(voxroot), 'script', 'rails'))
manager = File.expand_path(File.join(File.dirname(base), 'worker_manager.rb'))
+require 'warvox'
+
+
Dir.chdir(voxroot)
def stop
@@ -77,15 +82,22 @@ $stderr.puts "[*] Starting WarVOX on #{$browser_url}"
$stderr.puts ""
+WarVOX::Log.info("WarVOX is starting up...")
+
@manager_pid = Process.fork()
if not @manager_pid
- while (ARGV.shift) { }
+ while ARGV.shift do
+ end
load(manager)
exit(0)
end
+WarVOX::Log.info("Worker Manager has PID #{@manager_pid}")
+
@webserver_pid = $$
+WarVOX::Log.info("Web Server has PID #{@manager_pid}")
+
while(ARGV.length > 0); ARGV.shift; end
args.each {|arg| ARGV.push(arg) }
(DIR) diff --git a/config/routes.rb b/config/routes.rb
@@ -1,44 +1,46 @@
Web::Application.routes.draw do
- resources :projects
- resources :settings
- resources :providers
- resources :users
+
+
+
match "login" => "user_sessions#new", :as => "login"
match "logout" => "user_sessions#destroy", :as => "logout"
+
resources :user_sessions
match '/projects/:project_id/all' => 'projects#index', :as => :all_projects
- match '/projects/:project_id/jobs' => 'dial_jobs#index', :as => :dial_jobs
- match '/projects/:project_id/jobs/:id/run' => 'dial_jobs#run', :as => :run_dial_job
- match '/projects/:project_id/jobs/:id/stop' => 'dial_jobs#stop', :as => :stop_dial_job
- match '/projects/:project_id/jobs/new' => 'dial_jobs#new', :as => :new_dial_job
- delete '/projects/:project_id/jobs/:id' => 'dial_jobs#destroy'
- match '/projects/:project_id/results/' => 'dial_results#index', :as => :dial_results
- match '/projects/:project_id/results/:id/view' => 'dial_results#view', :as => :view_dial_result
- match '/projects/:project_id/results/:id/analyze' => 'dial_results#analyze', :as => :analyze_dial_result
- match '/projects/:project_id/results/:id/reanalyze' => 'dial_results#reanalyze', :as => :reanalyze_dial_result
- match '/projects/:project_id/results/:id/purge' => 'dial_results#purge', :as => :purge_dial_result
- delete '/projects/:project_id/results/:id' => 'dial_results#destroy'
+ match '/jobs/dial' => 'jobs#new_dialer', :as => :new_dialer_job
+ match '/jobs/dialer' => 'jobs#dialer', :as => :dialer_job
+ match '/jobs/analyze' => 'jobs#new_analyzer', :as => :new_analyzer_job
+ match '/jobs/analyzer' => 'jobs#analyzer', :as => :analyzer_job
+ match '/jobs/:id/stop' => 'jobs#stop', :as => :stop_job
+
+
+ match '/projects/:project_id/calls/' => 'calls#index', :as => :calls
+ match '/projects/:project_id/calls/:id/view' => 'calls#view', :as => :view_call
+ match '/projects/:project_id/calls/:id/analyze' => 'calls#analyze', :as => :analyze_call
+ match '/projects/:project_id/calls/:id/reanalyze' => 'calls#reanalyze', :as => :reanalyze_call
+ match '/projects/:project_id/calls/:id/purge' => 'calls#purge', :as => :purge_call
+ delete '/projects/:project_id/calls/:id' => 'calls#destroy'
match '/projects/:project_id/analyze' => 'analyze#index', :as => :analyze
match '/projects/:project_id/analyze/:id/resource/:result_id/:type' => 'analyze#resource', :as => :resource_analyze
match '/projects/:project_id/analyze/:id/view' => 'analyze#view', :as => :view_analyze
- match '/projects/:project_id/analyze/:dial_result_id/matches' => 'analyze#view_matches', :as => :view_matches
+ match '/projects/:project_id/analyze/:call_id/matches' => 'analyze#view_matches', :as => :view_matches
match '/projects/:project_id/analyze/:id/show' => 'analyze#show', :as => :show_analyze
- match '/projects/:project_id/providers' => 'providers#index', :as => :project_providers
+ resources :settings
+ resources :providers
+ resources :users
+ resources :projects
+ resources :jobs
- match '/projects/:project_id/about' => 'home#about', :as => :project_about
-
- match '/projects/:project_id/settings' => 'settings#index', :as => :project_settings
- match '/about' => 'home#about'
- match '/home/about' => 'home#about'
- match '/help' => 'home#help'
+ match '/about' => 'home#about', :as => :about
+ match '/help' => 'home#help', :as => :help
match '/check' => 'home#check', :as => :check
(DIR) diff --git a/db/migrate/20121228171549_initial_schema.rb b/db/migrate/20121228171549_initial_schema.rb
@@ -49,7 +49,6 @@ class InitialSchema < ActiveRecord::Migration
create_table "jobs" do |t|
t.timestamps
t.integer "project_id", :null => false
- t.string "name", :null => false
t.string "locked_by"
t.timestamp "locked_at"
t.timestamp "started_at"
@@ -73,6 +72,7 @@ class InitialSchema < ActiveRecord::Migration
create_table "line_attributes" do |t|
t.timestamps
t.integer "line_id", :null => false
+ t.integer "project_id", :null => false
t.text "name", :null => false
t.binary "value", :null => false
t.string "content_type", :default => "text"
@@ -104,6 +104,7 @@ class InitialSchema < ActiveRecord::Migration
create_table "call_media" do |t|
t.integer "call_id", :null => false
+ t.integer "project_id", :null => false
t.binary "audio"
t.binary "mp3"
t.binary "png_big"
(DIR) diff --git a/db/schema.rb b/db/schema.rb
@@ -17,6 +17,7 @@ ActiveRecord::Schema.define(:version => 20121228171549) do
create_table "call_media", :force => true do |t|
t.integer "call_id", :null => false
+ t.integer "project_id", :null => false
t.binary "audio"
t.binary "mp3"
t.binary "png_big"
@@ -35,6 +36,7 @@ ActiveRecord::Schema.define(:version => 20121228171549) do
t.integer "provider_id", :null => false
t.boolean "answered"
t.boolean "busy"
+ t.text "error"
t.integer "audio_length"
t.integer "ring_length"
t.text "caller_id"
@@ -51,7 +53,6 @@ ActiveRecord::Schema.define(:version => 20121228171549) do
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
t.integer "project_id", :null => false
- t.string "name", :null => false
t.string "locked_by"
t.datetime "locked_at"
t.datetime "started_at"
@@ -68,6 +69,7 @@ ActiveRecord::Schema.define(:version => 20121228171549) do
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
t.integer "line_id", :null => false
+ t.integer "project_id", :null => false
t.text "name", :null => false
t.binary "value", :null => false
t.string "content_type", :default => "text"
@@ -85,7 +87,7 @@ ActiveRecord::Schema.define(:version => 20121228171549) do
create_table "projects", :force => true do |t|
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
- t.text "name"
+ t.text "name", :null => false
t.text "description"
t.text "included"
t.text "excluded"
(DIR) diff --git a/lib/warvox.rb b/lib/warvox.rb
@@ -7,11 +7,14 @@ require 'warvox/config'
require 'warvox/jobs'
require 'warvox/phone'
require 'warvox/audio'
+require 'logger'
# Global configuration
module WarVOX
VERSION = '2.0.0-dev'
Base = File.expand_path(File.join(File.dirname(__FILE__), '..'))
Conf = File.expand_path(File.join(Base, 'config', 'warvox.conf'))
- JobManager = WarVOX::JobQueue.new
+ Log = Logger.new( WarVOX::Config.log_file )
+ Log.level = WarVOX::Config.log_level
+
end
(DIR) diff --git a/lib/warvox/config.rb b/lib/warvox/config.rb
@@ -83,6 +83,14 @@ module Config
File.expand_path(info['classifiers'].gsub('%BASE%', WarVOX::Base))
end
+ def self.log_file
+ STDOUT
+ end
+
+ def self.log_level
+ Logger::DEBUG
+ end
+
def self.classifiers_load
path = classifiers_path
sigs = []
(DIR) diff --git a/lib/warvox/jobs/dialer.rb b/lib/warvox/jobs/dialer.rb
@@ -145,7 +145,7 @@ class Dialer < Base
end
end
- :ActiveRecord::Base.connection_pool.with_connection do
+ ::ActiveRecord::Base.connection_pool.with_connection do
job = Job.find(@job_id)
if not job
raise RuntimeError, "The parent job is not available"
@@ -158,8 +158,8 @@ class Dialer < Base
res.provider_id = prov[:id]
res.answered = (fail == 0) ? true : false
res.busy = (busy == 1) ? true : false
- res.audio_seconds = (byte / 16000) # 8khz @ 16-bit
- res.ring_seconds = ring
+ res.audio_length = (byte / 16000) # 8khz @ 16-bit
+ res.ring_length = ring
res.caller_id = cid
res.save
@@ -211,7 +211,7 @@ class Dialer < Base
def update_progress(pct)
::ActiveRecord::Base.connection_pool.with_connection {
- Job.update({ :progress => pct }, { :id => @job_id })
+ Job.update_all({ :progress => pct }, { :id => @job_id })
}
end