module Boty class Bot include Boty::Logger attr_reader :id, :name, :trigger_message def initialize(bot_info, session) Locale.reload @raw_info, @id, @name = bot_info, bot_info["id"], bot_info["name"] @handlers ||= [] @commands ||= [] @events = {} ScriptLoader.new(self).load on :message, &method(:message_handler) end def event(data) return unless type = event_type(data) @events[type].each do |action| action.call data end end def on(event_type, &block) @events[event_type.to_sym] ||= [] @events[event_type.to_sym] << block end def off(event_type, &block) if block_given? @events[event_type].delete_if { |b| b == block } else @events[event_type] = [] end end def match(regex, &block) @handlers << create_action(regex, &block) end def no_match(regex, &block) @handlers.delete_if do |action| action.is_this? regex, block end end def respond(regex, &block) @commands << create_action(regex, &block) end def no_respond(regex, &block) @commands.delete_if do |action| action.is_this? regex, block end end def no(command) @handlers.delete_if do |action| action.desc.command == command end @commands.delete_if do |action| action.desc.command == command end end def say(message, api_parameters = {}) channel = (@trigger_message && @trigger_message.channel) || "general" options = { channel: channel }.merge api_parameters post_response = Slack.chat.post_message message, options logger.debug { "post response: #{post_response}" } end def desc(command, description = nil) @current_desc = { command: command, description: description } end def know_how descriptions = (Array(@commands) + Array(@handlers)).compact.map(&:desc) descriptions.inject({}) { |hsh, desc| hsh.merge!(desc.command => desc.description) } end def im(message) logger.debug { "sending im messge to #{@trigger_message.user.name}" } Slack.chat.post_im @trigger_message.user.id, message end def brain @brain ||= {} end private def event_type(data) type = data["type"].to_sym logger.debug { "bot specifc event[#{type}] arrived: #{data}" } unless @events[type] logger.debug "no action binded to #{type}" return end type end def create_action(regex, &block) Boty::Action.new(regex, @current_desc, &block).tap { @current_desc = nil } end def message_from_bot_itself?(data) data["user"] == self.id || data["user"] == self.name end def has_valid_mention?(data) return false if message_from_bot_itself? data !!(/(<@#{id}|#{name}>)/ =~ data["text"]) end def message_handler(data) actions = has_valid_mention?(data) ? @commands : @handlers @trigger_message = Message.new data begin Array(actions).each do |action| action.execute self, @trigger_message end ensure @trigger_message = nil end end end end