class BeerBot::Bot

Represents a sequence of BotModule instances.

Attributes

module_names[RW]
module_path[RW]

Public Class Methods

new() click to toggle source
Calls superclass method
# File lib/beerbot/01.bot/Bot.rb, line 19
def initialize
  super()
end

Public Instance Methods

action(action,from:nil,to:nil,me:false,config:nil) click to toggle source
# File lib/beerbot/01.bot/Bot.rb, line 158
def action action,from:nil,to:nil,me:false,config:nil
  self.run(:action,action,from:from,to:to,me:me,config:config)
end
cmd(msg,from:nil,to:nil,me:false,config:nil) click to toggle source

Process messages addressed directly to the bot.

# File lib/beerbot/01.bot/Bot.rb, line 140
def cmd msg,from:nil,to:nil,me:false,config:nil
  if @cmd then
    @cmd.call(msg,from:from,to:to,config:config,me:me)
  else
    self.run(:cmd,msg,from:from,to:to,config:config,me:me)
  end
end
event(event,**kargs) click to toggle source

Handle events other than being messaged.

IRC events like joining channels, changing nicks etc.

Both event and kargs is dependent on the dispatcher which in turn is dependent on how the protocol (eg irc) is parsed.

# File lib/beerbot/01.bot/Bot.rb, line 169
def event event,**kargs
  self.run(:event,event,**kargs)
end
has_errors() click to toggle source
# File lib/beerbot/01.bot/Bot.rb, line 91
def has_errors
  if self.find{|bot_module| !bot_module[:status]} then
    true
  else
    false
  end
end
hear(msg,from:nil,to:nil,me:false,config:nil) click to toggle source

Process messages the bot overhears.

# File lib/beerbot/01.bot/Bot.rb, line 150
def hear msg,from:nil,to:nil,me:false,config:nil
  if @hear then
    @hear.call(msg,from:from,to:to,me:me,config:config)
  else
    self.run(:hear,msg,from:from,to:to,me:me,config:config)
  end
end
help(arr,from:nil,to:nil,config:nil,me:false) click to toggle source
# File lib/beerbot/01.bot/Bot.rb, line 173
def help arr,from:nil,to:nil,config:nil,me:false
  m = []
  modname,*topics = arr

  # "help"

  if arr.empty? then
    helplist = self.valid_modules.select {|bot_module|
      bot_module[:mod].respond_to?(:help)
    }.map{|bot_module|
      bot_module[:name]
    }
    reply = [
      {
        to:from,
        msg:"To issue commands to the bot over a channel, you need to start with a command prefix like ','."
      },
      {
        to:from,
        msg:"Modules (type: help <module-name>): "+helplist.join('; ')
      }
    ]

  # "help modname [subtopic [... [... etc]]]"

  else

    bot_module = self.valid_modules.find{|bot_module|
      bot_module[:name]==modname
    }

    # Can't find module...
    if bot_module.nil? then
      reply = [to:to,msg:"Don't know this topic #{from}"]

    # Can find module...
    else

      mod = bot_module[:mod]
      reply = []


      # Module has help...
      if mod.respond_to?(:help) then
        arr = mod.help(topics)

        if !arr || arr.empty? then
          reply += [to:from,msg:"hmmm, the module didn't say anything..."]
        else
          if topics.empty? then
            reply += [to:from,msg:"Note: modules should list topics which you can access like: help #{modname} <topic>"]
          end
          reply += arr.map{|a| {to:from,msg:a}}
        end

      # Module doesn't have help...
      else
        reply += [to:from,msg:"type: #{modname} doesn't seem to have any help"]
      end
    end

  end

  if not me then
    reply += [to:to,msg:"pm'ing you #{from}"]
  end
  return reply
end
init(config) click to toggle source

Call all init methods on bot modules that have them.

Should only be called once.

# File lib/beerbot/01.bot/Bot.rb, line 27
def init config
  self.valid_modules.each {|botmodule|
    if botmodule[:mod].respond_to?(:init) then
      botmodule[:mod].init(config)
    end
  }
end
load!(module_names, module_path) click to toggle source

Purge existing modules from this array and load modules with names in module_names in module_path on disk into memory.

MODULE NAMES and MODULE PATH:

Best understood like this:

"#{module_path}/#{name}/*" = location of modules
modname = "::BeerBot::Modules::#{name}"
# File lib/beerbot/01.bot/Bot.rb, line 54
def load! module_names, module_path
  @module_path = module_path
  @module_names = module_names
  self.reject!{true} unless self.empty?  # ick :)
  Dir.chdir(module_path) {
    module_names.each {|name|
      initfile = "#{name}/init.rb"
      modname = "::BeerBot::Modules::#{name}"
      mod = nil
      err = [
        [:nodir,!File.directory?(name)],
        [:badname,name !~ /^[A-Z]/  ],
        [:noinit,!File.exists?(initfile)],
      ].select{|e| e[1]}
      ok = (err.size == 0)

      if ok then
        puts "loading #{initfile}..."
        load(initfile)
        mod = Object.const_get(modname)
        if mod.respond_to?(:instance) then
          mod = mod.instance
        end
      else
        p [initfile,err]
        raise "Can't load (some) modules."
      end

      bm = BotModule.new(
        name,status:ok,mod:mod,
        modname:modname,errors:err
      )
      self.push(bm)
    }
  }
end
run(meth,*args,**kargs) click to toggle source

Call :meth on valid (loaded) modules and maybe accumulate result or return first valid response…

Converts return value to ARRAY FORMAT if not already.

The array could be empty, which means nothing was returned (or we couldn’t interpret the output of the bot modules).

We expect each bot_module to return nil or a botmsg (Hash, Array or Proc that returns the first two).

At the moment, we use inject and break on first valid response…

# File lib/beerbot/01.bot/Bot.rb, line 119
def run meth,*args,**kargs
  self.valid_modules.inject([]) {|arr,bot_module|
    name,mod = bot_module.values_at(:name,:mod)
    unless mod.respond_to?(meth) then
      next arr
    end
    reply = mod.send(meth,*args,**kargs)
    suppress,botmsg = BotMsg.to_reply_format(reply)
    if botmsg then
      arr += botmsg
    end
    if suppress then
      break arr
    else
      arr
    end
  }
end
set_cmd(&block) click to toggle source

Override normal cmd processing with Proc.

You might want to do this to temporarily stop normal bot command behaviour in order for the bot to go into some sort of exclusive mode.

To disable normal response behaviour do:

bot.set_cmd {|msg,**kargs| nil }
bot.set_hear {|msg,**kargs| nil }

To unset,

bot.set_cmd
bot.set_hear
# File lib/beerbot/01.bot/Bot.rb, line 258
def set_cmd &block
  @cmd = block
end
set_hear(&block) click to toggle source

Override normal hear-processing with Proc.

See set_cmd.

# File lib/beerbot/01.bot/Bot.rb, line 266
def set_hear &block
  @hear = block
end
update_config(config) click to toggle source

Call config on all valid bot modules.

# File lib/beerbot/01.bot/Bot.rb, line 37
def update_config config
  self.valid_modules.each {|botmodule|
    if botmodule[:mod].respond_to?(:config) then
      botmodule[:mod].config(config)
    end
  }
end
valid_modules() click to toggle source

Return list of valid (loaded) modules.

# File lib/beerbot/01.bot/Bot.rb, line 101
def valid_modules
  self.select{|bot_module| bot_module[:status]}
end