class Pepito::Robot

The robot component of the bot.

Attributes

adapters[R]

List of running adapters. @return [Hash] A map of adapter’s keys to classes.

database[R]

Redis connection @return [Pepito::Database]

default_adapters[R]

Default adapters that can’t be turned off @return [Array<String>]

default_handlers[R]

Default handlers that can’t be turned off @return [Array<String>]

handlers[R]

List of running handlers. @return [Hash] A map of handler’s keys to classes.

http_api[R]

The running http_api. @return [Pepito::HTTPApi::RackApp]

http_api_server[R]

The Puma::Server running the HTTP API @return [Puma::Server]

http_api_thread[R]

The thread running the HTTP API. @return [Thread]

logger[R]

Logger @return [Logger]

name[R]

Name of the bot. @return [String]

web_app[R]

The web app. @return [Pepito::WebApp::App]

web_app_server[R]

The Puma::Server running the Web App @return [Puma::Server]

web_app_thread[R]

The thread running the web app. @return [Thread]

Public Class Methods

new() click to toggle source

@return [void]

# File lib/pepito/robot.rb, line 79
def initialize
  @logger = Logger.new(ENV['LOG_FILE'] || STDOUT)

  @logger.info('Connecting to the database')
  @database = Database.new

  @http_api = HTTPApi::RackApp.new

  @web_app = WebApp::App

  @default_handlers = %w(Info Help Room ExtensionsCatalog Queenbee)
  @handlers = {}

  @default_adapters = []
  @adapters = {}

  @name = @database.get('name') || 'pepito'
end

Public Instance Methods

adapter?(adapter) click to toggle source

Checks if an adapter is running or not. @param adapter [String] Name of the adapter. @return [Boolean]

# File lib/pepito/robot.rb, line 323
def adapter?(adapter)
  @adapters.key?(adapter)
end
adapters_list() click to toggle source

Retrieve the list of possible adapters to install from server @return [Array<String>]

# File lib/pepito/robot.rb, line 139
def adapters_list
  catalog_url = 'https://raw.githubusercontent.com/yafoy/pepito-catalog/master/all.json'
  response = RestClient.get(catalog_url)
  integrations = MultiJson.load(response.body, symbolize_keys: true)
  integrations[:adapters]
end
handler?(handler) click to toggle source

Checks if an handler is running or not. @param handler [String] Name of the handler. @return [Boolean]

# File lib/pepito/robot.rb, line 228
def handler?(handler)
  @handlers.key?(handler)
end
handlers_list() click to toggle source

Retrieve the list of possible handlers to install from server @return [Array<String>]

# File lib/pepito/robot.rb, line 130
def handlers_list
  catalog_url = 'https://raw.githubusercontent.com/yafoy/pepito-catalog/master/all.json'
  response = RestClient.get(catalog_url)
  integrations = MultiJson.load(response.body, symbolize_keys: true)
  integrations[:handlers]
end
receive_message(message) click to toggle source

Helper to receive a message. @param message [Pepito::Message] A message received by an adapter. @return [void]

# File lib/pepito/robot.rb, line 115
def receive_message(message)
  match = @handlers.dup.map do |_, handler|
    handler.chat_routes.map do |route|
      next unless message.match_route?(route)
      strings = handler.public_send(route.func, message.source, route.pattern.match(message.command || message.body))
      message.source.adapter.send_messages(message.source, strings) unless strings.nil?
      true
    end.any?
  end.any?

  message.source.adapter.send_messages(message.source, ['No match for command "' + message.command + '"']) if !match && message.command
end
run() click to toggle source

Runs the robot. @return [void]

# File lib/pepito/robot.rb, line 100
def run
  run_http_api
  run_web_app
  run_handlers
  run_adapters
  begin
    sleep
  rescue Interrupt
    @logger.info('Exiting')
  end
end
start_adapter(adapter, gem_name, config) click to toggle source

Starts an adapter. @param adapter [String] Name of the adapter to start. Must match the adapter’s class name. @param gem_name [String] Name of the gem for the adapter @param config [Hash<String,String>] The config for the adapter @return [Integer]

0 - if adapter was started
1 - if adapter is already running
2 - if adapter can't be found
3 - if there are missing methods on the adapter
4 - if there are missing configuration values
5 - other errors
# File lib/pepito/robot.rb, line 243
def start_adapter(adapter, gem_name, config)
  @logger.info('"' + adapter.to_s + '" adapter starting')
  if @adapters.key?(adapter)
    @logger.warn('"' + adapter.to_s + '" adapter already running')
    return 1
  else
    # Installing gem
    begin
      gem_load gem_name
    rescue => e
      @logger.error(e)
      return 2
    end

    begin
      adp = Pepito::Adapters.const_get(adapter).new(self, config)
    rescue NameError => e
      @logger.error('"' + adapter.to_s + '" adapter could not be found')
      @logger.error(e)
      return 2
    rescue Pepito::Errors::RequiredMethodsError => e
      @logger.error('"' + adapter.to_s + '" adapter failed to start. ' + e.message + ': ' + e.missing_methods.to_s)
      return 3
    rescue Pepito::Errors::MissingConfigurationValueError => e
      @logger.error('"' + adapter.to_s + '" adapter failed to start. ' + e.message + ': ' + e.configuration_values.to_s)
      return 4
    rescue => e
      @logger.error('"' + adapter.to_s + '" adapter failed to start. Error: ' + e.message.to_s)
      @logger.error(e)
      return 5
    end

    # If it didnt fail, spawn adapter thread
    @adapters[adapter] = adp
    @database.sadd('adapters', adapter)
    # Clear old config in database
    @database.del(adapter)
    # Set gem name in database
    @database.set(adapter + ':gem', gem_name)
    # Setup new config in database
    config.each do |key, value|
      @database.hset(adapter + ':config', key, value)
    end

    Thread.new do
      adp.run
    end

    @logger.info('"' + adapter.to_s + '" adapter started successfully')
    return 0
  end
