Repo cleanup
This commit is contained in:
parent
59872f579a
commit
e941353b64
444 changed files with 1485 additions and 21978 deletions
|
|
@ -0,0 +1,55 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class Channel
|
||||
class Driver
|
||||
class CdrSignal
|
||||
def fetchable?(_channel)
|
||||
false
|
||||
end
|
||||
|
||||
def disconnect; end
|
||||
|
||||
#
|
||||
# instance = Channel::Driver::CdrSignal.new
|
||||
# instance.send(
|
||||
# {
|
||||
# adapter: 'cdrsignal',
|
||||
# auth: {
|
||||
# api_key: api_key
|
||||
# },
|
||||
# },
|
||||
# signal_attributes,
|
||||
# notification
|
||||
# )
|
||||
#
|
||||
|
||||
def deliver(options, article, _notification = false)
|
||||
# return if we run import mode
|
||||
return if Setting.get('import_mode')
|
||||
|
||||
options = check_external_credential(options)
|
||||
|
||||
Rails.logger.debug { 'signal send started' }
|
||||
Rails.logger.debug { options.inspect }
|
||||
@signal = ::CdrSignal.new(options[:bot_endpoint], options[:bot_token])
|
||||
@signal.from_article(article)
|
||||
end
|
||||
|
||||
def self.streamable?
|
||||
false
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def check_external_credential(options)
|
||||
if options[:auth] && options[:auth][:external_credential_id]
|
||||
external_credential = ExternalCredential.find_by(id: options[:auth][:external_credential_id])
|
||||
raise "No such ExternalCredential.find(#{options[:auth][:external_credential_id]})" unless external_credential
|
||||
|
||||
options[:auth][:api_key] = external_credential.credentials['api_key']
|
||||
end
|
||||
options
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class Channel::Driver::CdrWhatsapp
|
||||
def fetchable?(_channel)
|
||||
false
|
||||
end
|
||||
|
||||
def disconnect; end
|
||||
|
||||
#
|
||||
# instance = Channel::Driver::CdrWhatsapp.new
|
||||
# instance.send(
|
||||
# {
|
||||
# adapter: 'cdr_whatsapp',
|
||||
# auth: {
|
||||
# api_key: api_key
|
||||
# },
|
||||
# },
|
||||
# whatsapp_attributes,
|
||||
# notification
|
||||
# )
|
||||
#
|
||||
|
||||
def deliver(options, article, _notification = false)
|
||||
# return if we run import mode
|
||||
return if Setting.get('import_mode')
|
||||
|
||||
options = check_external_credential(options)
|
||||
|
||||
Rails.logger.debug { 'whatsapp send started' }
|
||||
Rails.logger.debug { options.inspect }
|
||||
@whatsapp = ::CdrWhatsapp.new(options[:bot_endpoint], options[:bot_token])
|
||||
@whatsapp.from_article(article)
|
||||
end
|
||||
|
||||
def self.streamable?
|
||||
false
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def check_external_credential(options)
|
||||
if options[:auth] && options[:auth][:external_credential_id]
|
||||
external_credential = ExternalCredential.find_by(id: options[:auth][:external_credential_id])
|
||||
raise "No such ExternalCredential.find(#{options[:auth][:external_credential_id]})" unless external_credential
|
||||
|
||||
options[:auth][:api_key] = external_credential.credentials['api_key']
|
||||
end
|
||||
options
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Link::SetupSplitSignalGroup
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
included do
|
||||
after_create :setup_signal_group_for_split_ticket
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def setup_signal_group_for_split_ticket
|
||||
# Only if auto-groups enabled
|
||||
return unless ENV['BRIDGE_SIGNAL_AUTO_GROUPS'].to_s.downcase == 'true'
|
||||
|
||||
# Only child links (splits create child->parent links)
|
||||
return unless link_type_id == Link::Type.find_by(name: 'child')&.id
|
||||
|
||||
# Only Ticket-to-Ticket links
|
||||
ticket_object_id = Link::Object.find_by(name: 'Ticket')&.id
|
||||
return unless link_object_source_id == ticket_object_id
|
||||
return unless link_object_target_id == ticket_object_id
|
||||
|
||||
child_ticket = Ticket.find_by(id: link_object_source_value)
|
||||
parent_ticket = Ticket.find_by(id: link_object_target_value)
|
||||
return unless child_ticket && parent_ticket
|
||||
|
||||
# Only if parent has Signal group (chat_id starts with "group.")
|
||||
parent_signal_prefs = parent_ticket.preferences&.dig('cdr_signal')
|
||||
return unless parent_signal_prefs.present?
|
||||
return unless parent_signal_prefs['chat_id']&.start_with?('group.')
|
||||
|
||||
original_recipient = parent_signal_prefs['original_recipient']
|
||||
return unless original_recipient.present?
|
||||
|
||||
# Set up child for lazy group creation:
|
||||
# chat_id = phone number triggers new group on first message
|
||||
child_ticket.preferences ||= {}
|
||||
child_ticket.preferences['channel_id'] = parent_ticket.preferences['channel_id']
|
||||
child_ticket.preferences['cdr_signal'] = {
|
||||
'bot_token' => parent_signal_prefs['bot_token'],
|
||||
'chat_id' => original_recipient, # Phone number, NOT group ID
|
||||
'original_recipient' => original_recipient
|
||||
}
|
||||
# Set article type so Zammad shows Signal reply option
|
||||
child_ticket.create_article_type_id = Ticket::Article::Type.find_by(name: 'cdr_signal')&.id
|
||||
child_ticket.save!
|
||||
|
||||
Rails.logger.info "Signal split: Ticket ##{child_ticket.number} set up for new group (recipient: #{original_recipient})"
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Ticket::Article::EnqueueCommunicateCdrSignalJob
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
included do
|
||||
after_create :ticket_article_enqueue_communicate_cdr_signal_job
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def ticket_article_enqueue_communicate_cdr_signal_job
|
||||
# return if we run import mode
|
||||
return true if Setting.get('import_mode')
|
||||
|
||||
# if sender is customer, do not communicate
|
||||
return true unless sender_id
|
||||
|
||||
sender = Ticket::Article::Sender.lookup(id: sender_id)
|
||||
return true if sender.nil?
|
||||
return true if sender.name == 'Customer'
|
||||
|
||||
# only apply on cdr signal messages
|
||||
return true unless type_id
|
||||
|
||||
type = Ticket::Article::Type.lookup(id: type_id)
|
||||
return true unless type.name.match?(/\Acdr_signal/i)
|
||||
|
||||
CommunicateCdrSignalJob.perform_later(id)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Ticket::Article::EnqueueCommunicateCdrWhatsappJob
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
included do
|
||||
after_create :ticket_article_enqueue_communicate_cdr_whatsapp_job
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def ticket_article_enqueue_communicate_cdr_whatsapp_job
|
||||
# return if we run import mode
|
||||
return true if Setting.get('import_mode')
|
||||
|
||||
# if sender is customer, do not communicate
|
||||
return true unless sender_id
|
||||
|
||||
sender = Ticket::Article::Sender.lookup(id: sender_id)
|
||||
return true if sender.nil?
|
||||
return true if sender.name == 'Customer'
|
||||
|
||||
# only apply on cdr whatsapp messages
|
||||
return true unless type_id
|
||||
|
||||
type = Ticket::Article::Type.lookup(id: type_id)
|
||||
return true unless type.name.match?(/\Acdr_whatsapp/i)
|
||||
|
||||
CommunicateCdrWhatsappJob.perform_later(id)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -0,0 +1,143 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class Transaction::SignalNotification
|
||||
include ChecksHumanChanges
|
||||
|
||||
def initialize(item, params = {})
|
||||
@item = item
|
||||
@params = params
|
||||
end
|
||||
|
||||
def perform
|
||||
return if Setting.get('import_mode')
|
||||
return if %w[Ticket Ticket::Article].exclude?(@item[:object])
|
||||
return if @params[:disable_notification]
|
||||
return if !ticket
|
||||
return if !signal_notifications_enabled?
|
||||
return if !signal_channel
|
||||
|
||||
collect_signal_recipients.each do |user|
|
||||
SignalNotificationJob.perform_later(
|
||||
ticket_id: ticket.id,
|
||||
article_id: @item[:article_id],
|
||||
user_id: user.id,
|
||||
type: @item[:type],
|
||||
changes: human_changes(@item[:changes], ticket, user)
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def ticket
|
||||
@ticket ||= Ticket.find_by(id: @item[:object_id])
|
||||
end
|
||||
|
||||
def article
|
||||
return if !@item[:article_id]
|
||||
|
||||
@article ||= begin
|
||||
art = Ticket::Article.find_by(id: @item[:article_id])
|
||||
return unless art
|
||||
|
||||
sender = Ticket::Article::Sender.lookup(id: art.sender_id)
|
||||
if sender&.name == 'System'
|
||||
return if @item[:changes].blank? && art.preferences[:notification] != true
|
||||
return if art.preferences[:notification] != true
|
||||
end
|
||||
|
||||
art
|
||||
end
|
||||
end
|
||||
|
||||
def current_user
|
||||
@current_user ||= User.lookup(id: @item[:user_id]) || User.lookup(id: 1)
|
||||
end
|
||||
|
||||
def signal_notifications_enabled?
|
||||
Setting.get('signal_notification_enabled') == true
|
||||
end
|
||||
|
||||
def signal_channel
|
||||
@signal_channel ||= begin
|
||||
channel_id = Setting.get('signal_notification_channel_id')
|
||||
return unless channel_id
|
||||
|
||||
Channel.find_by(id: channel_id, area: 'Signal::Number', active: true)
|
||||
end
|
||||
end
|
||||
|
||||
def collect_signal_recipients
|
||||
recipients = []
|
||||
|
||||
possible_recipients = possible_recipients_of_group(ticket.group_id)
|
||||
|
||||
mention_users = Mention.where(mentionable_type: @item[:object], mentionable_id: @item[:object_id]).map(&:user)
|
||||
mention_users.each do |user|
|
||||
next if !user.group_access?(ticket.group_id, 'read')
|
||||
|
||||
possible_recipients.push(user)
|
||||
end
|
||||
|
||||
if ticket.owner_id != 1
|
||||
possible_recipients.push(ticket.owner)
|
||||
end
|
||||
|
||||
possible_recipients_with_ooo = Set.new(possible_recipients)
|
||||
possible_recipients.each do |user|
|
||||
add_out_of_office_replacement(user, possible_recipients_with_ooo)
|
||||
end
|
||||
|
||||
possible_recipients_with_ooo.each do |user|
|
||||
next if recipient_is_current_user?(user)
|
||||
next if !user.active?
|
||||
next if user_signal_uid(user).blank?
|
||||
next if !user_wants_signal_for_event?(user)
|
||||
|
||||
recipients.push(user)
|
||||
end
|
||||
|
||||
recipients.uniq(&:id)
|
||||
end
|
||||
|
||||
def possible_recipients_of_group(group_id)
|
||||
Rails.cache.fetch("User/signal_notification/possible_recipients_of_group/#{group_id}/#{User.latest_change}", expires_in: 20.seconds) do
|
||||
User.group_access(group_id, 'full').sort_by(&:login)
|
||||
end
|
||||
end
|
||||
|
||||
def add_out_of_office_replacement(user, recipients)
|
||||
replacement = user.out_of_office_agent
|
||||
return unless replacement
|
||||
return unless TicketPolicy.new(replacement, ticket).agent_read_access?
|
||||
|
||||
recipients.add(replacement)
|
||||
end
|
||||
|
||||
def recipient_is_current_user?(user)
|
||||
return false if @params[:interface_handle] != 'application_server'
|
||||
return true if article&.updated_by_id == user.id
|
||||
return true if !article && @item[:user_id] == user.id
|
||||
|
||||
false
|
||||
end
|
||||
|
||||
def user_signal_uid(user)
|
||||
user.preferences.dig('notification_config', 'signal_uid').presence
|
||||
end
|
||||
|
||||
def user_wants_signal_for_event?(user)
|
||||
event_type = @item[:type]
|
||||
return false if event_type.blank?
|
||||
|
||||
event_key = case event_type
|
||||
when 'create' then 'create'
|
||||
when 'update', 'update.merged_into', 'update.received_merge', 'update.reaction' then 'update'
|
||||
when 'reminder_reached' then 'reminder_reached'
|
||||
when 'escalation', 'escalation_warning' then 'escalation'
|
||||
else return false
|
||||
end
|
||||
|
||||
user.preferences.dig('notification_config', 'matrix', event_key, 'channel', 'signal') == true
|
||||
end
|
||||
end
|
||||
Loading…
Add table
Add a link
Reference in a new issue