remove replypath and all the places it was used.

with alias calling do() internally, there is no need for all this
replypath nonsense, and if there's ever a module that needs to reply
to stuff on its own outside of do(), it'd have to be implementing
all of this anyway, so it was pretty irrelevant.

this makes DrBotIRC alias/recursion stuff a bit cleaner.
This commit is contained in:
Brian S. Stephan 2011-01-07 23:09:07 -06:00
parent dbf02723e0
commit 359ca24856
19 changed files with 114 additions and 145 deletions

View File

@ -135,9 +135,9 @@ class DrBotIRC(irclib.IRC):
except NoOptionError: pass except NoOptionError: pass
except NoSectionError: pass except NoSectionError: pass
return self.reply(connection, replypath, self.try_recursion(connection, event, nick, userhost, None, what, admin_unlocked)) return self.reply(connection, replypath, self.try_recursion(connection, event, nick, userhost, what, admin_unlocked))
def try_alias(self, connection, event, nick, userhost, replypath, what, admin_unlocked): def try_alias(self, connection, event, nick, userhost, what, admin_unlocked):
# try doing alias work # try doing alias work
try: try:
alias_list = self.config.options('Alias') alias_list = self.config.options('Alias')
@ -149,23 +149,16 @@ class DrBotIRC(irclib.IRC):
command = re.sub(alias, self.config.get('Alias', alias), what) command = re.sub(alias, self.config.get('Alias', alias), what)
# i guess someone could have an alias of an alias... try again # i guess someone could have an alias of an alias... try again
command = self.try_alias(connection, event, nick, userhost, replypath, command, admin_unlocked) command = self.try_alias(connection, event, nick, userhost, command, admin_unlocked)
return self.reply(connection, replypath, command) return command
except NoOptionError: pass except NoOptionError: pass
except NoSectionError: pass except NoSectionError: pass
# if we got here, there are no matching aliases, so return what we got # if we got here, there are no matching aliases, so return what we got
return self.reply(connection, replypath, what) return what
def reply(self, connection, replypath, replystr, stop_responding=False): def reply(self, connection, replypath, replystr, stop_responding=False):
""" """Reply over IRC to replypath or return a string with the reply."""
Reply over IRC to replypath or return a string with the reply.
Utility method to do the proper type of reply (either to IRC, or as a return
to caller) depending on the target. Pretty simple, and included in the base
class for convenience. It should be the last step for callers:
return self.reply(connection, replypath, 'hello')
"""
if replystr is not None: if replystr is not None:
if replypath is None: if replypath is None:
@ -175,7 +168,7 @@ class DrBotIRC(irclib.IRC):
if stop_responding: if stop_responding:
return "NO MORE" return "NO MORE"
def try_recursion(self, connection, event, nick, userhost, replypath, what, admin_unlocked): def try_recursion(self, connection, event, nick, userhost, what, admin_unlocked):
"""Scan message for subcommands to execute and use as part of this command. """Scan message for subcommands to execute and use as part of this command.
Upon seeing a line intended for this module, see if there are subcommands Upon seeing a line intended for this module, see if there are subcommands
@ -190,7 +183,7 @@ class DrBotIRC(irclib.IRC):
attempt = what attempt = what
# check for aliases # check for aliases
attempt = self.try_alias(connection, event, nick, userhost, replypath, attempt, admin_unlocked) attempt = self.try_alias(connection, event, nick, userhost, attempt, admin_unlocked)
# begin recursion search # begin recursion search
@ -201,27 +194,27 @@ class DrBotIRC(irclib.IRC):
if start_idx == -1 or end_idx == -1 or len(subcmd) == 0: if start_idx == -1 or end_idx == -1 or len(subcmd) == 0:
# no recursion, so see if there's a module to handle this # no recursion, so see if there's a module to handle this
return self.reply(connection, replypath, self.scan_modules(connection, event, nick, userhost, replypath, attempt, admin_unlocked)) return self.scan_modules(connection, event, nick, userhost, attempt, admin_unlocked)
else: else:
# found recursion, search again # found recursion, search again
ret = self.try_recursion(connection, event, nick, userhost, None, subcmd, admin_unlocked) ret = self.try_recursion(connection, event, nick, userhost, subcmd, admin_unlocked)
if ret is not None: if ret is not None:
# recursion search had a hit, replace [foo] with it and re-recurse # recursion search had a hit, replace [foo] with it and re-recurse
return self.reply(connection, replypath, self.try_recursion(connection, event, nick, userhost, replypath, attempt.replace('['+subcmd+']', ret), admin_unlocked)) return self.try_recursion(connection, event, nick, userhost, attempt.replace('['+subcmd+']', ret), admin_unlocked)
else: else:
# recursion search didn't have a hit, so see if there's a module to handle this # recursion search didn't have a hit, so see if there's a module to handle this
return self.reply(connection, replypath, self.scan_modules(connection, event, nick, userhost, replypath, attempt, admin_unlocked)) return self.scan_modules(connection, event, nick, userhost, attempt, admin_unlocked)
def scan_modules(self, connection, event, nick, userhost, replypath, attempt, admin_unlocked): def scan_modules(self, connection, event, nick, userhost, attempt, admin_unlocked):
"""Walk the loaded modules, see if any reply to input text.""" """Walk the loaded modules, see if any reply to input text."""
# aliases resolved. run result against each module # aliases resolved. run result against each module
for module in self.modlist: for module in self.modlist:
ret = module.do(connection, event, nick, userhost, replypath, attempt, admin_unlocked) ret = module.do(connection, event, nick, userhost, attempt, admin_unlocked)
if ret is not None: if ret is not None:
# a module had a result for us, post-alias, so return it # a module had a result for us, post-alias, so return it
# TODO: scan all modules with compounding results # TODO: scan all modules with compounding results
return self.reply(connection, replypath, ret) return ret
def quit_irc(self, connection, msg): def quit_irc(self, connection, msg):
for module in self.modlist: for module in self.modlist:

