2026-01-21 09:44:40 +01:00
|
|
|
# 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
|
|
|
|
|
|
2026-01-28 14:46:34 +01:00
|
|
|
Channel.find_by(id: channel_id, area: 'Signal::Number', active: true)
|
2026-01-21 09:44:40 +01:00
|
|
|
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_has_signal_notifications_enabled?(user)
|
|
|
|
|
next if user.signal_uid.blank?
|
|
|
|
|
next if !should_notify_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_has_signal_notifications_enabled?(user)
|
|
|
|
|
user.preferences.dig('signal_notifications', 'enabled') == true
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
def should_notify_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('signal_notifications', 'events', event_key) == true
|
|
|
|
|
end
|
|
|
|
|
end
|