long list of changes to allow modular Module reloads: server as module variable, class appends self to module list, unregister_handlers method which must be overridden, reload method which does the magic to create the a new object of the re-read class. drop use of the main rehash and reload_modules, and don't pass rehash around anymore. load initial objects 'the old way' again. feature modules change for compatability and implementation of all of the above changes

This commit is contained in:
Brian S. Stephan 2010-07-29 22:36:08 -05:00
parent b5062171f9
commit 57090fdda4
8 changed files with 77 additions and 73 deletions

View File

@ -14,7 +14,9 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import inspect
import re
import sys
from irclib import irclib
@ -31,12 +33,14 @@ class Module(object):
# modules to call do and see if anything can handle text they may have seen (such
# as in recursive commands).
def __init__(self, config, server, modlist, rehash):
def __init__(self, config, server, modlist):
self.config = config
self.server = server
self.modlist = modlist
self.register_handlers(server)
# Should do some error handling here.
self.rehash = rehash # Is there another way to call the rehash function in dr.botzo?
# add self to the object list
modlist.append(self)
# print what was loaded, for debugging
print("loaded " + self.__class__.__name__)
@ -53,6 +57,15 @@ class Module(object):
def register_handlers(self, server):
print "looks like someone forgot to implement register_handlers!"
# This is called by reload, to remove the soon-to-be old object from the server
# global handlers (or whatever has been added via register_handlers). Classes
# inheriting from Module should implement this, e.g.:
#
# server.remove_global_handler('privmsg', self.on_privmsg)
def unregister_handlers(self):
print "looks like someone forgot to implement unregister_handlers!"
# Does some variable setup and initial sanity checking before calling Module.do,
# which should be implemented by subclasses and what can be ultimately responsible
# for the work. Of course, you are free to reimplement on_pubmsg on your own too.
@ -82,6 +95,9 @@ class Module(object):
if replypath is not None:
what = self.try_recursion(connection, event, nick, userhost, replypath, what, admin_unlocked)
# try reloading
self.reload(connection, event, nick, userhost, replypath, what, admin_unlocked)
self.do(connection, event, nick, userhost, replypath, what, admin_unlocked)
# Does some variable setup and initial sanity checking before calling Module.do,
@ -106,6 +122,18 @@ class Module(object):
self.do(connection, event, nick, userhost, replypath, what, admin_unlocked)
# If the command given was to reload, reload this module.
def reload(self, connection, event, nick, userhost, replypath, what, admin_unlocked):
whats = what.split(' ')
if whats[0] == 'reload' and admin_unlocked:
reload(sys.modules[self.__module__])
for name, obj in inspect.getmembers(sys.modules[self.__module__]):
if inspect.isclass(obj) and str(obj).find(self.__module__) > 0:
self.modlist.remove(self)
self.unregister_handlers()
obj(self.config, self.server, self.modlist)
# Upon seeing a line intended for this module, see if there are subcommands
# that we should do what is basically a text replacement on. The intent is to
# allow things like the following:

View File

@ -39,45 +39,6 @@ class DrBotIRC(irclib.IRC):
self.connections.append(c)
return c
# This finds all the currently loaded modules that start with "modules" (as all
# the bot modules are currently in a subfolder called modules) and calls
# reload() on them. This will only work if the folder name doesn't change.
def rehash():
myre = re.compile('modules')
for i in sys.modules:
currMod = sys.modules[i]
if currMod is not None and myre.search(i):
reload(currMod)
# Remove the pubmsg and privmsg handlers from the irclib object.
# If we don't do this we will see phantom messages
for obj in modObjs:
server.remove_global_handler('pubmsg', obj.on_pubmsg)
server.remove_global_handler('privmsg', obj.on_privmsg)
reload_modules(moduleList)
# Create the actual module objects, which will readd the handlers we removed
# earlier, and add them to the modObjs list, which we can use during the
# next rehash to remove the handlers.
def reload_modules(moduleList):
for mod in moduleList:
cls = globals()[mod]
# Importing the names imports a module since the file name and class
# name are the same. Look for the class definition in each module
# with the same name and create that object.
if inspect.ismodule(cls):
for name, obj in inspect.getmembers(cls):
if inspect.isclass(obj) and re.search(mod, obj.__name__):
modObjs.append(obj(config, server, modlist, rehash))
break
else:
modObjs.append(cls(config, server, modlist, rehash))
# read config file
config = ConfigParser({'debug': 'false'})
@ -104,14 +65,12 @@ irclib.DEBUG = config.getboolean('IRC', 'debug')
irc = DrBotIRC()
server = irc.server().connect(botserver, botport, botnick, botircname)
reload_modules(moduleList)
#count = Countdown(config, server, modlist)
#dice = Dice(config, server, modlist)
#fact = FactFile(config, server, modlist)
#admin = IrcAdmin(config, server, modlist)
#gt = GoogleTranslate(config, server, modlist)
#seen = Seen(config, server, modlist)
count = Countdown.Countdown(config, server, modlist)
dice = Dice.Dice(config, server, modlist)
fact = FactFile.FactFile(config, server, modlist)
admin = IrcAdmin.IrcAdmin(config, server, modlist)
gt = GoogleTranslate.GoogleTranslate(config, server, modlist)
seen = Seen.Seen(config, server, modlist)
# loop forever
irc.process_forever()

View File

