Class: Phone::Pbx
- Inherits:
-
Object
- Object
- Phone::Pbx
- Includes:
- Singleton
- Defined in:
- app/services/phone/pbx.rb
Overview
Service object: pbx.
Defined Under Namespace
Classes: ApiError, PbxResponse
Constant Summary collapse
- QUEUES =
Queues.
{ tech_24x7: 1147, sales: 1142, tech1: 1143, tech2: 1148, operator: 1141, test: 1162, customer_contact: 1200, management: 1204, accounting: 1225, sales_homeowner: 1276, sales_commercial: 1277, sales_bg: 1278, sales_trade: 1279, sales_ecommerce: 1280 }.freeze
- STATUSES =
Statuses.
{ dnd: 11, available: 7 }.freeze
- UNIFIED_STATUS =
Unified status.
{ available: { pbx: 7, queue: true }, available_non_queue: { pbx: 7, queue: false }, dnd: { pbx: 11, queue: false }, not_working: { pbx: 9, queue: false } }.freeze
- SERVER_TIME_FORMAT =
Server time format.
"%Y-%m-%d %H:%M:%S"
Instance Attribute Summary collapse
-
#logger ⇒ Object
readonly
Returns the value of attribute logger.
-
#server_time_zone ⇒ Object
readonly
Returns the value of attribute server_time_zone.
-
#switchvox ⇒ Object
readonly
Returns the value of attribute switchvox.
-
#uri ⇒ Object
readonly
Returns the value of attribute uri.
Instance Method Summary collapse
-
#call_log_search(api_params = {}, &block) ⇒ Object
Call Log search.
-
#convert_to_obj(arg) ⇒ Object
Converts API response hashes to objects with method-style access.
- #current_calls ⇒ Object
-
#employee_places_call(employee, to_number, options = {}) ⇒ Object
This method extracts all the necessary information for an employee to make an outbound call to a number.
- #format_datetime(datetime) ⇒ Object
-
#get_presence_options_list(switchvox_account_id) ⇒ Object
Get list of presence statuses.
-
#get_presence_status(switchvox_account_id) ⇒ Object
Returns the presence status for one employee based on switchvox_account_id, will look like: 13:15:43", :id=>"11", :presence=>"dnd", :message=>nil, :sub_presence=>nil or nil will be returned if nothing was found or on error.
- #get_queue_members_status(queue_ids = nil) ⇒ Object
-
#get_queues_status(queue_ids = nil) ⇒ Object
Calls switchvox api and retrieve a hash of switchvox_account_id with queue_account_id and status in that queue.
-
#initialize(options = {}) ⇒ Pbx
constructor
A new instance of Pbx.
-
#member_queue_log_search(api_params = {}, &block) ⇒ Object
QueueMemberLogs.search.
- #missed_call_search(missed_call_uniqueid) ⇒ Object
- #parse_datetime(datetime_string) ⇒ Object
-
#place_call(from_number, to_number, caller_account_id, options = {}) ⇒ Object
Generic method wrapper to place call through switchvox (click to call style) http://developers.digium.com/switchvox/wiki/index.php/Switchvox.users.call.
- #prepare_json_payload(hash) ⇒ Object
-
#process_request(api_method, api_params, block = nil) ⇒ Object
Wrapper method to call the switchvox api and paginate results, calls block with each page.
- #prune_account_ids(account_ids) ⇒ Object
- #queue_log_search(api_params = {}, &block) ⇒ Object
-
#report_api_failure(api_method, http_status: nil, body_snippet: nil, cause: nil) ⇒ Object
Report a Switchvox-side failure to AppSignal so it surfaces as an incident rather than disappearing into the logs.
-
#retrieve_extension_account_id(pbx_extension) ⇒ Object
For a given extension code (e.g 800) retrieves the associated switchvox account id via api call.
-
#retrieve_extension_info(pbx_extension = nil, options = {}) ⇒ Object
Wrapper for switchvox.extensions.search.
- #start_packet_capture(duration) ⇒ Object
- #stringify_values(hash) ⇒ Object
- #switchvox_request(api_method, options = {}, ignore_error_codes = []) ⇒ Object
-
#update_presence_status(account_id, presence_option_id) ⇒ Object
Updates the PBX Presence flag.
-
#update_queue_status(account_id:, log_in_queue:, call_queue_account_ids: []) ⇒ Object
Account id: the switchvox account id of the user log in queue: true to login, false to log out call_queue_account_id: an optional queue account id to sign in/out of, default to all.
-
#update_unified_presence(account_id:, status_id:, log_in_queue: false, call_queue_account_ids: []) ⇒ Object
Synchronized status update using a unified symbol map.
- #valid_sip_account_ids ⇒ Object
Constructor Details
#initialize(options = {}) ⇒ Pbx
Returns a new instance of Pbx.
55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 |
# File 'app/services/phone/pbx.rb', line 55 def initialize( = {}) @logger = [:logger] || Rails.logger host = Heatwave::Configuration.fetch(:switchvox, :host) username = Heatwave::Configuration.fetch(:switchvox, :username) password = Heatwave::Configuration.fetch(:switchvox, :password) # Validate credentials are present to fail fast with helpful error raise ArgumentError, 'Switchvox host not configured. Add switchvox.host to Rails credentials.' if host.blank? raise ArgumentError, 'Switchvox credentials not configured. Add switchvox.username and switchvox.password to Rails credentials.' if username.blank? || password.blank? @uri = "https://#{host}/json" @domain = "https://#{host}" # SSL verification off — Switchvox PBX uses a self-signed cert. @client = Faraday.new(ssl: { verify: false }) do |f| f.request :authorization, :basic, username, password f.adapter Faraday.default_adapter end @server_time_zone = ActiveSupport::TimeZone.new("Central Time (US & Canada)") end |
Instance Attribute Details
#logger ⇒ Object (readonly)
Returns the value of attribute logger.
53 54 55 |
# File 'app/services/phone/pbx.rb', line 53 def logger @logger end |
#server_time_zone ⇒ Object (readonly)
Returns the value of attribute server_time_zone.
53 54 55 |
# File 'app/services/phone/pbx.rb', line 53 def server_time_zone @server_time_zone end |
#switchvox ⇒ Object (readonly)
Returns the value of attribute switchvox.
53 54 55 |
# File 'app/services/phone/pbx.rb', line 53 def switchvox @switchvox end |
#uri ⇒ Object (readonly)
Returns the value of attribute uri.
53 54 55 |
# File 'app/services/phone/pbx.rb', line 53 def uri @uri end |
Instance Method Details
#call_log_search(api_params = {}, &block) ⇒ Object
Call Log search
130 131 132 133 134 135 136 137 138 |
# File 'app/services/phone/pbx.rb', line 130 def call_log_search(api_params = {}, &block) api_params['start_date'] ||= Time.current.beginning_of_day api_params['end_date'] ||= Time.current.end_of_day api_params['start_date'] = format_datetime(api_params['start_date']) api_params['end_date'] = format_datetime(api_params['end_date']) api_params['sort_field'] = 'start_time' api_params['sort_direction'] = 'ASC' process_request "switchvox.callLogs.search", api_params, block end |
#convert_to_obj(arg) ⇒ Object
Converts API response hashes to objects with method-style access.
NOTE: OpenStruct is intentionally kept here because API responses have dynamic
structures that vary by endpoint. Data.define requires known members at compile time.
487 488 489 490 491 492 493 494 495 496 |
# File 'app/services/phone/pbx.rb', line 487 def convert_to_obj(arg) if arg.is_a? Hash arg.each { |k, v| arg[k] = convert_to_obj(v) } OpenStruct.new(arg) elsif arg.is_a? Array arg.map! { |v| convert_to_obj(v) } else arg end end |
#current_calls ⇒ Object
201 202 203 204 205 206 207 208 209 210 |
# File 'app/services/phone/pbx.rb', line 201 def current_calls result = switchvox_request("switchvox.currentCalls.getList", {}) return [] if result.is_a?(PbxResponse) calls = [result.current_calls&.current_call].flatten.compact calls.map do |v| v.start_time = parse_datetime(v.start_time) v.marshal_dump end end |
#employee_places_call(employee, to_number, options = {}) ⇒ Object
This method extracts all the necessary information for an employee to
make an outbound call to a number
116 117 118 119 120 121 122 123 124 125 126 127 |
# File 'app/services/phone/pbx.rb', line 116 def employee_places_call(employee, to_number, = {}) caller_account_id = employee.employee_phone_status.switchvox_account_id [:caller_id_name] ||= employee.full_name raise "Employee is not setup with switchvox account id" if caller_account_id.blank? pbx_extension = employee.pbx_extension raise "Employee is not setup with pbx extension" if pbx_extension.blank? pbx = Phone::Pbx.instance pbx.place_call(pbx_extension, to_number, caller_account_id, ) end |
#format_datetime(datetime) ⇒ Object
77 78 79 |
# File 'app/services/phone/pbx.rb', line 77 def format_datetime(datetime) datetime.in_time_zone(server_time_zone).strftime(SERVER_TIME_FORMAT) end |
#get_presence_options_list(switchvox_account_id) ⇒ Object
Get list of presence statuses
363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 |
# File 'app/services/phone/pbx.rb', line 363 def (switchvox_account_id) api_params = { account_id: switchvox_account_id }.with_indifferent_access # 84711 = "That account_id is invalid" — typically a stale # `switchvox_account_id` on an EmployeePhoneStatus row (former employee, # deprovisioned Switchvox account, or garbage test data). The graceful- # degrade-to-`[]` path below already handles it correctly; suppress the # AppSignal incident so the SyncPhoneStatusWorker (every 10 minutes per # phone-enabled employee) doesn't fire one notification per stale row # per tick. Surfaced as incident #5971 (~92 occurrences/24h). result = switchvox_request("switchvox.users.presence.options.getList", api_params, ['84711']) # Return empty array on error (PbxResponse) or if errors present in API response if result.is_a?(PbxResponse) || result.try(:[], :errors).present? [] else [result..presence_option].flatten.map(&:marshal_dump) end end |
#get_presence_status(switchvox_account_id) ⇒ Object
Returns the presence status for one employee based on switchvox_account_id, will look like:
13:15:43", :id=>"11", :presence=>"dnd", :message=>nil, :sub_presence=>nil
or nil will be returned if nothing was found or on error
225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 |
# File 'app/services/phone/pbx.rb', line 225 def get_presence_status(switchvox_account_id) api_params = { account_id: switchvox_account_id }.with_indifferent_access # 10014 = Switchvox rejecting the `account_id` parameter value as invalid. # It belongs to Switchvox's generic request-validation family (neighbours # 10011 "missing required parameter" / 10013 "invalid number of parameters"; # genuine server-side faults are 12003 / 99999, and transport failures arrive # as non-2xx HTTP) — i.e. the value we sent was bad, not a Switchvox outage. # It fires when an EmployeePhoneStatus carries a blank/stale # `switchvox_account_id` (employee not provisioned for click-to-call, # deprovisioned account, test data) — the same class of problem the sibling # presence.options.getList path already silences via ['84711']. Both callers # degrade gracefully (Crm::OutboundCallsController#create falls through to its # "set your status" branch; #pull_presence returns :api_call_failure), so # reporting it to AppSignal is pure noise. Suppress only this code so a real # Switchvox-side failure (any other fault, non-2xx, or timeout) still surfaces. # Surfaced as incident #5980 (2 occurrences/7d, low volume). result = switchvox_request("switchvox.users.presence.getInfo", api_params, ['10014']) return nil if result.is_a?(PbxResponse) result.presence end |
#get_queue_members_status(queue_ids = nil) ⇒ Object
277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 |
# File 'app/services/phone/pbx.rb', line 277 def get_queue_members_status(queue_ids = nil) results_hsh = {} queues = QUEUES queues = queues.select { |_k, v| queue_ids.include?(v) } if queue_ids.present? queues.each do |queue_name, queue_id| logger.info " Retrieving queue status for queue id: #{queue_id} #{queue_name}" api_params = { account_id: queue_id }.with_indifferent_access result = switchvox_request("switchvox.callQueues.getCurrentStatus", api_params) next if result.is_a?(PbxResponse) next if result.call_queue&.queue_members&.queue_member.blank? queue_members = result.call_queue.queue_members.queue_member queue_name = result.call_queue.call_queue_name queue_strategy = result.call_queue.strategy results_hsh[queue_id] ||= {} results_hsh[queue_id]['name'] = queue_name results_hsh[queue_id]['strategy'] = queue_strategy queue_members.each do |member| results_hsh[queue_id]['members'] ||= [] results_hsh[queue_id]['members'] << member.fullname end end results_hsh end |
#get_queues_status(queue_ids = nil) ⇒ Object
Calls switchvox api and retrieve a hash of switchvox_account_id with queue_account_id and status in that queue
248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 |
# File 'app/services/phone/pbx.rb', line 248 def get_queues_status(queue_ids = nil) results_hsh = {} queues = QUEUES queues = queues.select { |_k, v| queue_ids.include?(v) } if queue_ids.present? queues.each do |queue_name, queue_id| logger.info " Retrieving queue status for queue id: #{queue_id} #{queue_name}" api_params = { account_id: queue_id }.with_indifferent_access result = switchvox_request("switchvox.callQueues.getCurrentStatus", api_params) next if result.is_a?(PbxResponse) next if result.call_queue&.queue_members&.queue_member.blank? queue_members = result.call_queue.queue_members.queue_member # queue_name from API response available via result.call_queue.call_queue_name if needed if queue_members.is_a?(Array) queue_members.each do |member| switchvox_account_id = member.account_id.to_i results_hsh[switchvox_account_id] ||= {} results_hsh[switchvox_account_id][queue_id] = member.logged_in_status end else switchvox_account_id = queue_members.account_id.to_i results_hsh[switchvox_account_id] ||= {} results_hsh[switchvox_account_id][queue_id] = queue_members.logged_in_status end end results_hsh end |
#member_queue_log_search(api_params = {}, &block) ⇒ Object
QueueMemberLogs.search
165 166 167 168 169 170 171 172 173 174 175 176 177 |
# File 'app/services/phone/pbx.rb', line 165 def member_queue_log_search(api_params = {}, &block) api_params = api_params.with_indifferent_access api_params['start_date'] ||= Time.current.beginning_of_day api_params['end_date'] ||= Time.current.end_of_day api_params['start_date'] = format_datetime(api_params['start_date']) api_params['end_date'] = format_datetime(api_params['end_date']) api_params['member_account_ids'] ||= valid_sip_account_ids api_params['sort_field'] = 'start_time' api_params['sort_direction'] = 'ASC' api_params['call_types'] = %w[missed_calls completed_calls] process_request "switchvox.callQueueMemberLogs.search", api_params, block end |
#missed_call_search(missed_call_uniqueid) ⇒ Object
140 141 142 143 144 145 146 |
# File 'app/services/phone/pbx.rb', line 140 def missed_call_search(missed_call_uniqueid) api_params = {} api_params['uniqueid'] = missed_call_uniqueid api_params['sort_field'] = 'missed_time' api_params['sort_direction'] = 'ASC' process_request "switchvox.callQueueMissedCalls.getList", api_params end |
#parse_datetime(datetime_string) ⇒ Object
81 82 83 |
# File 'app/services/phone/pbx.rb', line 81 def parse_datetime(datetime_string) server_time_zone.parse(datetime_string) end |
#place_call(from_number, to_number, caller_account_id, options = {}) ⇒ Object
Generic method wrapper to place call through switchvox (click to call style)
http://developers.digium.com/switchvox/wiki/index.php/Switchvox.users.call
87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 |
# File 'app/services/phone/pbx.rb', line 87 def place_call(from_number, to_number, caller_account_id, = {}) caller_id_name = [:caller_id_name] || "WARMLYYOURS" vars = [] vars << "party_id=#{[:party_id]}" if [:party_id].present? vars << "activity_id=#{[:activity_id]}" if [:activity_id].present? if from_number.to_s.size > 3 && (pf = PhoneNumber.parse(from_number)) from_number = pf.dial_string end ignore_user_call_rules = [:ignore_user_call_rules].to_b ? 1 : 0 if to_number.to_s.size > 3 && (pt = PhoneNumber.parse(to_number)) to_number = pt.dial_string end api_params = { caller_id_name: caller_id_name, dial_as_account_id: caller_account_id, dial_first: from_number, dial_second: to_number, timeout: 60, ignore_user_api_settings: 0, ignore_user_call_rules: ignore_user_call_rules, # This might be useful timeout_second_call: 60, auto_answer: 1, variables: vars }.with_indifferent_access switchvox_request("switchvox.call", api_params) end |
#prepare_json_payload(hash) ⇒ Object
498 499 500 501 502 503 |
# File 'app/services/phone/pbx.rb', line 498 def prepare_json_payload(hash) hash_string = stringify_values(hash) json = ActiveSupport::JSON.encode(hash_string) json.gsub!(/^\s{8}/, '') json end |
#process_request(api_method, api_params, block = nil) ⇒ Object
Wrapper method to call the switchvox api and paginate results, calls block with each page.
api_params is a hash, :items_per_page defaults to 100, :page_number defaults to 1
383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 |
# File 'app/services/phone/pbx.rb', line 383 def process_request(api_method, api_params, block = nil) logger.debug("Starting switchvox request", api_method: api_method) api_params['items_per_page'] ||= 100 api_params['page_number'] ||= 1 results = [] total_pages = nil total_items = nil loop do logger.debug("Starting switchvox paginated request", api_method: api_method, page: api_params['page_number'], total_pages: total_pages) page_results = switchvox_request(api_method, api_params) break if page_results.is_a?(PbxResponse) # Error occurred break if page_results&.calls&.call.blank? total_pages ||= page_results.calls.total_pages.to_i total_items ||= page_results.calls.total_items.to_i new_results = [page_results.calls.call].flatten if block block.call(new_results) else results += new_results end api_params['page_number'] += 1 end if block total_items else results end end |
#prune_account_ids(account_ids) ⇒ Object
218 219 220 |
# File 'app/services/phone/pbx.rb', line 218 def prune_account_ids(account_ids) account_ids & valid_sip_account_ids end |
#queue_log_search(api_params = {}, &block) ⇒ Object
150 151 152 153 154 155 156 157 158 159 160 161 162 |
# File 'app/services/phone/pbx.rb', line 150 def queue_log_search(api_params = {}, &block) api_params = api_params.with_indifferent_access api_params['start_date'] ||= Time.current.beginning_of_day api_params['end_date'] ||= Time.current.end_of_day api_params['start_date'] = format_datetime(api_params['start_date']) api_params['end_date'] = format_datetime(api_params['end_date']) api_params['queue_account_ids'] = QUEUES.values api_params['call_types'] = %w[completed_calls abandoned_calls redirected_calls] api_params['sort_field'] = 'start_time' api_params['sort_direction'] = 'ASC' process_request "switchvox.callQueueLogs.search", api_params, block end |
#report_api_failure(api_method, http_status: nil, body_snippet: nil, cause: nil) ⇒ Object
Report a Switchvox-side failure to AppSignal so it surfaces as an incident
rather than disappearing into the logs. Class+method-level message keeps
related failures grouped into a single incident during a sustained outage
(AppSignal dedupes by class+message).
471 472 473 474 475 476 477 478 479 480 481 482 |
# File 'app/services/phone/pbx.rb', line 471 def report_api_failure(api_method, http_status: nil, body_snippet: nil, cause: nil) error = ApiError.new( api_method: api_method, http_status: http_status, body_snippet: body_snippet, cause_message: cause&. ) ErrorReporting.error(error, source: :background) rescue StandardError => e # Never let the reporter itself break a worker — log and move on. logger.warn "[pbx:#{api_method}] ErrorReporting itself failed: #{e.class}: #{e.}" end |
#retrieve_extension_account_id(pbx_extension) ⇒ Object
For a given extension code (e.g 800) retrieves the associated switchvox account id
via api call
214 215 216 |
# File 'app/services/phone/pbx.rb', line 214 def retrieve_extension_account_id(pbx_extension) retrieve_extension_info(pbx_extension).account_id.to_i end |
#retrieve_extension_info(pbx_extension = nil, options = {}) ⇒ Object
Wrapper for switchvox.extensions.search
180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 |
# File 'app/services/phone/pbx.rb', line 180 def retrieve_extension_info(pbx_extension = nil, = {}) api_params = {}.with_indifferent_access if pbx_extension api_params[:min_extension] = pbx_extension api_params[:max_extension] = pbx_extension end api_params[:min_extension] ||= 800 api_params[:max_extension] ||= 899 api_params[:extension_types] = [:extension_types] || ['sip'] result = switchvox_request("switchvox.extensions.search", api_params) return [] if result.is_a?(PbxResponse) result.extensions&.extension || [] end |
#start_packet_capture(duration) ⇒ Object
324 325 326 327 328 329 330 331 332 333 334 |
# File 'app/services/phone/pbx.rb', line 324 def start_packet_capture(duration) result = switchvox_request("switchvox.debug.pcap.startSession", duration) = "Starting packet capture session with duration #{duration}" if result.try(:success) logger.info true else logger.error false end end |
#stringify_values(hash) ⇒ Object
505 506 507 508 509 510 511 512 513 514 515 516 517 |
# File 'app/services/phone/pbx.rb', line 505 def stringify_values(hash) new_hsh = {} hash.each do |key, value| new_hsh[key.to_s] = if value.is_a?(Array) value.map(&:to_s) elsif value.is_a?(Hash) stringify_values(value) else value.to_s end end new_hsh end |
#switchvox_request(api_method, options = {}, ignore_error_codes = []) ⇒ Object
415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 |
# File 'app/services/phone/pbx.rb', line 415 def switchvox_request(api_method, = {}, ignore_error_codes = []) logger.debug("[pbx] Initiated", api_method: api_method) body_hsh = { request: { method: api_method, parameters: } } body_json = prepare_json_payload(body_hsh) logger.info "[pbx:#{api_method}] Raw request: #{body_json}" begin res = @client.post(@uri, body_json, 'Content-Type' => 'application/json') response_body = res.body # For now just log in info, later switch to debug logger.info "[pbx:#{api_method}] Raw response: #{response_body}" # Distinguish network-acl rejection (HTTP 403 + Switchvox's main/http_forbidden.html # landing page) and other 4xx/5xx from real JSON. Faraday isn't configured to # raise on non-2xx, so without this check the next line tries to Oj.load HTML # and we lose the actual signal in the JSON::ParserError. unless (200..299).cover?(res.status) report_api_failure(api_method, http_status: res.status, body_snippet: response_body.to_s[0, 400]) return PbxResponse.new(success: false, errors: ["PBX HTTP #{res.status}. body=#{response_body.to_s[0, 200]}"]) end parsed_response = Oj.load(response_body) obj = convert_to_obj(parsed_response["response"]) if obj.result obj.result elsif obj.errors && !(ignore_error_codes.present? && ignore_error_codes.include?(obj.errors.error.code)) logger.error "[pbx:#{api_method}] Error returned #{obj.errors.inspect}" report_api_failure(api_method, http_status: res.status, body_snippet: "switchvox_error=#{obj.errors.inspect[0, 300]}") PbxResponse.new(success: false, errors: obj.errors) else PbxResponse.new(success: true, errors: nil) end rescue Oj::ParseError, JSON::ParserError => e logger.error "[pbx:#{api_method}] JSON parse error: #{e.class} - #{e.}" report_api_failure(api_method, http_status: res&.status, body_snippet: "json_parse=#{e.[0, 200]}", cause: e) PbxResponse.new(success: false, errors: ["Malformed JSON response. #{e.class}: #{e.}"]) rescue Errno::ECONNREFUSED, Errno::EHOSTUNREACH, Errno::ENETUNREACH, SocketError, Faraday::ConnectionFailed => e logger.error "[pbx:#{api_method}] Connection error: #{e.class} - #{e.}" report_api_failure(api_method, body_snippet: "connection_error=#{e.class}", cause: e) PbxResponse.new(success: false, errors: ["PBX connection error. #{e.class}: #{e.}"]) rescue Net::ReadTimeout, Net::OpenTimeout, Faraday::TimeoutError => e logger.error "[pbx:#{api_method}] Timeout error: #{e.class} - #{e.}" report_api_failure(api_method, body_snippet: "timeout=#{e.class}", cause: e) PbxResponse.new(success: false, errors: ["PBX timeout. #{e.class}: #{e.}"]) end end |
#update_presence_status(account_id, presence_option_id) ⇒ Object
Updates the PBX Presence flag
310 311 312 313 314 315 316 317 318 319 320 321 322 |
# File 'app/services/phone/pbx.rb', line 310 def update_presence_status(account_id, presence_option_id) api_params = { presence_option_id: presence_option_id, account_id: account_id }.with_indifferent_access result = switchvox_request("switchvox.users.presence.update", api_params) = "Update presence status for account_id #{account_id} with api_params #{api_params} returned #{result.inspect}" if result.try(:success) logger.info true else logger.error false end end |
#update_queue_status(account_id:, log_in_queue:, call_queue_account_ids: []) ⇒ Object
Account id: the switchvox account id of the user
log in queue: true to login, false to log out
call_queue_account_id: an optional queue account id to sign in/out of, default to all
339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 |
# File 'app/services/phone/pbx.rb', line 339 def update_queue_status(account_id:, log_in_queue:, call_queue_account_ids: []) if call_queue_account_ids.blank? logger.error "Update queue status for account_id #{account_id} not possible without call_queue_account_ids specified" return false end cmd = log_in_queue ? 'login' : 'logout' # Log in/out of each queue call_queue_account_ids.each do |call_queue_account_id| api_params = { call_queue_account_id: call_queue_account_id, account_id: account_id }.with_indifferent_access # Ignore error code 78956 which will be returned if user is already logged out result = switchvox_request("switchvox.users.callQueues.#{cmd}", api_params, ['78956']) = "Update queue status for account_id #{account_id} with api_params #{api_params} returned #{result.inspect}" if result.try(:success) logger.info else logger.error end end end |
#update_unified_presence(account_id:, status_id:, log_in_queue: false, call_queue_account_ids: []) ⇒ Object
Synchronized status update using a unified symbol map
304 305 306 307 |
# File 'app/services/phone/pbx.rb', line 304 def update_unified_presence(account_id:, status_id:, log_in_queue: false, call_queue_account_ids: []) update_queue_status account_id: account_id, log_in_queue: log_in_queue, call_queue_account_ids: call_queue_account_ids if call_queue_account_ids.present? update_presence_status account_id, status_id end |
#valid_sip_account_ids ⇒ Object
197 198 199 |
# File 'app/services/phone/pbx.rb', line 197 def valid_sip_account_ids retrieve_extension_info.map(&:account_id).map(&:to_i).sort end |