| job.rb - warvox - VoIP based wardialing tool, forked from rapid7/warvox. | |
| git clone git://jay.scot/warvox | |
| Log | |
| Files | |
| Refs | |
| README | |
| --- | |
| job.rb (5144B) | |
| --- | |
| 1 # == Schema Information | |
| 2 # | |
| 3 # Table name: jobs | |
| 4 # | |
| 5 # id :integer not null, primary key | |
| 6 # created_at :datetime | |
| 7 # updated_at :datetime | |
| 8 # project_id :integer not null | |
| 9 # locked_by :string(255) | |
| 10 # locked_at :datetime | |
| 11 # started_at :datetime | |
| 12 # completed_at :datetime | |
| 13 # created_by :string(255) | |
| 14 # task :string(255) not null | |
| 15 # args :binary | |
| 16 # status :string(255) | |
| 17 # error :text | |
| 18 # progress :integer default(0) | |
| 19 # | |
| 20 | |
| 21 class Job < ApplicationRecord | |
| 22 | |
| 23 reportable :hourly, aggregation: :count, grouping: :hour, date_column:… | |
| 24 reportable :daily, aggregation: :count, grouping: :day, date_column: :… | |
| 25 reportable :weeky, aggregation: :count, grouping: :week, date_column: … | |
| 26 reportable :monthly, aggregation: :count, grouping: :month, date_colum… | |
| 27 | |
| 28 class JobValidator < ActiveModel::Validator | |
| 29 def validate(record) | |
| 30 case record.task | |
| 31 when 'dialer' | |
| 32 | |
| 33 cracked_range = WarVOX::Phone.crack_mask(record.range) rescue [] | |
| 34 unless cracked_range.length > 0 | |
| 35 record.errors[:range] << "No valid ranges were specified" | |
| 36 end | |
| 37 | |
| 38 cracked_mask = WarVOX::Phone.crack_mask(record.cid_mask) rescue … | |
| 39 unless cracked_mask.length > 0 | |
| 40 record.errors[:cid_mask] << "No valid Caller ID mask was speci… | |
| 41 end | |
| 42 | |
| 43 unless record.seconds.to_i > 0 and record.seconds.to_i < 300 | |
| 44 record.errors[:seconds] << "Seconds should be between 1 and 30… | |
| 45 end | |
| 46 | |
| 47 unless record.lines.to_i > 0 and record.lines.to_i < 10000 | |
| 48 record.errors[:lines] << "Lines should be between 1 and 10,000" | |
| 49 end | |
| 50 | |
| 51 $stderr.puts "Errors: #{record.errors.map{|x| x.inspect}}" | |
| 52 | |
| 53 when 'analysis' | |
| 54 unless ['calls', 'job', 'project', 'global'].include?(record.sco… | |
| 55 record.errors[:scope] << "Scope must be calls, job, project, o… | |
| 56 end | |
| 57 if record.scope == "job" and Job.where(id: record.target_id.to_i… | |
| 58 record.errors[:job_id] << "The job_id is not valid" | |
| 59 end | |
| 60 if record.scope == "project" and Project.where(id: record.target… | |
| 61 record.errors[:project_id] << "The project_id is not valid" | |
| 62 end | |
| 63 if record.scope == "calls" and (record.target_ids.nil? or record… | |
| 64 record.errors[:target_ids] << "The target_ids list is empty" | |
| 65 end | |
| 66 when 'import' | |
| 67 else | |
| 68 record.errors[:base] << "Invalid task specified" | |
| 69 end | |
| 70 end | |
| 71 end | |
| 72 | |
| 73 # XXX: Purging a single job will be slow, but deleting the project is … | |
| 74 has_many :calls, dependent: :destroy | |
| 75 | |
| 76 belongs_to :project | |
| 77 | |
| 78 validates_presence_of :project_id | |
| 79 | |
| 80 # Allow the base Job class to be used for Dial Jobs | |
| 81 attr_accessor :range | |
| 82 attr_accessor :range_file | |
| 83 attr_accessor :lines | |
| 84 attr_accessor :seconds | |
| 85 attr_accessor :cid_mask | |
| 86 | |
| 87 attr_accessor :scope | |
| 88 attr_accessor :force | |
| 89 attr_accessor :target_id | |
| 90 attr_accessor :target_ids | |
| 91 | |
| 92 validates_with JobValidator | |
| 93 | |
| 94 def stop | |
| 95 self.class.where(id: self.id).update_all(status: 'cancelled') | |
| 96 end | |
| 97 | |
| 98 def update_progress(pct) | |
| 99 if pct >= 100 | |
| 100 self.class.where(id: self.id).update_all(progress: pct, completed_… | |
| 101 else | |
| 102 self.class.where(id: self.id).update_all(progress: pct) | |
| 103 end | |
| 104 end | |
| 105 | |
| 106 def details | |
| 107 Marshal.load(self.args) rescue {} | |
| 108 end | |
| 109 | |
| 110 def schedule | |
| 111 case task | |
| 112 when 'dialer' | |
| 113 self.status = 'submitted' | |
| 114 self.args = Marshal.dump({ | |
| 115 range: self.range, | |
| 116 lines: self.lines.to_i, | |
| 117 seconds: self.seconds.to_i, | |
| 118 cid_mask: self.cid_mask | |
| 119 }) | |
| 120 | |
| 121 return self.save | |
| 122 | |
| 123 when 'analysis' | |
| 124 self.status = 'submitted' | |
| 125 d = { | |
| 126 scope: self.scope, # job / proj… | |
| 127 force: !!(self.force), # true / fal… | |
| 128 target_id: self.target_id.to_i, # job_id… | |
| 129 target_ids: (self.target_ids || []).map{… | |
| 130 } | |
| 131 $stderr.puts d.inspect | |
| 132 | |
| 133 self.args = Marshal.dump({ | |
| 134 scope: self.scope, # job / project/ global | |
| 135 force: !!(self.force), # true / false | |
| 136 target_id: self.target_id.to_i, # job_id or project_id or nil | |
| 137 target_ids: (self.target_ids || []).map{|x| x.to_i } | |
| 138 }) | |
| 139 return self.save | |
| 140 else | |
| 141 raise ::RuntimeError, "Unsupported Job type" | |
| 142 end | |
| 143 end | |
| 144 | |
| 145 def rate | |
| 146 tend = (self.completed_at || Time.now) | |
| 147 tlen = tend.to_f - self.started_at.to_f | |
| 148 | |
| 149 case self.task | |
| 150 when 'dialer' | |
| 151 Call.where('job_id = ?', self.id).count() / tlen | |
| 152 when 'analysis' | |
| 153 Call.where('job_id = ? AND analysis_completed_at > ? AND analysis_… | |
| 154 when 'import' | |
| 155 Call.where('job_id = ?', self.id).count() / tlen | |
| 156 else | |
| 157 0 | |
| 158 end | |
| 159 end | |
| 160 | |
| 161 end |