View File

@ -90,23 +90,6 @@ class Module(object):
Implement this to close databases, write to disk, etc. Implement this to close databases, write to disk, etc.
""" """
def reply(self, connection, replypath, replystr, stop_responding=False):
"""Reply over IRC to replypath or return a string with the reply.
Utility method to do the proper type of reply (either to IRC, or as a return
to caller) depending on the target. Pretty simple, and included in the base
class for convenience. It should be the last step for callers:
return self.reply(connection, replypath, 'hello')
"""
if replystr is not None:
if replypath is None:
return replystr
else:
connection.privmsg(replypath, replystr)
if stop_responding:
return "NO MORE"
def remove_metaoptions(self, list): def remove_metaoptions(self, list):
"""Remove metaoptions from provided list, which was probably from a config file.""" """Remove metaoptions from provided list, which was probably from a config file."""
@ -160,7 +143,7 @@ class Module(object):
Set up the database tables and so on, if subclass is planning on using it. Set up the database tables and so on, if subclass is planning on using it.
""" """
def do(self, connection, event, nick, userhost, replypath, what, admin_unlocked): def do(self, connection, event, nick, userhost, what, admin_unlocked):
"""Do the primary thing this module was intended to do, in most cases. """Do the primary thing this module was intended to do, in most cases.
Implement this method in your subclass to have a fairly-automatic hook into Implement this method in your subclass to have a fairly-automatic hook into

View File

@ -31,7 +31,7 @@ class Countdown(Module):
"""Class that adds a countdown item to the bot.""" """Class that adds a countdown item to the bot."""
def do(self, connection, event, nick, userhost, replypath, what, admin_unlocked): def do(self, connection, event, nick, userhost, what, admin_unlocked):
"""Add/retrieve countdown items.""" """Add/retrieve countdown items."""
match = re.search('^!countdown\s+add\s+(\S+)\s+(.*)$', what) match = re.search('^!countdown\s+add\s+(\S+)\s+(.*)$', what)
@ -44,7 +44,7 @@ class Countdown(Module):
self.config.set(self.__class__.__name__, item, target.astimezone(tzutc()).isoformat()) self.config.set(self.__class__.__name__, item, target.astimezone(tzutc()).isoformat())
replystr = 'added countdown item ' + item replystr = 'added countdown item ' + item
return self.reply(connection, replypath, replystr) return replystr
match = re.search('^!countdown\s+remove\s+(\S+)$', what) match = re.search('^!countdown\s+remove\s+(\S+)$', what)
if match: if match:
@ -52,7 +52,7 @@ class Countdown(Module):
item = match.group(1) item = match.group(1)
if self.config.remove_option(self.__class__.__name__, item): if self.config.remove_option(self.__class__.__name__, item):
replystr = 'removed countdown item ' + item replystr = 'removed countdown item ' + item
return self.reply(connection, replypath, replystr) return replystr
except NoSectionError: pass except NoSectionError: pass
match = re.search('^!countdown\s+list$', what) match = re.search('^!countdown\s+list$', what)
@ -62,7 +62,7 @@ class Countdown(Module):
self.remove_metaoptions(cdlist) self.remove_metaoptions(cdlist)
cdlist.sort() cdlist.sort()
liststr = ', '.join(cdlist) liststr = ', '.join(cdlist)
return self.reply(connection, replypath, liststr) return liststr
except NoSectionError: pass except NoSectionError: pass
match = re.search('^!countdown\s+(\S+)$', what) match = re.search('^!countdown\s+(\S+)$', what)
@ -103,7 +103,7 @@ class Countdown(Module):
if rdelta.seconds > 1: if rdelta.seconds > 1:
relstr += 's' relstr += 's'
relstr += ', ' relstr += ', '
return self.reply(connection, replypath, relstr[0:-2]) return relstr[0:-2]
except NoOptionError: pass except NoOptionError: pass
# vi:tabstop=4:expandtab:autoindent # vi:tabstop=4:expandtab:autoindent

View File

@ -260,7 +260,7 @@ class Dice(Module):
global output global output
return output return output
def do(self, connection, event, nick, userhost, replypath, what, admin_unlocked): def do(self, connection, event, nick, userhost, what, admin_unlocked):
match = re.search('^!roll\s+(.*)$', what) match = re.search('^!roll\s+(.*)$', what)
if match: if match:
dicestr = match.group(1) dicestr = match.group(1)
@ -268,7 +268,7 @@ class Dice(Module):
yacc.parse(dicestr) yacc.parse(dicestr)
reply = self.get_result() reply = self.get_result()
if reply is not "": if reply is not "":
return self.reply(connection, replypath, nick + ': ' + reply) return nick + ': ' + reply
match = re.search('^!ctech\s+(.*)$', what) match = re.search('^!ctech\s+(.*)$', what)
if match: if match:
@ -373,7 +373,7 @@ class Dice(Module):
if count is not len(rollitrs)-1: if count is not len(rollitrs)-1:
reply += "; " reply += "; "
if reply is not "": if reply is not "":
return self.reply(connection, replypath, nick + ': ' + reply) return nick + ': ' + reply
# vi:tabstop=4:expandtab:autoindent # vi:tabstop=4:expandtab:autoindent
# kate: indent-mode python;indent-width 4;replace-tabs on; # kate: indent-mode python;indent-width 4;replace-tabs on;

View File