end
start_handler(handler, gem_name, config) click to toggle source

Starts an handler. @param handler [String] Name of the handler to start. @return [Integer]

0 - If success
1 - If failed because handler is already running
2 - If handler can't be found
3 - If handler is missing configuration values
4 - Other errors
# File lib/pepito/robot.rb, line 154
def start_handler(handler, gem_name, config)
  @logger.info('"' + handler.to_s + '" handler starting')
  if @handlers.key?(handler)
    @logger.warn('"' + handler.to_s + '" handler is already running')
    return 1
  else
    # Installing gem
    begin
      gem_load gem_name
    rescue => e
      @logger.error(e)
      return 2
    end

    begin
      @handlers[handler] = Handlers.const_get(handler).new(self, config)
    rescue NameError
      @logger.error('"' + handler.to_s + '" handler does not exist')
      return 2
    rescue Pepito::Errors::MissingConfigurationValueError => e
      @logger.error('"' + handler.to_s + '" handler failed to start. ' + e.message + ': ' + e.configuration_values.to_s)
      return 3
    rescue => e
      @logger.error('"' + handler.to_s + '" handler failed to start. Error: ' + e.message.to_s)
      @logger.error(e)
      return 4
    end

    @http_api.router.uncompile
    @handlers[handler].run
    @handlers[handler].start
    @database.sadd('handlers', handler)
    @database.set(handler + ':gem', gem_name)
    # Setup new config in database
    config.each do |key, value|
      @database.hset(handler + ':config', key, value)
    end

    @logger.info('"' + handler.to_s + '" handler started successfully')
    return 0
  end
end
stop_adapter(adapter) click to toggle source

Stops an adapter. @param adapter [String] Name of the adapter to stop. Must match the adapter’s class name. @return [Integer]

0 - If successful
1 - If adapter is default
2 - If adapter is not running
# File lib/pepito/robot.rb, line 302
def stop_adapter(adapter)
  if @default_adapters.include?(adapter)
    @logger.error('Can\'t stop "' + adapter.to_s + '" adapter because it is a default adapter')
    return 1
  elsif !@adapters.key?(adapter)
    @logger.warn('"' + adapter.to_s + '" adapter is not running')
    return 2
  else
    @adapters[adapter].stop
    @adapters.delete(adapter)
    @database.del(adapter + ':config')
    @database.del(adapter + ':gem')
    @database.srem('adapters', adapter)
    @logger.info('"' + adapter.to_s + '" adapter stopped successfully')
    return 0
  end
end
stop_handler(handler) click to toggle source

Stops an handler. @param handler [String] Name of the handler to stop. Must match the handler’s class name. @return [Integer]

0 - If handler stopped
1 - If it is a default handler
2 - If it is not running
# File lib/pepito/robot.rb, line 203
def stop_handler(handler)
  @logger.info('Stopping "' + handler.to_s + '" handler')
  if @default_handlers.include?(handler)
    @logger.error('Can\'t stop "' + handler.to_s + '" because it is a default handler')
    return 1
  elsif !@handlers.key?(handler)
    @logger.warn('"' + handler.to_s + '" handler is not running')
    return 2
  else
    @handlers.delete(handler)
    @database.srem('handlers', handler)
    @database.del(handler + ':config')
    @database.del(handler + ':gem')
    @http_api.router.reset!
    @handlers.each do |_, h|
      h.start
    end
    @logger.info('"' + handler.to_s + '" handler stopped successfully')
    return 0
  end
end

Private Instance Methods

run_adapters() click to toggle source

Runs the adapters saved in the database @return [void]

# File lib/pepito/robot.rb, line 373
def run_adapters
  @logger.info('Starting the adapters')
  @default_adapters.each do |adapter, gem_name, configs|
    start_adapter(adapter, gem_name, configs)
  end

  @database.smembers('adapters').each do |adapter|
    start_adapter(adapter, @database.get(adapter + ':gem'), @database.hgetall(adapter + ':config')) unless @default_adapters.include?(adapter)
  end
end
run_handlers() click to toggle source

Runs the handlers saved in the database @return [void]

# File lib/pepito/robot.rb, line 360
def run_handlers
  @logger.info('Starting the handlers')
  @default_handlers.each do |handler|
    start_handler(handler, 'pepito', [])
  end

  @database.smembers('handlers').each do |handler|
    start_handler(handler, @database.get(handler + ':gem'), @database.hgetall(handler + ':config')) unless @default_handlers.include?(handler)
  end
end
run_http_api() click to toggle source

Runs the http api in a new thread. @return [void]

# File lib/pepito/robot.rb, line 331
def run_http_api
  @logger.info('Starting the HTTP API')
  @http_api_thread = Thread.new do
    @http_api_server = Puma::Server.new(@http_api.app)
    @http_api_server.add_tcp_listener('127.0.0.1', 8080)
    @http_api_server.run
  end

  @http_api_thread.abort_on_exception = true
end
run_web_app() click to toggle source

Runs the web app in a new thread. @return [void]

# File lib/pepito/robot.rb, line 344
def run_web_app
  @logger.info('Starting the web app')
  @web_app_thread = Thread.new do
    @web_app.set(:robot, self)

    @web_app_server = Puma::Server.new(@web_app)
    @web_app_server.add_tcp_listener('127.0.0.1', 4567)

    @web_app_server.run
  end

  @web_app_thread.abort_on_exception = true
end