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