@ -26,12 +26,12 @@ class Echo(Module):
"""Repeat provided text.""" """Repeat provided text."""
def do(self, connection, event, nick, userhost, replypath, what, admin_unlocked): def do(self, connection, event, nick, userhost, what, admin_unlocked):
"""Repeat provided text.""" """Repeat provided text."""
match = re.search('^!echo\s+(.*)$', what) match = re.search('^!echo\s+(.*)$', what)
if match: if match:
return self.reply(connection, replypath, match.group(1)) return match.group(1)
# vi:tabstop=4:expandtab:autoindent # vi:tabstop=4:expandtab:autoindent
# kate: indent-mode python;indent-width 4;replace-tabs on; # kate: indent-mode python;indent-width 4;replace-tabs on;

View File

@ -57,13 +57,13 @@ class EightBall(Module):
self.responses.append('Outlook not so good.') self.responses.append('Outlook not so good.')
self.responses.append('Very doubtful.') self.responses.append('Very doubtful.')
def do(self, connection, event, nick, userhost, replypath, what, admin_unlocked): def do(self, connection, event, nick, userhost, what, admin_unlocked):
"""Determine the response to the question. Spoiler alert: it's random.""" """Determine the response to the question. Spoiler alert: it's random."""
match = re.search('^!8ball', what) match = re.search('^!8ball', what)
if match: if match:
response = self.responses[random.randint(1,len(self.responses))-1] response = self.responses[random.randint(1,len(self.responses))-1]
return self.reply(connection, replypath, response) return response
# vi:tabstop=4:expandtab:autoindent # vi:tabstop=4:expandtab:autoindent
# kate: indent-mode python;indent-width 4;replace-tabs on; # kate: indent-mode python;indent-width 4;replace-tabs on;

View File

@ -29,7 +29,7 @@ class FactFile(Module):
"""Return a random fact/quote/whatever from one or more files.""" """Return a random fact/quote/whatever from one or more files."""
def do(self, connection, event, nick, userhost, replypath, what, admin_unlocked): def do(self, connection, event, nick, userhost, what, admin_unlocked):
"""Search for a fact, or return a random one.""" """Search for a fact, or return a random one."""
whats = what.split(' ') whats = what.split(' ')
@ -53,7 +53,7 @@ class FactFile(Module):
to_print = facts[random.randint(1, len(facts))-1] to_print = facts[random.randint(1, len(facts))-1]
# return text # return text
return self.reply(connection, replypath, to_print.rstrip()) return to_print.rstrip()
else: else:
print('filename in config file for \'' + whats[0] + '\' is wrong') print('filename in config file for \'' + whats[0] + '\' is wrong')

View File

@ -56,7 +56,7 @@ class Facts(Module):
print("sqlite error: " + str(e)) print("sqlite error: " + str(e))
raise raise
def do(self, connection, event, nick, userhost, replypath, what, admin_unlocked): def do(self, connection, event, nick, userhost, what, admin_unlocked):
"""Add or retrieve a fact from the database.""" """Add or retrieve a fact from the database."""
try: try:
@ -70,7 +70,7 @@ class Facts(Module):
cur.execute('''INSERT INTO facts_facts (category, fact, who, userhost) cur.execute('''INSERT INTO facts_facts (category, fact, who, userhost)
VALUES (?, ?, ?, ?)''', (category, fact, nick, userhost)) VALUES (?, ?, ?, ?)''', (category, fact, nick, userhost))
db.commit() db.commit()
return self.reply(connection, replypath, category + ' added.') return category + ' added.'
match = re.search('^!facts\s+(\S+)\s+(.*)$', what) match = re.search('^!facts\s+(\S+)\s+(.*)$', what)
if match: if match:
@ -80,7 +80,7 @@ class Facts(Module):
facts = category_facts.fetchall() facts = category_facts.fetchall()
if len(facts) > 0: if len(facts) > 0:
fact = facts[random.randint(1,len(facts))-1] fact = facts[random.randint(1,len(facts))-1]
return self.reply(connection, replypath, fact['fact'].rstrip().encode('utf-8', 'ignore')) return fact['fact'].rstrip().encode('utf-8', 'ignore')
match = re.search('^!facts\s+(\S+)$', what) match = re.search('^!facts\s+(\S+)$', what)
if match: if match:
@ -89,10 +89,10 @@ class Facts(Module):
facts = category_facts.fetchall() facts = category_facts.fetchall()
if len(facts) > 0: if len(facts) > 0:
fact = facts[random.randint(1,len(facts))-1] fact = facts[random.randint(1,len(facts))-1]
return self.reply(connection, replypath, fact['fact'].rstrip().encode('utf-8', 'ignore')) return fact['fact'].rstrip().encode('utf-8', 'ignore')
except sqlite3.Error as e: except sqlite3.Error as e:
return self.reply(connection, replypath, "sqlite error: " + str(e)) return "sqlite error: " + str(e)
# vi:tabstop=4:expandtab:autoindent # vi:tabstop=4:expandtab:autoindent
# kate: indent-mode python;indent-width 4;replace-tabs on; # kate: indent-mode python;indent-width 4;replace-tabs on;

View File

@ -31,7 +31,7 @@ class GoogleTranslate(Module):
http://code.google.com/apis/ajaxlanguage/documentation/ http://code.google.com/apis/ajaxlanguage/documentation/
""" """
def do(self, connection, event, nick, userhost, replypath, what, admin_unlocked): def do(self, connection, event, nick, userhost, what, admin_unlocked):
"""Query Google for weather info. """Query Google for weather info.
Leaves the input alone to let google make the best guess. Leaves the input alone to let google make the best guess.
@ -61,7 +61,7 @@ class GoogleTranslate(Module):
translation = translation.replace('\\u0026gt;', '>') translation = translation.replace('\\u0026gt;', '>')
translation = translation.replace('\\u0026#39;', '\'') translation = translation.replace('\\u0026#39;', '\'')
return self.reply(connection, replypath, translation) return translation
# vi:tabstop=4:expandtab:autoindent # vi:tabstop=4:expandtab:autoindent
# kate: indent-mode python;indent-width 4;replace-tabs on; # kate: indent-mode python;indent-width 4;replace-tabs on;

