18F/dolores-landingham-slack-bot

View on GitHub
app/services/message_sender.rb

Summary

Maintainability
A
1 hr
Test Coverage
require "slack-ruby-client"

class MessageSender
  def initialize(employee, message, test_message: false)
    @employee = employee
    @message = message
    @test_message = test_message
  end

  def run
    slack_user_id = EmployeeFinder.new(employee.slack_username).slack_user_id

    if employee.slack_user_id.nil? && slack_user_id.present?
      employee.slack_user_id = slack_user_id
      employee.save
    end

    if employee.slack_channel_id.nil?
      channel_id = SlackChannelIdFinder.new(employee.slack_user_id, client).run
      employee.slack_channel_id = channel_id
      employee.save
    end

    if employee.slack_channel_id.present?
      begin
        post_message(channel_id: employee.slack_channel_id, message: message)
        create_sent_message(
          employee: employee,
          message: message,
          error: nil,
        )
      rescue Slack::Web::Api::Error => error
        create_sent_message(
          employee: employee,
          message: message,
          error: error,
        )
      end
    else
      create_sent_message(
        employee: employee,
        message: message,
        error: StandardError.new("Was unable to find a slack channel for user with name #{employee.slack_username} and slack user id #{employee.slack_user_id}"),
      )
    end

  end

  private

  attr_reader :employee, :message, :test_message

  def client
    @client ||= Slack::Web::Client.new
  end

  def post_message(options)
    client.chat_postMessage(
      channel: options[:channel_id],
      as_user: true,
      text: options[:message].body,
    )
  end

  def create_sent_message(options)
    if !test_message
      SentMessage.create(
        employee: options[:employee],
        message: options[:message],
        sent_on: Date.current,
        sent_at: Time.current,
        error_message: error_message(options[:error]),
        message_body: formatted_message(options),
      )
    end
  end

  def error_message(error)
    if error
      error.message
    else
      ""
    end
  end

  def formatted_message(options)
    MessageFormatter.new(options[:message]).escape_slack_characters
  end
end