r7kamura/ellen

View on GitHub
lib/ruboty/robot.rb

Summary

Maintainability
A
0 mins
Test Coverage
module Ruboty
  class Robot
    DEFAULT_ENV = "development"
    DEFAULT_ROBOT_NAME = "ruboty"

    include Mem

    delegate :say, to: :adapter

    attr_reader :options

    def initialize(options = {})
      @options = options
    end

    def run
      daemon
      dotenv
      bundle
      setup
      pid
      remember
      handle
      adapt
    end

    def receive(attributes)
      message = Message.new(attributes.merge(robot: self))
      unless handlers.inject(false) { |matched, handler| matched | handler.call(message) }
        handlers.each do |handler|
          handler.call(message, missing: true)
        end
      end
    end

    # @return [true] Because it needs to tell that an action is matched.
    undef :say
    def say(*args)
      adapter.say(*args)
      true
    end

    # ROBOT_NAME is deprecated.
    def name
      ENV["RUBOTY_NAME"] || ENV["ROBOT_NAME"] || DEFAULT_ROBOT_NAME
    end

    def brain
      Brains::Base.find_class.new
    end
    memoize :brain

    private

    def adapt
      adapter.run
    end

    def adapter
      AdapterBuilder.new(self).build
    end
    memoize :adapter

    def bundle
      ::Bundler.require(:default, env)
    rescue ::Bundler::GemfileNotFound
    end

    def env
      ENV["RUBOTY_ENV"] || DEFAULT_ENV
    end
    memoize :env

    def daemon
      Process.daemon(true, false) if options[:daemon]
    end

    def dotenv
      Dotenv.load if options[:dotenv]
    end

    def setup
      load(options[:load]) if options[:load]
    end

    def handlers
      Ruboty.handlers.map { |handler_class| handler_class.new(self) }
    end
    memoize :handlers

    def remember
      brain
    end

    def handle
      handlers
    end

    def pid
      path = options[:pid]
      if path
        File.open(path, "w") { |f| f.write(Process.pid) }
        at_exit { File.unlink(path) }
      end
    end
  end
end