123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254 |
- # Copyright (C) 2012-2024 Zammad Foundation, https://zammad-foundation.org/
- class Cti::Driver::Base
- def initialize(params = {})
- @config = params[:config] || config
- @params = mapping(params[:params])
- end
- def mapping(params)
- params
- end
- def config
- {}
- end
- def process
- # validate directions
- result = direction_check
- return result if result.present?
- # reject inbound call
- result = reject_check
- if result.present? && result[:action] == 'reject'
- @params['comment'] = 'reject, busy'
- if @params['user'].present?
- @params['comment'] = "#{@params['user']} -> reject, busy"
- end
- Cti::Log.process(@params)
- return result
- end
- # set caller ID of outbound call
- result = caller_id_rewrite(@params)
- if result.present? && result[:action] == 'set_caller_id'
- @params['from'] = result[:params][:from_caller_id]
- Cti::Log.process(@params)
- return result
- end
- log = Cti::Log.process(@params)
- if log.present?
- # push new call notification
- push_incoming_call(log)
- # open screen if call got answered
- push_open_ticket_screen(log)
- end
- result || {}
- end
- def direction_check
- # check possible directions
- if @params['direction'] != 'in' && @params['direction'] != 'out'
- return {
- action: 'invalid_direction',
- params: @params
- }
- end
- nil
- end
- def reject_check
- return nil if @params['direction'] != 'in'
- return nil if @params['event'] != 'newCall'
- config_inbound = @config[:inbound] || {}
- block_caller_ids = config_inbound[:block_caller_ids] || []
- # check if call needs to be blocked
- block_caller_ids.each do |item|
- next if item[:caller_id] != @params['from']
- return {
- action: 'reject'
- }
- end
- nil
- end
- def caller_id_rewrite(params)
- return nil if params['direction'] != 'out'
- return nil if params['event'] != 'newCall'
- config_outbound = @config[:outbound]
- routing_table = nil
- default_caller_id = nil
- if config_outbound.present?
- routing_table = config_outbound[:routing_table]
- default_caller_id = config_outbound[:default_caller_id]
- end
- to = params[:to]
- return nil if to.blank?
- if routing_table.present?
- routing_table.each do |row|
- dest = row[:dest].gsub(%r{\*}, '.+?')
- next if !to.match?(%r{^#{dest}$})
- return {
- action: 'set_caller_id',
- params: {
- from_caller_id: row[:caller_id],
- to_caller_id: params[:to],
- }
- }
- end
- end
- if default_caller_id.present?
- return {
- action: 'set_caller_id',
- params: {
- from_caller_id: default_caller_id,
- to_caller_id: params[:to],
- }
- }
- end
- nil
- end
- def push_open_ticket_screen(log)
- return if log.destroyed?
- return if @params[:event] != 'answer'
- return if @params[:direction] != 'in'
- user = push_open_ticket_screen_recipient
- return if !user
- return if !user.permissions?('cti.agent')
- customer_id = log.best_customer_id_of_log_entry
- # open user profile if user has a ticket in the last 30 days
- if customer_id
- last_activity = Setting.get('cti_customer_last_activity')
- if Ticket.where(customer_id: customer_id).exists?(['updated_at > ?', last_activity.seconds.ago])
- PushMessages.send_to(user.id, {
- event: 'remote_task',
- data: {
- key: "User-#{customer_id}",
- controller: 'UserProfile',
- params: { user_id: customer_id.to_s },
- show: true,
- url: "user/profile/#{customer_id}"
- },
- })
- return
- end
- end
- id = SecureRandom.uuid
- title = Translation.translate(user.locale, __('Call from %s'), @params[:from])
- PushMessages.send_to(user.id, {
- event: 'remote_task',
- data: {
- key: "TicketCreateScreen-#{id}",
- controller: 'TicketCreate',
- params: { customer_id: customer_id.to_s, title: title, id: id },
- show: true,
- url: "ticket/create/id/#{id}"
- },
- })
- end
- def push_open_ticket_screen_recipient
- # try to find answering which answered call
- user = nil
- # based on answeringNumber
- if @params[:answeringNumber].present?
- user = Cti::CallerId.known_agents_by_number(@params[:answeringNumber]).first
- if !user
- user = User.find_by(phone: @params[:answeringNumber], active: true)
- end
- end
- # based on user param
- if !user && @params[:user].present?
- user = User.find_by(login: @params[:user].downcase)
- end
- # based on user_id param
- if !user && @params[:user_id].present?
- user = User.find_by(id: @params[:user_id])
- end
- user
- end
- def push_incoming_call(log)
- return if log.destroyed?
- return if @params[:event] != 'newCall'
- return if @params[:direction] != 'in'
- # check if only a certain user should get the notification
- if @config[:notify_map].present?
- user_ids = []
- @config[:notify_map].each do |row|
- next if row[:user_ids].blank? || row[:queue] != @params[:to]
- row[:user_ids].each do |user_id|
- user = User.find_by(id: user_id)
- next if !user
- next if !user.permissions?('cti.agent')
- user_ids.push user.id
- end
- end
- # add agents which have this number directly assigned
- Cti::CallerId.known_agents_by_number(@params[:to]).each do |user|
- next if !user
- next if !user.permissions?('cti.agent')
- user_ids.push user.id
- end
- user_ids.uniq.each do |user_id|
- PushMessages.send_to(
- user_id,
- {
- event: 'cti_event',
- data: log,
- },
- )
- end
- return true
- end
- # send notify about event
- users = User.with_permissions('cti.agent')
- users.each do |user|
- PushMessages.send_to(
- user.id,
- {
- event: 'cti_event',
- data: log,
- },
- )
- end
- true
- end
- end
|