View File

@ -52,7 +52,7 @@ class IrcAdmin(Module):
connection.join(channel) connection.join(channel)
except NoOptionError: pass except NoOptionError: pass
def do(self, connection, event, nick, userhost, replypath, what, admin_unlocked): def do(self, connection, event, nick, userhost, what, admin_unlocked):
"""Try all the admin methods.""" """Try all the admin methods."""
# TODO: sophisticate. also, document all of these # TODO: sophisticate. also, document all of these
@ -60,51 +60,47 @@ class IrcAdmin(Module):
whats = what.split(' ') whats = what.split(' ')
if whats[0] == '!join' and admin_unlocked and len(whats) >= 2: if whats[0] == '!join' and admin_unlocked and len(whats) >= 2:
return self.sub_join_channel(connection, event, nick, userhost, replypath, what, admin_unlocked) return self.sub_join_channel(connection, event, nick, userhost, what, admin_unlocked)
elif whats[0] == '!part' and admin_unlocked and len(whats) >= 2: elif whats[0] == '!part' and admin_unlocked and len(whats) >= 2:
return self.sub_part_channel(connection, event, nick, userhost, replypath, what, admin_unlocked) return self.sub_part_channel(connection, event, nick, userhost, what, admin_unlocked)
elif whats[0] == '!quit' and admin_unlocked: elif whats[0] == '!quit' and admin_unlocked:
return self.sub_quit_irc(connection, event, nick, userhost, replypath, what, admin_unlocked) return self.sub_quit_irc(connection, event, nick, userhost, what, admin_unlocked)
elif whats[0] == '!autojoin' and admin_unlocked and len(whats) >= 3: elif whats[0] == '!autojoin' and admin_unlocked and len(whats) >= 3:
return self.sub_autojoin_manipulate(connection, event, nick, userhost, replypath, what, admin_unlocked) return self.sub_autojoin_manipulate(connection, event, nick, userhost, what, admin_unlocked)
elif whats[0] == '!config' and whats[1] == 'save' and admin_unlocked: elif whats[0] == '!config' and whats[1] == 'save' and admin_unlocked:
return self.reply(connection, replypath, self.irc.save_config()) return self.irc.save_config()
elif whats[0] == '!nick' and admin_unlocked and len(whats) >= 2: elif whats[0] == '!nick' and admin_unlocked and len(whats) >= 2:
return self.sub_change_nick(connection, event, nick, userhost, replypath, what, admin_unlocked) return self.sub_change_nick(connection, event, nick, userhost, what, admin_unlocked)
elif whats[0] == '!load' and admin_unlocked and len(whats) >= 2: elif whats[0] == '!load' and admin_unlocked and len(whats) >= 2:
return self.sub_load_module(connection, event, nick, userhost, replypath, what, admin_unlocked) return self.sub_load_module(connection, event, nick, userhost, what, admin_unlocked)
elif whats[0] == '!reload' and admin_unlocked and len(whats) >= 2: elif whats[0] == '!reload' and admin_unlocked and len(whats) >= 2:
return self.sub_reload_module(connection, event, nick, userhost, replypath, what, admin_unlocked) return self.sub_reload_module(connection, event, nick, userhost, what, admin_unlocked)
elif whats[0] == '!unload' and admin_unlocked and len(whats) >= 2: elif whats[0] == '!unload' and admin_unlocked and len(whats) >= 2:
return self.sub_unload_module(connection, event, nick, userhost, replypath, what, admin_unlocked) return self.sub_unload_module(connection, event, nick, userhost, what, admin_unlocked)
def sub_join_channel(self, connection, event, nick, userhost, replypath, what, admin_unlocked): def sub_join_channel(self, connection, event, nick, userhost, what, admin_unlocked):
whats = what.split(' ') whats = what.split(' ')
channel = whats[1] channel = whats[1]
if irclib.is_channel(channel): if irclib.is_channel(channel):
connection.join(channel) connection.join(channel)
replystr = 'Joined ' + channel + '.' replystr = 'Joined ' + channel + '.'
return self.reply(connection, replypath, replystr) return replystr
def sub_part_channel(self, connection, event, nick, userhost, replypath, what, admin_unlocked): def sub_part_channel(self, connection, event, nick, userhost, what, admin_unlocked):
whats = what.split(' ') whats = what.split(' ')
channel = whats[1] channel = whats[1]
if irclib.is_channel(channel): if irclib.is_channel(channel):
connection.part(channel, ' '.join(whats[2:])) connection.part(channel, ' '.join(whats[2:]))
replystr = 'Parted ' + channel + '.' replystr = 'Parted ' + channel + '.'
return self.reply(connection, replypath, replystr) return replystr
def sub_quit_irc(self, connection, event, nick, userhost, replypath, what, admin_unlocked): def sub_quit_irc(self, connection, event, nick, userhost, what, admin_unlocked):
whats = what.split(' ') whats = what.split(' ')
if replypath is not None:
connection.privmsg(replypath, 'Quitting...')
self.irc.quit_irc(connection, ' '.join(whats[1:])) self.irc.quit_irc(connection, ' '.join(whats[1:]))
def sub_autojoin_manipulate(self, connection, event, nick, userhost, replypath, what, admin_unlocked): def sub_autojoin_manipulate(self, connection, event, nick, userhost, what, admin_unlocked):
whats = what.split(' ') whats = what.split(' ')
if whats[1] == 'add': if whats[1] == 'add':
@ -116,7 +112,7 @@ class IrcAdmin(Module):
channelset.add(channel) channelset.add(channel)
self.config.set(self.__class__.__name__, 'autojoin', ','.join(channelset)) self.config.set(self.__class__.__name__, 'autojoin', ','.join(channelset))
replystr = 'Added ' + channel + ' to autojoin.' replystr = 'Added ' + channel + ' to autojoin.'
return self.reply(connection, replypath, replystr) return replystr
except NoOptionError: pass except NoOptionError: pass
elif whats[1] == 'remove': elif whats[1] == 'remove':
try: try:
@ -127,39 +123,39 @@ class IrcAdmin(Module):
channelset.discard(channel) channelset.discard(channel)
self.config.set(self.__class__.__name__, 'autojoin', ','.join(channelset)) self.config.set(self.__class__.__name__, 'autojoin', ','.join(channelset))
replystr = 'Removed ' + channel + ' from autojoin.' replystr = 'Removed ' + channel + ' from autojoin.'
return self.reply(connection, replypath, replystr) return replystr
except NoOptionError: pass except NoOptionError: pass
def sub_change_nick(self, connection, event, nick, userhost, replypath, what, admin_unlocked): def sub_change_nick(self, connection, event, nick, userhost, what, admin_unlocked):
whats = what.split(' ') whats = what.split(' ')
newnick = whats[1] newnick = whats[1]
connection.nick(newnick) connection.nick(newnick)
self.config.set('dr.botzo', 'nick', newnick) self.config.set('dr.botzo', 'nick', newnick)
replystr = 'changed nickname' replystr = 'changed nickname'
return self.reply(connection, replypath, replystr) return replystr
def sub_load_module(self, connection, event, nick, userhost, replypath, what, admin_unlocked): def sub_load_module(self, connection, event, nick, userhost, what, admin_unlocked):
"""Load a module (in both the python and dr.botzo sense) if not """Load a module (in both the python and dr.botzo sense) if not
already loaded. already loaded.
""" """
whats = what.split(' ') whats = what.split(' ')
return self.reply(connection, replypath, self.irc.load_module(whats[1])) return self.irc.load_module(whats[1])
def sub_unload_module(self, connection, event, nick, userhost, replypath, what, admin_unlocked): def sub_unload_module(self, connection, event, nick, userhost, what, admin_unlocked):
"""Attempt to unload and del a module if it's loaded.""" """Attempt to unload and del a module if it's loaded."""
whats = what.split(' ') whats = what.split(' ')
return self.reply(connection, replypath, self.irc.unload_module(whats[1])) return self.irc.unload_module(whats[1])
def sub_reload_module(self, connection, event, nick, userhost, replypath, what, admin_unlocked): def sub_reload_module(self, connection, event, nick, userhost, what, admin_unlocked):
"""Attempt to reload a module, by removing it from memory and then """Attempt to reload a module, by removing it from memory and then
re-initializing it. re-initializing it.
""" """
whats = what.split(' ') whats = what.split(' ')
return self.reply(connection, replypath, self.irc.reload_module(whats[1])) return self.irc.reload_module(whats[1])
# vi:tabstop=4:expandtab:autoindent # vi:tabstop=4:expandtab:autoindent
# kate: indent-mode python;indent-width 4;replace-tabs on; # kate: indent-mode python;indent-width 4;replace-tabs on;

