class SlackRubyBot::Commands::Base

Attributes

command_classes[RW]

Public Class Methods

attachment(match, fields_to_scan = nil, &block) click to toggle source
# File lib/slack-ruby-bot/commands/base.rb, line 81
def attachment(match, fields_to_scan = nil, &block)
  fields_to_scan = [fields_to_scan] unless fields_to_scan.nil? || fields_to_scan.is_a?(Array)
  routes[match] = {
    match_method: :attachment,
    block: block,
    fields_to_scan: fields_to_scan
  }
end
bot_matcher() click to toggle source
# File lib/slack-ruby-bot/commands/base.rb, line 90
def bot_matcher
  '(?<bot>\S*)'
end
command(*values, &block) click to toggle source
# File lib/slack-ruby-bot/commands/base.rb, line 32
def command(*values, &block)
  values = values.map { |value| value.is_a?(Regexp) ? value.source : Regexp.escape(value) }.join('|')
  match Regexp.new("^#{bot_matcher}[[:space:]]+(?<command>#{values})([[:space:]]+(?<expression>.*)|)$", Regexp::IGNORECASE | Regexp::MULTILINE), &block
end
command_name_from_class() click to toggle source
# File lib/slack-ruby-bot/commands/base.rb, line 23
def command_name_from_class
  name ? name.split(':').last.downcase : object_id.to_s
end
help(&block) click to toggle source
# File lib/slack-ruby-bot/commands/base.rb, line 19
def help(&block)
  Support::Help.instance.capture_help(self, &block)
end
inherited(subclass) click to toggle source
# File lib/slack-ruby-bot/commands/base.rb, line 14
def inherited(subclass)
  SlackRubyBot::Commands::Base.command_classes ||= []
  SlackRubyBot::Commands::Base.command_classes << subclass
end
invoke(client, data) click to toggle source
# File lib/slack-ruby-bot/commands/base.rb, line 37
def invoke(client, data)
  finalize_routes!
  expression, text = parse(client, data)
  return false unless expression || data.attachments

  routes.each_pair do |route, options|
    match_method = options[:match_method]
    case match_method
    when :match
      next unless expression

      match = route.match(expression)
      match ||= route.match(text) if text
      next unless match
      next if match.names.include?('bot') && !client.name?(match['bot'])

      match = Support::Match.new(match)
    when :scan
      next unless expression

      match = expression.scan(route)
      next unless match.any?
    when :attachment
      next unless data.attachments && !data.attachments.empty?

      match, attachment, field = match_attachments(data, route, options[:fields_to_scan])
      next unless match

      match = Support::Match.new(match, attachment, field)
    end
    call_command(client, data, match, options[:block])
    return true
  end
  false
end
match(match, &block) click to toggle source
# File lib/slack-ruby-bot/commands/base.rb, line 73
def match(match, &block)
  routes[match] = { match_method: :match, block: block }
end
operator(*values, &block) click to toggle source
# File lib/slack-ruby-bot/commands/base.rb, line 27
def operator(*values, &block)
  values = values.map { |value| Regexp.escape(value) }.join('|')
  match Regexp.new("^(?<operator>#{values})(?<expression>.*)$", Regexp::IGNORECASE), &block
end
routes() click to toggle source
# File lib/slack-ruby-bot/commands/base.rb, line 94
def routes
  @routes ||= ActiveSupport::OrderedHash.new
end
scan(match, &block) click to toggle source
# File lib/slack-ruby-bot/commands/base.rb, line 77
def scan(match, &block)
  routes[match] = { match_method: :scan, block: block }
end

Private Class Methods

call_command(client, data, match, block) click to toggle source
# File lib/slack-ruby-bot/commands/base.rb, line 100
def call_command(client, data, match, block)
  if block
    block.call(client, data, match) if permitted?(client, data, match)
  elsif respond_to?(:call)
    send(:call, client, data, match) if permitted?(client, data, match)
  else
    raise NotImplementedError, data.text
  end
end
direct_message?(data) click to toggle source
# File lib/slack-ruby-bot/commands/base.rb, line 118
def direct_message?(data)
  data.channel && data.channel[0] == 'D'
end
finalize_routes!() click to toggle source
# File lib/slack-ruby-bot/commands/base.rb, line 131
def finalize_routes!
  return if routes&.any?

  command command_name_from_class
end
match_attachments(data, route, fields_to_scan = nil) click to toggle source
# File lib/slack-ruby-bot/commands/base.rb, line 137
def match_attachments(data, route, fields_to_scan = nil)
  fields_to_scan ||= %i[pretext text title]
  data.attachments.each do |attachment|
    fields_to_scan.each do |field|
      next unless attachment[field]

      match = route.match(attachment[field])
      return match, attachment, field if match
    end
  end
  false
end
message_begins_with_bot_mention?(text, bot_names) click to toggle source
# File lib/slack-ruby-bot/commands/base.rb, line 126
def message_begins_with_bot_mention?(text, bot_names)
  bot_names = bot_names.join('|')
  !!text.downcase.match(/\A(#{bot_names})\s|\A(#{bot_names})\z/)
end
message_from_another_user?(data) click to toggle source
# File lib/slack-ruby-bot/commands/base.rb, line 122
def message_from_another_user?(data)
  data.user && data.user != SlackRubyBot.config.user_id
end
parse(client, data) click to toggle source
# File lib/slack-ruby-bot/commands/base.rb, line 110
def parse(client, data)
  text = data.text
  return text unless direct_message?(data) && message_from_another_user?(data)
  return text if message_begins_with_bot_mention?(text, client.names)

  ["#{client.name} #{text}", text]
end
permitted?(_client, _data, _match) click to toggle source

Intended to be overridden by subclasses to hook in an authorization mechanism.

# File lib/slack-ruby-bot/commands/base.rb, line 152
def permitted?(_client, _data, _match)
  true
end