@ -24,14 +24,18 @@ from Module import Module
class Countdown(Module):
def __init__(self, config, server, modlist, rehash):
super(Countdown, self).__init__(config, server, modlist, rehash)
def __init__(self, config, server, modlist):
super(Countdown, self).__init__(config, server, modlist)
modlist.append(self)
def register_handlers(self, server):
server.add_global_handler('pubmsg', self.on_pubmsg)
server.add_global_handler('privmsg', self.on_privmsg)
def unregister_handlers(self):
self.server.remove_global_handler('pubmsg', self.on_pubmsg)
self.server.remove_global_handler('privmsg', self.on_privmsg)
def do(self, connection, event, nick, userhost, replypath, what, admin_unlocked):
whats = what.split(' ')
if whats[0] == 'countdown' and len(whats) >= 2:

View File

@ -25,14 +25,18 @@ from Module import Module
class Dice(Module):
def __init__(self, config, server, modlist, rehash):
super(Dice, self).__init__(config, server, modlist, rehash)
def __init__(self, config, server, modlist):
super(Dice, self).__init__(config, server, modlist)
modlist.append(self)
def register_handlers(self, server):
server.add_global_handler('pubmsg', self.on_pubmsg)
server.add_global_handler('privmsg', self.on_privmsg)
def unregister_handlers(self):
self.server.remove_global_handler('pubmsg', self.on_pubmsg)
self.server.remove_global_handler('privmsg', self.on_privmsg)
def do(self, connection, event, nick, userhost, replypath, what, admin_unlocked):
overallroll = what

View File

@ -26,14 +26,18 @@ from Module import Module
class FactFile(Module):
def __init__(self, config, server, modlist, rehash):
super(FactFile, self).__init__(config, server, modlist, rehash)
def __init__(self, config, server, modlist):
super(FactFile, self).__init__(config, server, modlist)
modlist.append(self)
def register_handlers(self, server):
server.add_global_handler('pubmsg', self.on_pubmsg)
server.add_global_handler('privmsg', self.on_privmsg)
def unregister_handlers(self):
self.server.remove_global_handler('pubmsg', self.on_pubmsg)
self.server.remove_global_handler('privmsg', self.on_privmsg)
def do(self, connection, event, nick, userhost, replypath, what, admin_unlocked):
whats = what.split(' ')
try:

View File

@ -27,14 +27,18 @@ from Module import Module
class GoogleTranslate(Module):
def __init__(self, config, server, modlist, rehash):
super(GoogleTranslate, self).__init__(config, server, modlist, rehash)
def __init__(self, config, server, modlist):
super(GoogleTranslate, self).__init__(config, server, modlist)
modlist.append(self)
def register_handlers(self, server):
server.add_global_handler('pubmsg', self.on_pubmsg)
server.add_global_handler('privmsg', self.on_privmsg)
def unregister_handlers(self):
self.server.remove_global_handler('pubmsg', self.on_pubmsg)
self.server.remove_global_handler('privmsg', self.on_privmsg)
def do(self, connection, event, nick, userhost, replypath, what, admin_unlocked):
whats = what.split(' ')
if whats[0] == 'translate' and len(whats) >= 4:

View File

@ -24,8 +24,8 @@ from Module import Module
class IrcAdmin(Module):
def __init__(self, config, server, modlist, rehash):
super(IrcAdmin, self).__init__(config, server, modlist, rehash)
def __init__(self, config, server, modlist):
super(IrcAdmin, self).__init__(config, server, modlist)
modlist.append(self)
def register_handlers(self, server):
@ -33,6 +33,11 @@ class IrcAdmin(Module):
server.add_global_handler('pubmsg', self.on_pubmsg)
server.add_global_handler('privmsg', self.on_privmsg)
def unregister_handlers(self):
self.server.remove_global_handler('welcome', self.on_connect)
self.server.remove_global_handler('pubmsg', self.on_pubmsg)
self.server.remove_global_handler('privmsg', self.on_privmsg)
def on_connect(self, connection, event):
"""handler for when the bot has connected to IRC
"""
@ -62,17 +67,6 @@ class IrcAdmin(Module):
self.sub_autojoin_manipulate(connection, event, nick, userhost, replypath, what, admin_unlocked)
self.sub_save_config(connection, event, nick, userhost, replypath, what, admin_unlocked)
self.sub_change_nick(connection, event, nick, userhost, replypath, what, admin_unlocked)
self.sub_rehash(connection, event, nick, userhost, replypath, what, admin_unlocked)
def sub_rehash(self, connection, event, nick, userhost, replypath, what, admin_unlocked):
whats = what.split(' ')
if whats[0] == 'rehash' and admin_unlocked:
self.rehash()
replystr = 'rehashed modules'
if replypath is None:
return replystr
else:
connection.privmsg(replypath, replystr)
def sub_join_channel(self, connection, event, nick, userhost, replypath, what, admin_unlocked):
whats = what.split(' ')

View File

@ -28,14 +28,18 @@ from Module import Module
class Seen(Module):
def __init__(self, config, server, modlist, rehash):
super(Seen, self).__init__(config, server, modlist, rehash)
def __init__(self, config, server, modlist):
super(Seen, self).__init__(config, server, modlist)
modlist.append(self)
def register_handlers(self, server):
server.add_global_handler('pubmsg', self.on_pubmsg)
server.add_global_handler('privmsg', self.on_privmsg)
def unregister_handlers(self):
self.server.remove_global_handler('pubmsg', self.on_pubmsg)
self.server.remove_global_handler('privmsg', self.on_privmsg)
# Overriding the default because we need stuff to occur before the addressed
# and so on checks.
@ -70,6 +74,9 @@ class Seen(Module):
if replypath is not None:
what = self.try_recursion(connection, event, nick, userhost, replypath, what, admin_unlocked)
# try reloading
self.reload(connection, event, nick, userhost, replypath, what, admin_unlocked)
self.do(connection, event, nick, userhost, replypath, what, admin_unlocked)
def do(self, connection, event, nick, userhost, replypath, what, admin_unlocked):