DrBotIRC: docstring/comment cleanups

this is some of the oldest code in the bot, there's probably a lot more
that could be cleaned up (and, indeed, some upcoming commits do some of
that)
This commit is contained in:
Brian S. Stephan 2012-12-18 22:15:52 -06:00
parent 8a5e6b9130
commit da430981be
1 changed files with 174 additions and 29 deletions

View File

@ -14,6 +14,7 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
""" """
import bisect import bisect
@ -35,41 +36,56 @@ class DrBotzoMethods:
"""Methods to expose to the XML-RPC server.""" """Methods to expose to the XML-RPC server."""
def __init__(self, irc): def __init__(self, irc):
"""Store the same stuff the core module would, since we'll probably need it.""" """Store the same stuff the core module would, since we'll probably
need it.
Args:
irc the irc instance to save a reference to
"""
self.irc = irc self.irc = irc
self.log = logging.getLogger('drbotzo') self.log = logging.getLogger('drbotzo')
def echo(self, message): def echo(self, message):
""" """Just reply to the client, for testing purposes.
Just reply to the client, for testing purposes.
Args:
message the message to echo
Returns:
message, unmodified.
Keyword arguments:
message - the message to echo
""" """
return message return message
def say(self, target, message): def say(self, target, message):
""" """Say a message in a channel/to a nick.
Say a message in a channel/to a nick.
Args:
target the nick/channel to privmsg
message the message to send
Returns:
"OK", since there's no other feedback to give.
Keyword arguments:
target - the nick/channel to privmsg
message - the message to send
""" """
self.irc.server.privmsg(target, message) self.irc.server.privmsg(target, message)
return "OK" return "OK"
def execute_module_method(self, modname, method, args): def execute_module_method(self, modname, method, args):
""" """Execute the method (with arguments) of the specified module.
Execute the method (with arguments) of the specified module.
Args:
modname the loaded module to retrieve
method the method to call from that module
args the arguments to provide to the method as a tuple
Returns:
An error string, or the outcome of the method call.
Keyword arguments:
modname - the loaded module to retrieve
method - the method to call from that module
args - the arguments to provide to the method as a pythonic tuple
""" """
for module in self.irc.modlist: for module in self.irc.modlist:
@ -93,6 +109,16 @@ class DrBotServerConnection(irclib.ServerConnection):
nickmask = None nickmask = None
def __init__(self, irclibobj): def __init__(self, irclibobj):
"""Instantiate the server connection.
Also start guessing at the nickmask and get ready to do on_welcome
stuff.
Args:
irclibobj the irclib instance to connect with
"""
irclib.ServerConnection.__init__(self, irclibobj) irclib.ServerConnection.__init__(self, irclibobj)
# temporary. hopefully on_welcome() will set this # temporary. hopefully on_welcome() will set this
@ -102,7 +128,14 @@ class DrBotServerConnection(irclib.ServerConnection):
self.add_global_handler('welcome', self.on_welcome, 1) self.add_global_handler('welcome', self.on_welcome, 1)
def on_welcome(self, connection, event): def on_welcome(self, connection, event):
"""Set the nickmask that the ircd tells us is us.""" """Set the nickmask that the ircd tells us is us.
Args:
connection source connection
event incoming event
"""
what = event.arguments()[0] what = event.arguments()[0]
match = re.search('(\S+!\S+@\S+)', what) match = re.search('(\S+!\S+@\S+)', what)
@ -110,7 +143,13 @@ class DrBotServerConnection(irclib.ServerConnection):
self.nickmask = match.group(1) self.nickmask = match.group(1)
def privmsg(self, target, text): def privmsg(self, target, text):
"""Send a PRIVMSG command.""" """Send a PRIVMSG command.
Args:
target the destination nick/channel
text the message to send
"""
splitter = "..." splitter = "..."
@ -132,6 +171,7 @@ class DrBotServerConnection(irclib.ServerConnection):
times = times + 1 times = times + 1
if times >= 4: if times >= 4:
# this is stupidly long, abort
return return
# done splitting # done splitting
@ -148,6 +188,12 @@ class DrBotIRC(irclib.IRC):
server = None server = None
def __init__(self, config): def __init__(self, config):
"""Initialize XML-RPC interface and save references.
Args:
config the config structure to load stuff from
"""
irclib.IRC.__init__(self) irclib.IRC.__init__(self)
self.config = config self.config = config
@ -173,14 +219,26 @@ class DrBotIRC(irclib.IRC):
except NoOptionError: pass except NoOptionError: pass
def server(self): def server(self):
"""Create a DrBotServerConnection.""" """Create a DrBotServerConnection.
Returns:
The newly created DrBotServerConnection.
"""
self.server = DrBotServerConnection(self) self.server = DrBotServerConnection(self)
self.connections.append(self.server) self.connections.append(self.server)
return self.server return self.server
def _handle_event(self, connection, event): def _handle_event(self, connection, event):
"""Override event handler to do recursion.""" """Override event handler to do recursion.
Args:
connection source connection
event incoming event
"""
try: try:
nick = irclib.nm_to_n(event.source()) nick = irclib.nm_to_n(event.source())
@ -209,14 +267,24 @@ class DrBotIRC(irclib.IRC):
self.log.exception(e) self.log.exception(e)
def xmlrpc_register_function(self, func, name): def xmlrpc_register_function(self, func, name):
"""Add a method to the XML-RPC interface.""" """Add a method to the XML-RPC interface.
Args:
func the method to register
name the name to expose the method as
"""
if func and self.xmlrpc: if func and self.xmlrpc:
if hasattr(func, '__call__'): if hasattr(func, '__call__'):
self.xmlrpc.register_function(func, name) self.xmlrpc.register_function(func, name)
def _xmlrpc_listen(self): def _xmlrpc_listen(self):
"""Begin listening. Hopefully this was called in a new thread.""" """Begin listening.
Hopefully this was called in a new thread.
"""
self.xmlrpc.serve_forever() self.xmlrpc.serve_forever()
@ -225,6 +293,11 @@ class DrBotIRC(irclib.IRC):
The intent here is that we replace [text] with whatever a module The intent here is that we replace [text] with whatever a module
provides to us. provides to us.
Args:
connection source connection
event incoming event
""" """
h = self.handlers h = self.handlers
@ -240,6 +313,14 @@ class DrBotIRC(irclib.IRC):
def try_alias_cmds(self, connection, event): def try_alias_cmds(self, connection, event):
"""See if there is an alias ("!command") in the text, and if so """See if there is an alias ("!command") in the text, and if so
do alias manipulation before any other recursion or aliasing. do alias manipulation before any other recursion or aliasing.
Args:
connection source connection
event incoming event
Returns:
The outcome of the alias command, if the text had one.
""" """
try: try:
@ -303,7 +384,17 @@ class DrBotIRC(irclib.IRC):
except NoSectionError: pass except NoSectionError: pass
def try_alias(self, connection, event): def try_alias(self, connection, event):
# try doing alias work """Try turning aliases into commands.
Args:
connection source connection
event incoming event
Returns:
The de-aliased event object.
"""
try: try:
what = event.arguments()[0] what = event.arguments()[0]
alias_list = self.config.options('Alias') alias_list = self.config.options('Alias')
@ -337,6 +428,11 @@ class DrBotIRC(irclib.IRC):
command arg1 [anothercommand arg1 arg2] command arg1 [anothercommand arg1 arg2]
where the output of anothercommand is command's arg2..n. where the output of anothercommand is command's arg2..n.
Args:
connection source connection
event incoming event
""" """
try: try:
@ -381,6 +477,13 @@ class DrBotIRC(irclib.IRC):
except IndexError: pass except IndexError: pass
def quit_irc(self, connection, msg): def quit_irc(self, connection, msg):
"""Quit IRC, disconnect, shut everything down.
Args:
connection the connection to quit
msg the message to send while quitting
"""
for module in self.modlist: for module in self.modlist:
module.save() module.save()
module.shutdown() module.shutdown()
@ -391,8 +494,20 @@ class DrBotIRC(irclib.IRC):
self.log.info("Bot shutting down.") self.log.info("Bot shutting down.")
sys.exit() sys.exit()
def reply(self, connection, event, replystr, stop_responding=False): def reply(self, connection, event, replystr, stop=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.
Args:
connection source connection
event incoming event
replystr the message to reply with
stop whether or not to let other handlers see this
Returns:
The replystr if the event is inside recursion, or, potentially,
"NO MORE" to stop other event handlers from acting.
"""
replypath = event.target() replypath = event.target()
@ -407,10 +522,12 @@ class DrBotIRC(irclib.IRC):
replies = replystr.split('\n') replies = replystr.split('\n')
for reply in replies: for reply in replies:
connection.privmsg(replypath, reply) connection.privmsg(replypath, reply)
if stop_responding: if stop:
return "NO MORE" return "NO MORE"
def save_modules(self): def save_modules(self):
"""Call each module's save(), in case they have something to do."""
for module in self.modlist: for module in self.modlist:
module.save() module.save()
@ -422,6 +539,13 @@ class DrBotIRC(irclib.IRC):
self.xmlrpc.server_close() self.xmlrpc.server_close()
def save_config(self): def save_config(self):
"""Write the config file to disk.
Returns:
Short string indicating success.
"""
with open('dr.botzo.cfg', 'w') as cfg: with open('dr.botzo.cfg', 'w') as cfg:
self.config.write(cfg) self.config.write(cfg)
@ -430,6 +554,13 @@ class DrBotIRC(irclib.IRC):
def load_module(self, modname): def load_module(self, modname):
"""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.
Args:
modname the module to attempt to load
Returns:
String describing the outcome of the load attempt.
""" """
for module in self.modlist: for module in self.modlist:
@ -457,7 +588,15 @@ class DrBotIRC(irclib.IRC):
return "Module '" + modname + "' could not be loaded." return "Module '" + modname + "' could not be loaded."
def unload_module(self, modname): def unload_module(self, modname):
"""Attempt to unload and del a module if it's loaded.""" """Attempt to unload and del a module if it's loaded.
Args:
modname the module to attempt to unload
Returns:
String describing the outcome of the unload attempt.
"""
modstr = 'modules.'+modname modstr = 'modules.'+modname
for module in self.modlist: for module in self.modlist:
@ -485,7 +624,12 @@ class DrBotIRC(irclib.IRC):
return 'Module ' + modname + ' is not loaded.' return 'Module ' + modname + ' is not loaded.'
def list_modules(self): def list_modules(self):
"""List loaded modules.""" """List loaded modules.
Returns:
A list of the loaded modules' names.
"""
modnames = [] modnames = []
for module in self.modlist: for module in self.modlist:
@ -493,8 +637,9 @@ class DrBotIRC(irclib.IRC):
return modnames return modnames
# SIGINT signal handler
def sigint_handler(self, signal, frame): def sigint_handler(self, signal, frame):
"""Cleanly shutdown on SIGINT."""
for module in self.modlist: for module in self.modlist:
module.save() module.save()
module.shutdown() module.shutdown()