View File

@ -93,19 +93,19 @@ class Karma(Module):
print("sqlite error: " + str(e)) print("sqlite error: " + str(e))
raise raise
def do(self, connection, event, nick, userhost, replypath, what, admin_unlocked): def do(self, connection, event, nick, userhost, what, admin_unlocked):
"""look for karma strings at the start of messages""" """look for karma strings at the start of messages"""
if (self.karmare.search(what)): if (self.karmare.search(what)):
return self.handle_karma_change(connection, nick, userhost, replypath, what) return self.handle_karma_change(connection, nick, userhost, what)
elif (self.queryre.search(what)): elif (self.queryre.search(what)):
return self.handle_karma_query(connection, nick, userhost, replypath, what) return self.handle_karma_query(connection, nick, userhost, what)
elif (self.statre.search(what)): elif (self.statre.search(what)):
return self.handle_stat_query(connection, nick, userhost, replypath, what) return self.handle_stat_query(connection, nick, userhost, what)
elif (self.reportre.search(what)): elif (self.reportre.search(what)):
return self.handle_report_query(connection, nick, userhost, replypath, what) return self.handle_report_query(connection, nick, userhost, what)
def handle_karma_change(self, connection, nick, userhost, replypath, what): def handle_karma_change(self, connection, nick, userhost, what):
""" """
handle the karma change and storage. handle the karma change and storage.
""" """
@ -113,15 +113,15 @@ class Karma(Module):
key = match.group(1) if match.group(1) else match.group(2) key = match.group(1) if match.group(1) else match.group(2)
value = match.group(3) value = match.group(3)
if (value == '++'): if (value == '++'):
return self.reply(connection, replypath, self.karma_modify(key, 1, nick, userhost)) return self.karma_modify(key, 1, nick, userhost)
elif (value == '--'): elif (value == '--'):
return self.reply(connection, replypath, self.karma_modify(key, -1, nick, userhost)) return self.karma_modify(key, -1, nick, userhost)
elif (value == '+-'): elif (value == '+-'):
self.karma_modify(key, 1, nick, userhost) self.karma_modify(key, 1, nick, userhost)
return self.reply(connection, replypath, self.karma_modify(key, -1, nick, userhost)) return self.karma_modify(key, -1, nick, userhost)
elif (value == '-+'): elif (value == '-+'):
self.karma_modify(key, -1, nick, userhost) self.karma_modify(key, -1, nick, userhost)
return self.reply(connection, replypath, self.karma_modify(key, 1, nick, userhost)) return self.karma_modify(key, 1, nick, userhost)
def karma_modify(self, key, value, nick, userhost): def karma_modify(self, key, value, nick, userhost):
""" """
@ -140,7 +140,7 @@ class Karma(Module):
conn.rollback() conn.rollback()
return "sqlite error: " + str(e) return "sqlite error: " + str(e)
def handle_report_query(self, connection, nick, userhost, replypath, what): def handle_report_query(self, connection, nick, userhost, what):
match = self.reportre.search(what) match = self.reportre.search(what)
report = match.group(1) report = match.group(1)
@ -173,10 +173,10 @@ class Karma(Module):
message = '{header} {list}'.format(header=header, list=list) message = '{header} {list}'.format(header=header, list=list)
except sqlite3.Error as e: except sqlite3.Error as e:
conn.rollback() conn.rollback()
return self.reply(connection, replypath, "sqlite error: " + str(e)) return "sqlite error: " + str(e)
return self.reply(connection, replypath, message); return message
def handle_stat_query(self, connection, nick, userhost, replypath, what): def handle_stat_query(self, connection, nick, userhost, what):
match = self.statre.search(what) match = self.statre.search(what)
statnick = match.group(1) statnick = match.group(1)
@ -196,11 +196,11 @@ class Karma(Module):
reply = '{nick}: {statnick} has given {pos} postive karma and {neg} negative karma, for a total of {total} karma'.format(nick=nick, statnick=statnick, pos=pos, neg=neg, total=total) reply = '{nick}: {statnick} has given {pos} postive karma and {neg} negative karma, for a total of {total} karma'.format(nick=nick, statnick=statnick, pos=pos, neg=neg, total=total)
except sqlite3.Error as e: except sqlite3.Error as e:
return self.reply(connection, replypath, "sqlite error: " + str(e)) return "sqlite error: " + str(e)
return self.reply(connection, replypath, reply) return reply
def handle_karma_query(self, connection, nick, userhost, replypath, what): def handle_karma_query(self, connection, nick, userhost, what):
match = self.queryre.search(what) match = self.queryre.search(what)
key = match.group(1) key = match.group(1)
@ -224,9 +224,9 @@ class Karma(Module):
reply = '{nick}: {key} has {value[0]!s} points of karma (rank {rank})'.format( reply = '{nick}: {key} has {value[0]!s} points of karma (rank {rank})'.format(
nick=nick, key=key, value=value, rank=rank) nick=nick, key=key, value=value, rank=rank)
except sqlite3.Error as e: except sqlite3.Error as e:
return self.reply(connection, replypath, "sqlite error: " + str(e)) return "sqlite error: " + str(e)
return self.reply(connection, replypath, reply) return reply
if __name__ == "__main__": if __name__ == "__main__":
print "Hello World" print "Hello World"

