FLOW

__copyright__ = 'this file is in the public domain'

  1. receive string from server
  2. make string into an ircevent
  3. basic handling of the ircevent
  4. check if the event is a command to the bot, if so execute it
  5. check to see if it triggers any callbacks

receive string and make it an ircevent

in gozerbot/irc.py:

# read on socket .. make ircevent .. call the handle_ievent method
res = self.fsock.readline()
ievent = Ircevent().parse(self, res)
self.handle_ievent(ievent)

basic handling of the ircevent

in gozerbot/bot.py:

def handle_ievent(self, ievent):
    """ call Irc class method .. add to backlog .. check for callbacks """
    j = Ircevent()
    Irc.handle_ievent(self, ievent)
    self.backlog.append(ievent)
    j.copyin(ievent)
    callbacks.check(self, j)

in gozerbot/irc.py:

def handle_ievent(self, ievent):
    """ handle ircevent .. dispatch to method """
    try:
        # see if the irc object has a method to handle the ievent
        method = getattr(self,'handle_' + ievent.cmnd.lower())
        # try to call method
        try:
            method(ievent)
        except:
            handle_exception()
    except AttributeError:
        pass
    # see if there are wait callbacks
    self.wait.check(ievent)

this will call a function handle_CMND on the bot.

command handling

in gozerbot/bot.py:

the handle_privmsg function handles the PRIVMSG commands and checks if a command is given and if so calls plugins.trydispatch()

in gozerbot/plugins.py:

the trydispatch function checks if the user should be ignored, if not checks for pipelining or multiple commands. in case of pipelining the ircevent queues entry will be chained. each command runs a dispatch function in its own thread. variables: what is one of redispatcher of commands object, com is the command triggered, bot is the bot on which the command is given and ievent is the ircevent that triggered the command

def dispatch(self, what, com, bot, ievent):
    """ dispatch ievent """
    if bot.stopped:
        return 0
    # check for user provided channel
    makeargrest(ievent)
    ievent.usercmnd = 1
    commandhandler.put(ievent.speed, what, com, bot, ievent)
    addievent(ievent.userhost, ievent)
    return 1

dispatch pushes the triggered command to the commandhandler. this will allow use to do priority based scheduling of commands

in gozerbot/eventhandler.py:

through the commandhandler the dispatch function of the redispatcher or commands object is called with command bot and ievent passed as argument

what.dispatch(com, bot, ievent)

in gozerbot/redispatcher.py or gozerbot/commands.py:

this is were the actual dispatch is taking place, the command or re callback gets two arguments passed .. the bot and the ircevent

def dispatch(self, com, bot, ievent):
    """ dispatch on ircevent """
    if bot.stopped:
        return 0
    # execute command
    if com.threaded:
        thr.start_bot_command(com.func, (bot, ievent))
    else:
        try:
            com.func(bot, ievent)
        except Exception, ex:
            handle_exception(ievent)
            return 0
    return 1

callback handling

in gozerbot/callbacks.py:

this functions checks to see if any callback for an ircevent is registered and if so calls self.callback that will do the actual firing of the callback.

def check(self, bot, ievent):
    """ check for callbacks to be fired """
    # check for "ALL" callbacks
    if self.cbs.has_key('ALL'):
        for cb in self.cbs['ALL']:
            self.callback(cb, bot, ievent)
    cmnd = ievent.cmnd.upper()
    # check for CMND callbacks
    if self.cbs.has_key(cmnd):
        for cb in self.cbs[cmnd]:
            self.callback(cb, bot, ievent)

snippet of self.callback:

every callback has a optional test function that is used to determine if the callback should fire or not .. cb.prereq. the actual callback is called in its own thread or in the main bot loop

# see if the callback pre requirement succeeds
if cb.prereq:
    rlog(-10, 'callback', 'excecuting in loop %s' % str(cb.prereq))
    if not cb.prereq(bot, ievent):
        return
# check if callback function is there
if not cb.func:
    return
# start callback in its own thread
rlog(-10, 'callback', 'excecuting callback %s' % str(cb.func))
if cb.threaded:
    thr.start_new_thread(cb.func, (bot, ievent), cb.kwargs)
else:
    cb.func(bot, ievent, **cb.kwargs)