trabajo-afectivo/app/models/transaction/slack.rb

311 lines
9.1 KiB
Ruby
Raw Normal View History

2016-10-19 03:11:36 +00:00
# Copyright (C) 2012-2016 Zammad Foundation, http://zammad-foundation.org/
2016-04-15 21:56:10 +00:00
class Transaction::Slack
2016-04-18 00:02:31 +00:00
=begin
2016-04-18 00:02:31 +00:00
backend = Transaction::Slack.new(
2016-04-15 21:56:10 +00:00
object: 'Ticket',
type: 'update',
object_id: 123,
interface_handle: 'application_server', # application_server|websocket|scheduler
2016-04-15 21:56:10 +00:00
changes: {
'attribute1' => [before, now],
'attribute2' => [before, now],
2016-07-16 21:43:08 +00:00
},
created_at: Time.zone.now,
user_id: 123,
)
backend.perform
2016-04-15 21:56:10 +00:00
=end
2016-04-15 21:56:10 +00:00
def initialize(item, params = {})
@item = item
@params = params
end
def perform
# return if we run import mode
return if Setting.get('import_mode')
2016-04-15 21:56:10 +00:00
return if @item[:object] != 'Ticket'
return if !Setting.get('slack_integration')
config = Setting.get('slack_config')
return if !config
return if !config['items']
ticket = Ticket.find_by(id: @item[:object_id])
return if !ticket
2016-04-15 21:56:10 +00:00
if @item[:article_id]
article = Ticket::Article.find(@item[:article_id])
2016-05-16 15:01:59 +00:00
# ignore notifications
sender = Ticket::Article::Sender.lookup(id: article.sender_id)
2017-11-23 08:09:44 +00:00
if sender&.name == 'System'
return if @item[:changes].blank?
2016-05-16 15:01:59 +00:00
article = nil
end
2016-04-15 21:56:10 +00:00
end
# ignore if no changes has been done
changes = human_changes(ticket)
2017-11-23 08:09:44 +00:00
return if @item[:type] == 'update' && !article && changes.blank?
2016-04-15 21:56:10 +00:00
# get user based notification template
# if create, send create message / block update messages
template = nil
sent_value = nil
2016-04-15 21:56:10 +00:00
if @item[:type] == 'create'
template = 'ticket_create'
elsif @item[:type] == 'update'
template = 'ticket_update'
elsif @item[:type] == 'reminder_reached'
template = 'ticket_reminder_reached'
sent_value = ticket.pending_time
2016-04-15 21:56:10 +00:00
elsif @item[:type] == 'escalation'
template = 'ticket_escalation'
sent_value = ticket.escalation_at
2016-04-15 21:56:10 +00:00
elsif @item[:type] == 'escalation_warning'
template = 'ticket_escalation_warning'
sent_value = ticket.escalation_at
2016-04-15 21:56:10 +00:00
else
raise "unknown type for notification #{@item[:type]}"
end
user = User.find(1)
current_user = User.lookup(id: @item[:user_id])
if !current_user
current_user = User.lookup(id: 1)
end
2016-04-15 21:56:10 +00:00
result = NotificationFactory::Slack.template(
template: template,
locale: user[:preferences][:locale] || Setting.get('locale_default'),
timezone: user[:preferences][:timezone] || Setting.get('timezone_default'),
objects: {
ticket: ticket,
article: article,
current_user: current_user,
changes: changes,
2016-04-15 21:56:10 +00:00
},
)
# good, warning, danger
color = '#000000'
ticket_state_type = ticket.state.state_type.name
if ticket.escalation_at && ticket.escalation_at < Time.zone.now
2016-04-15 21:56:10 +00:00
color = '#f35912'
elsif ticket_state_type == 'pending reminder'
if ticket.pending_time && ticket.pending_time < Time.zone.now
color = '#faab00'
end
2017-11-23 08:09:44 +00:00
elsif ticket_state_type.match?(/^(new|open)$/)
2016-04-15 21:56:10 +00:00
color = '#faab00'
elsif ticket_state_type == 'closed'
color = '#38ad69'
end
config['items'].each do |local_config|
2017-11-23 08:09:44 +00:00
next if local_config['webhook'].blank?
2016-04-15 21:56:10 +00:00
# check if reminder_reached/escalation/escalation_warning is already sent today
2016-04-18 08:01:20 +00:00
md5_webhook = Digest::MD5.hexdigest(local_config['webhook'])
cache_key = "slack::backend::#{@item[:type]}::#{ticket.id}::#{md5_webhook}"
if sent_value
value = Cache.get(cache_key)
if value == sent_value
Rails.logger.debug { "did not send webhook, already sent (#{@item[:type]}/#{ticket.id}/#{local_config['webhook']})" }
next
end
Cache.write(
cache_key,
sent_value,
{
expires_in: 24.hours
},
)
end
2016-04-15 21:56:10 +00:00
# check action
2016-04-18 08:01:20 +00:00
if local_config['types'].class == Array
2016-04-18 00:08:11 +00:00
hit = false
local_config['types'].each do |type|
2016-04-18 00:08:11 +00:00
next if type.to_s != @item[:type].to_s
2016-04-18 00:08:11 +00:00
hit = true
break
end
2016-04-18 00:08:11 +00:00
next if !hit
2016-04-18 08:01:20 +00:00
elsif local_config['types']
next if local_config['types'].to_s != @item[:type].to_s
2016-04-15 21:56:10 +00:00
end
# check group
2016-04-18 08:01:20 +00:00
if local_config['group_ids'].class == Array
2016-04-18 00:08:11 +00:00
hit = false
local_config['group_ids'].each do |group_id|
2016-04-18 00:08:11 +00:00
next if group_id.to_s != ticket.group_id.to_s
2016-04-18 00:08:11 +00:00
hit = true
break
end
2016-04-18 00:08:11 +00:00
next if !hit
2016-04-18 08:01:20 +00:00
elsif local_config['group_ids']
next if local_config['group_ids'].to_s != ticket.group_id.to_s
2016-04-15 21:56:10 +00:00
end
logo_url = 'https://zammad.com/assets/images/logo-200x200.png'
2017-11-23 08:09:44 +00:00
if local_config['logo_url'].present?
2016-04-18 08:01:20 +00:00
logo_url = local_config['logo_url']
end
Rails.logger.debug { "sent webhook (#{@item[:type]}/#{ticket.id}/#{local_config['webhook']})" }
2016-04-15 21:56:10 +00:00
notifier = Slack::Notifier.new(
2016-04-18 08:01:20 +00:00
local_config['webhook'],
channel: local_config['channel'],
username: local_config['username'],
icon_url: logo_url,
mrkdwn: true,
2016-04-18 00:02:31 +00:00
http_client: Transaction::Slack::Client,
2016-04-15 21:56:10 +00:00
)
2016-04-18 08:01:20 +00:00
if local_config['expand']
2016-04-15 21:56:10 +00:00
body = "#{result[:subject]}\n#{result[:body]}"
result = notifier.ping body
else
attachment = {
text: result[:body],
2016-04-15 21:56:10 +00:00
mrkdwn_in: ['text'],
color: color,
2016-04-15 21:56:10 +00:00
}
result = notifier.ping result[:subject],
attachments: [attachment]
end
if !result.empty? && !result[0].success?
if sent_value
Cache.delete(cache_key)
end
2016-04-18 08:01:20 +00:00
Rails.logger.error "Unable to post webhook: #{local_config['webhook']}: #{result.inspect}"
2016-04-18 00:02:31 +00:00
next
2016-04-15 21:56:10 +00:00
end
Rails.logger.debug { "sent webhook (#{@item[:type]}/#{ticket.id}/#{local_config['webhook']})" }
end
2016-04-15 21:56:10 +00:00
end
def human_changes(record)
return {} if !@item[:changes]
2016-04-15 21:56:10 +00:00
user = User.find(1)
locale = user.preferences[:locale] || Setting.get('locale_default') || 'en-us'
2016-04-15 21:56:10 +00:00
# only show allowed attributes
attribute_list = ObjectManager::Attribute.by_object_as_hash('Ticket', user)
#puts "AL #{attribute_list.inspect}"
user_related_changes = {}
@item[:changes].each do |key, value|
2016-04-15 21:56:10 +00:00
# if no config exists, use all attributes
2017-11-23 08:09:44 +00:00
if attribute_list.blank?
2016-04-15 21:56:10 +00:00
user_related_changes[key] = value
# if config exists, just use existing attributes for user
elsif attribute_list[key.to_s]
user_related_changes[key] = value
end
end
2016-04-15 21:56:10 +00:00
changes = {}
user_related_changes.each do |key, value|
2016-04-15 21:56:10 +00:00
# get attribute name
attribute_name = key.to_s
object_manager_attribute = attribute_list[attribute_name]
if attribute_name[-3, 3] == '_id'
attribute_name = attribute_name[ 0, attribute_name.length - 3 ].to_s
end
# add item to changes hash
if key.to_s == attribute_name
changes[attribute_name] = value
end
# if changed item is an _id field/reference, look up the real values
2016-04-15 21:56:10 +00:00
value_id = []
value_str = [ value[0], value[1] ]
if key.to_s[-3, 3] == '_id'
value_id[0] = value[0]
value_id[1] = value[1]
if record.respond_to?(attribute_name) && record.send(attribute_name)
relation_class = record.send(attribute_name).class
if relation_class && value_id[0]
relation_model = relation_class.lookup(id: value_id[0])
if relation_model
if relation_model['name']
value_str[0] = relation_model['name']
elsif relation_model.respond_to?('fullname')
value_str[0] = relation_model.send('fullname')
end
end
end
if relation_class && value_id[1]
relation_model = relation_class.lookup(id: value_id[1])
if relation_model
if relation_model['name']
value_str[1] = relation_model['name']
elsif relation_model.respond_to?('fullname')
value_str[1] = relation_model.send('fullname')
end
end
end
end
end
# check if we have a dedicated display name for it
2016-04-15 21:56:10 +00:00
display = attribute_name
if object_manager_attribute && object_manager_attribute[:display]
# delete old key
changes.delete(display)
# set new key
display = object_manager_attribute[:display].to_s
end
changes[display] = if object_manager_attribute && object_manager_attribute[:translate]
from = Translation.translate(locale, value_str[0])
to = Translation.translate(locale, value_str[1])
[from, to]
else
[value_str[0].to_s, value_str[1].to_s]
end
end
2016-04-15 21:56:10 +00:00
changes
end
2016-04-18 00:02:31 +00:00
class Transaction::Slack::Client
def self.post(uri, params = {})
UserAgent.post(
uri.to_s,
params,
{
open_timeout: 4,
read_timeout: 10,
2016-04-18 00:02:31 +00:00
total_timeout: 20,
log: {
2016-04-18 00:02:31 +00:00
facility: 'slack_webhook',
}
},
)
end
end
2016-04-15 21:56:10 +00:00
end