View File

@ -47,7 +47,7 @@ class MegaHAL(Module):
"""Sync the megahal brain.""" """Sync the megahal brain."""
mh_python.cleanup() mh_python.cleanup()
def do(self, connection, event, nick, userhost, replypath, what, admin_unlocked): def do(self, connection, event, nick, userhost, what, admin_unlocked):
"""Say something on IRC if the bot is being addressed, or at least learn what was said.""" """Say something on IRC if the bot is being addressed, or at least learn what was said."""
# i think this megahal module is corrupting the object while walking it, # i think this megahal module is corrupting the object while walking it,
@ -66,14 +66,11 @@ class MegaHAL(Module):
reply = mh_python.doreply(line) reply = mh_python.doreply(line)
elif re.search('^!megahal$', line, re.IGNORECASE) is not None: elif re.search('^!megahal$', line, re.IGNORECASE) is not None:
reply = mh_python.doreply('') reply = mh_python.doreply('')
elif replypath is not None:
# only learn if the command is not an internal one
mh_python.learn(line)
if reply is not "": if reply is not "":
if append_nick: if append_nick:
reply = nick + ": " + reply reply = nick + ": " + reply
return self.reply(connection, replypath, reply) return reply
# vi:tabstop=4:expandtab:autoindent # vi:tabstop=4:expandtab:autoindent
# kate: indent-mode python;indent-width 4;replace-tabs on; # kate: indent-mode python;indent-width 4;replace-tabs on;

View File

@ -67,7 +67,7 @@ class Pi(Module):
print("sqlite error: " + str(e)) print("sqlite error: " + str(e))
raise raise
def do(self, connection, event, nick, userhost, replypath, what, admin_unlocked): def do(self, connection, event, nick, userhost, what, admin_unlocked):
match = re.search('^!pi$', what) match = re.search('^!pi$', what)
if match: if match:
db = self.get_db() db = self.get_db()
@ -98,9 +98,9 @@ class Pi(Module):
db.commit() db.commit()
except sqlite3.Error as e: except sqlite3.Error as e:
db.rollback() db.rollback()
return self.reply(connection, replypath, "sqlite error: " + str(e)) return "sqlite error: " + str(e)
return self.reply(connection, replypath, "({0:.10f}, {1:.10f}) is {2}within the circle. pi is {5:.10f}. (i:{3:d} p:{4:d})".format(x, y, "" if inside else "not ", count_inside, count, pi)); return "({0:.10f}, {1:.10f}) is {2}within the circle. pi is {5:.10f}. (i:{3:d} p:{4:d})".format(x, y, "" if inside else "not ", count_inside, count, pi)
# vi:tabstop=4:expandtab:autoindent # vi:tabstop=4:expandtab:autoindent
# kate: indent-mode python;indent-width 4;replace-tabs on; # kate: indent-mode python;indent-width 4;replace-tabs on;

