lib/backup/notifier/slack.rb
# frozen_string_literal: true
require "uri"
require "json"
module Backup
module Notifier
class Slack < Base
##
# The incoming webhook url
attr_accessor :webhook_url
##
# The channel to send messages to
attr_accessor :channel
##
# The username to display along with the notification
attr_accessor :username
##
# The emoji icon to display along with the notification
#
# See http://www.emoji-cheat-sheet.com for a list of icons.
#
# Default: :floppy_disk:
attr_accessor :icon_emoji
##
# Array of statuses for which the log file should be attached.
#
# Available statuses are: `:success`, `:warning` and `:failure`.
# Default: [:warning, :failure]
attr_accessor :send_log_on
def initialize(model, &block)
super
instance_eval(&block) if block_given?
@send_log_on ||= [:warning, :failure]
@icon_emoji ||= ":floppy_disk:"
end
private
##
# Notify the user of the backup operation results.
#
# `status` indicates one of the following:
#
# `:success`
# : The backup completed successfully.
# : Notification will be sent if `on_success` is `true`.
#
# `:warning`
# : The backup completed successfully, but warnings were logged.
# : Notification will be sent if `on_warning` or `on_success` is `true`.
#
# `:failure`
# : The backup operation failed.
# : Notification will be sent if `on_warning` or `on_success` is `true`.
#
def notify!(status)
data = {
text: message.call(model, status: status_data_for(status)),
attachments: [attachment(status)]
}
[:channel, :username, :icon_emoji].each do |param|
val = send(param)
data.merge!(param => val) if val
end
options = {
headers: { "Content-Type" => "application/x-www-form-urlencoded" },
body: URI.encode_www_form(payload: JSON.dump(data))
}
options[:expects] = 200 # raise error if unsuccessful
Excon.post(uri, options)
end
def attachment(status)
{
fallback: "#{title(status)} - Job: #{model.label} (#{model.trigger})",
text: title(status),
color: color(status),
fields: [
{
title: "Job",
value: "#{model.label} (#{model.trigger})",
short: false
},
{
title: "Started",
value: model.started_at,
short: true
},
{
title: "Finished",
value: model.finished_at,
short: true
},
{
title: "Duration",
value: model.duration,
short: true
},
{
title: "Version",
value: "Backup v#{Backup::VERSION}\nRuby: #{RUBY_DESCRIPTION}",
short: false
},
log_field(status)
].compact
}
end
def log_field(status)
send_log = send_log_on.include?(status)
return unless send_log
{
title: "Detailed Backup Log",
value: Logger.messages.map(&:formatted_lines).flatten.join("\n"),
short: false
}
end
def color(status)
case status
when :success then "good"
when :failure then "danger"
when :warning then "warning"
end
end
def title(status)
case status
when :success then "Backup Completed Successfully!"
when :failure then "Backup Failed!"
when :warning then "Backup Completed Successfully (with Warnings)!"
end
end
def uri
@uri ||= webhook_url
end
end
end
end