View File

@ -29,7 +29,7 @@ class Seen(Module):
"""Track when people say things in public channels, and report on it.""" """Track when people say things in public channels, and report on it."""
def do(self, connection, event, nick, userhost, replypath, what, admin_unlocked): def do(self, connection, event, nick, userhost, what, admin_unlocked):
# whatever it is, store it # whatever it is, store it
if not self.config.has_section(self.__class__.__name__): if not self.config.has_section(self.__class__.__name__):
self.config.add_section(self.__class__.__name__) self.config.add_section(self.__class__.__name__)
@ -44,7 +44,7 @@ class Seen(Module):
seendata = self.config.get(self.__class__.__name__, query).split('|:|') seendata = self.config.get(self.__class__.__name__, query).split('|:|')
converted = datetime.strptime(seendata[1], "%Y-%m-%dT%H:%M:%S.%f").replace(tzinfo=tzutc()) converted = datetime.strptime(seendata[1], "%Y-%m-%dT%H:%M:%S.%f").replace(tzinfo=tzutc())
replystr = 'last saw ' + query + ' at ' + converted.astimezone(tzlocal()).strftime("%Y/%m/%d %H:%M:%S %Z") + ' saying \'' + seendata[2] + '\'' replystr = 'last saw ' + query + ' at ' + converted.astimezone(tzlocal()).strftime("%Y/%m/%d %H:%M:%S %Z") + ' saying \'' + seendata[2] + '\''
return self.reply(connection, replypath, replystr) return replystr
except NoOptionError: pass except NoOptionError: pass
# vi:tabstop=4:expandtab:autoindent # vi:tabstop=4:expandtab:autoindent

View File

@ -28,7 +28,7 @@ class TextTransform(Module):
Do a number of text transformations, like rot13. Do a number of text transformations, like rot13.
""" """
def do(self, connection, event, nick, userhost, replypath, what, admin_unlocked): def do(self, connection, event, nick, userhost, what, admin_unlocked):
""" """
Pass the real work on to one of our methods and see if any bite. Pass the real work on to one of our methods and see if any bite.
""" """
@ -37,11 +37,11 @@ class TextTransform(Module):
reply = [''] reply = ['']
if self.rot13(what, reply): if self.rot13(what, reply):
return self.reply(connection, replypath, reply[0]) return reply[0]
elif self.base64(what, reply): elif self.base64(what, reply):
return self.reply(connection, replypath, reply[0]) return reply[0]
elif self.upper(what, reply): elif self.upper(what, reply):
return self.reply(connection, replypath, reply[0]) return reply[0]
def rot13(self, what, reply): def rot13(self, what, reply):
""" """

View File

@ -26,7 +26,7 @@ from Module import Module
class Trigger(Module): class Trigger(Module):
"""Return text based on trigger input.""" """Return text based on trigger input."""
def do(self, connection, event, nick, userhost, replypath, what, admin_unlocked): def do(self, connection, event, nick, userhost, what, admin_unlocked):
"""Look up input text in config, and respond with result if found.""" """Look up input text in config, and respond with result if found."""
try: try:
@ -36,7 +36,7 @@ class Trigger(Module):
for trigger in trigger_list: for trigger in trigger_list:
if re.search(trigger, what) is not None: if re.search(trigger, what) is not None:
output = self.config.get(self.__class__.__name__, trigger) output = self.config.get(self.__class__.__name__, trigger)
return self.reply(connection, replypath, output) return output
except NoOptionError: pass except NoOptionError: pass
except NoSectionError: pass except NoSectionError: pass

View File

@ -52,7 +52,7 @@ class Twitter(Module):
self.twit = twitter.Api() self.twit = twitter.Api()
self.authed = False self.authed = False
def do(self, connection, event, nick, userhost, replypath, what, admin_unlocked): def do(self, connection, event, nick, userhost, what, admin_unlocked):
""" """
Attempt to do twitter things. Attempt to do twitter things.
""" """
@ -62,9 +62,9 @@ class Twitter(Module):
status = match.group(1) status = match.group(1)
try: try:
tweet = self.twit.GetStatus(status) tweet = self.twit.GetStatus(status)
return self.reply(connection, replypath, self.tweet_or_retweet_text(tweet=tweet, print_source=True)) return self.tweet_or_retweet_text(tweet=tweet, print_source=True)
except twitter.TwitterError as e: except twitter.TwitterError as e:
return self.reply(connection, replypath, 'Couldn\'t obtain status: ' + str(e)) return 'Couldn\'t obtain status: ' + str(e)
match = re.search('^!twitter\s+getuserstatus\s+(\S+)(\s+.*|$)', what) match = re.search('^!twitter\s+getuserstatus\s+(\S+)(\s+.*|$)', what)
if match: if match:
@ -83,25 +83,25 @@ class Twitter(Module):
tweets = self.twit.GetUserTimeline(screen_name=user, count=count, include_rts=True) tweets = self.twit.GetUserTimeline(screen_name=user, count=count, include_rts=True)
if tweets: if tweets:
tweet = tweets[-1*index] tweet = tweets[-1*index]
return self.reply(connection, replypath, self.tweet_or_retweet_text(tweet=tweet)) return self.tweet_or_retweet_text(tweet=tweet)
except twitter.TwitterError as e: except twitter.TwitterError as e:
return self.reply(connection, replypath, 'Couldn\'t obtain status: ' + str(e)) return 'Couldn\'t obtain status: ' + str(e)
match = re.search('^!twitter\s+tweet\s+(.*)', what) match = re.search('^!twitter\s+tweet\s+(.*)', what)
if match: if match:
tweet = match.group(1) tweet = match.group(1)
if self.authed is False: if self.authed is False:
return self.reply(connection, replypath, 'You must be authenticated to tweet.') return 'You must be authenticated to tweet.'
if admin_unlocked is False: if admin_unlocked is False:
return self.reply(connection, replypath, 'Only admins can tweet.') return 'Only admins can tweet.'
try: try:
if self.twit.PostUpdates(tweet, continuation='\xe2\x80\xa6') is not None: if self.twit.PostUpdates(tweet, continuation='\xe2\x80\xa6') is not None:
return self.reply(connection, replypath, 'Tweet(s) sent.') return 'Tweet(s) sent.'
else: else:
return self.reply(connection, replypath, 'Unknown error sending tweet(s).') return 'Unknown error sending tweet(s).'
except twitter.TwitterError as e: except twitter.TwitterError as e:
return self.reply(connection, replypath, 'Couldn\'t tweet: ' + str(e)) return 'Couldn\'t tweet: ' + str(e)
match = re.search('^!twitter\s+gettoken$', what) match = re.search('^!twitter\s+gettoken$', what)
if match: if match:
@ -113,7 +113,7 @@ class Twitter(Module):
self.request_token = dict(urlparse.parse_qsl(content)) self.request_token = dict(urlparse.parse_qsl(content))
# have the user auth # have the user auth
return self.reply(connection, replypath, 'Go to the following link in your browser: %s?oauth_token=%s and then send me the pin.' % (self.authorize_url, self.request_token['oauth_token'])) return 'Go to the following link in your browser: %s?oauth_token=%s and then send me the pin.' % (self.authorize_url, self.request_token['oauth_token'])
match = re.search('^!twitter\s+auth\s+(\S+)$', what) match = re.search('^!twitter\s+auth\s+(\S+)$', what)
if match: if match:
@ -131,7 +131,7 @@ class Twitter(Module):
# finally, create the twitter API object # finally, create the twitter API object
self.twit = twitter.Api(self.consumer_key, self.consumer_secret, self.access_token['oauth_token'], self.access_token['oauth_token_secret']) self.twit = twitter.Api(self.consumer_key, self.consumer_secret, self.access_token['oauth_token'], self.access_token['oauth_token_secret'])
self.authed = True self.authed = True
return self.reply(connection, replypath, 'The bot is now logged in.') return 'The bot is now logged in.'
def tweet_or_retweet_text(self, tweet, print_source=False): def tweet_or_retweet_text(self, tweet, print_source=False):
""" """

View File

@ -28,7 +28,7 @@ from Module import Module
class Urls(Module): class Urls(Module):
"""Track URLs and allow one to be returned randomly or searched for.""" """Track URLs and allow one to be returned randomly or searched for."""
def do(self, connection, event, nick, userhost, replypath, what, admin_unlocked): def do(self, connection, event, nick, userhost, what, admin_unlocked):
"""Search for a URL from the store, or return a random one, or add one.""" """Search for a URL from the store, or return a random one, or add one."""
whats = what.split(' ') whats = what.split(' ')
@ -45,7 +45,7 @@ class Urls(Module):
urlstr = ' '.join(whats[2:]) + "\n" urlstr = ' '.join(whats[2:]) + "\n"
file.write(urlstr) file.write(urlstr)
return self.reply(connection, replypath, 'added url') return 'added url'
# default: get a random url # default: get a random url
@ -64,7 +64,7 @@ class Urls(Module):
to_print = urls[random.randint(1, len(urls))-1] to_print = urls[random.randint(1, len(urls))-1]
# return text # return text
return self.reply(connection, replypath, to_print.rstrip()) return to_print.rstrip()
else: else:
print('filename in config file for urls is wrong') print('filename in config file for urls is wrong')
except NoOptionError: pass except NoOptionError: pass

View File

@ -30,7 +30,7 @@ from Module import Module
class Weather(Module): class Weather(Module):
"""Provide weather lookup services to the bot.""" """Provide weather lookup services to the bot."""
def do(self, connection, event, nick, userhost, replypath, what, admin_unlocked): def do(self, connection, event, nick, userhost, what, admin_unlocked):
"""Query Google Weather for a location's weather.""" """Query Google Weather for a location's weather."""
match = re.search('^!weather\s+(.*)$', what) match = re.search('^!weather\s+(.*)$', what)
@ -62,11 +62,11 @@ class Weather(Module):
for city in google_weather['forecasts']: for city in google_weather['forecasts']:
weatherstr += " " + city['day_of_week'].encode('utf-8') + ": " + city['condition'].encode('utf-8') + ". High " + city['high'].encode('utf-8') + "°F, Low " + city['low'].encode('utf-8') + "°F." weatherstr += " " + city['day_of_week'].encode('utf-8') + ": " + city['condition'].encode('utf-8') + ". High " + city['high'].encode('utf-8') + "°F, Low " + city['low'].encode('utf-8') + "°F."
return self.reply(connection, replypath, weatherstr) return weatherstr
except URLError as e: except URLError as e:
return self.reply(connection, replypath, "error connecting to google weather:" + str(e)) return "error connecting to google weather:" + str(e)
except IndexError as e: except IndexError as e:
return self.reply(connection, replypath, "error in pywapi: " + str(e)) return "error in pywapi: " + str(e)
# vi:tabstop=4:expandtab:autoindent # vi:tabstop=4:expandtab:autoindent
# kate: indent-mode python;indent-width 4;replace-tabs on; # kate: indent-mode python;indent-width 4;replace-tabs on;