move XML-RPC support into DrBotIRC so everything can eventually use it

This commit is contained in:
Brian S. Stephan 2012-03-30 09:43:30 -05:00
parent 91faebf33a
commit 05a3bd0af7
2 changed files with 81 additions and 112 deletions

View File

@ -21,11 +21,62 @@ import copy
from ConfigParser import NoOptionError, NoSectionError from ConfigParser import NoOptionError, NoSectionError
import re import re
import signal import signal
from SimpleXMLRPCServer import SimpleXMLRPCServer
import socket import socket
import sys import sys
import thread
from extlib import irclib from extlib import irclib
class DrBotzoMethods:
"""Methods to expose to the XML-RPC server."""
def __init__(self, irc):
"""Store the same stuff the core module would, since we'll probably need it."""
self.irc = irc
def echo(self, message):
"""
Just reply to the client, for testing purposes.
Arguments: message - the message to echo
"""
return message
def say(self, target, message):
"""
Say a message in a channel/to a nick.
Arguments: target - the nick/channel to privmsg
message - the message to send
"""
self.irc.server.privmsg(target, message)
return "OK"
def execute_module_method(self, modname, method, args):
"""
Execute the method (with arguments) of the specified module.
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:
if modname == module.__class__.__name__:
try:
func = getattr(module, method)
except AttributeError:
return "couldn't find " + method + " in found module " + modname
if hasattr(func, '__call__'):
return func(*args)
else:
return method + " in found module " + modname + " is not callable"
return "couldn't find " + modname
class DrBotServerConnection(irclib.ServerConnection): class DrBotServerConnection(irclib.ServerConnection):
"""Subclass irclib's ServerConnection, in order to expand privmsg.""" """Subclass irclib's ServerConnection, in order to expand privmsg."""
@ -90,10 +141,26 @@ class DrBotIRC(irclib.IRC):
irclib.IRC.__init__(self) irclib.IRC.__init__(self)
self.config = config self.config = config
self.xmlrpc = None
# handle SIGINT # handle SIGINT
signal.signal(signal.SIGINT, self.sigint_handler) signal.signal(signal.SIGINT, self.sigint_handler)
# load XML-RPC server
try:
if self.config.has_section('XMLRPC'):
host = self.config.get('XMLRPC', 'host')
port = self.config.getint('XMLRPC', 'port')
if host and port:
self.funcs = DrBotzoMethods(self)
self.xmlrpc = SimpleXMLRPCServer((host, port))
self.xmlrpc.register_introspection_functions()
self.xmlrpc.register_instance(self.funcs)
thread.start_new_thread(self._xmlrpc_listen, ())
except NoOptionError: pass
def server(self): def server(self):
"""Create a DrBotServerConnection.""" """Create a DrBotServerConnection."""
self.server = DrBotServerConnection(self) self.server = DrBotServerConnection(self)
@ -129,6 +196,11 @@ class DrBotIRC(irclib.IRC):
except Exception as e: except Exception as e:
print("exception floated up to DrBotIrc: " + str(e)) print("exception floated up to DrBotIrc: " + str(e))
def _xmlrpc_listen(self):
"""Begin listening. Hopefully this was called in a new thread."""
self.xmlrpc.serve_forever()
def try_to_replace_event_text_with_module_text(self, connection, event): def try_to_replace_event_text_with_module_text(self, connection, event):
"""Do something very similar to _handle_event, but for recursion. """Do something very similar to _handle_event, but for recursion.
@ -296,12 +368,20 @@ class DrBotIRC(irclib.IRC):
connection.quit(msg) connection.quit(msg)
print(self.save_config()) print(self.save_config())
self._xmlrpc_shutdown()
sys.exit() sys.exit()
def save_modules(self): def save_modules(self):
for module in self.modlist: for module in self.modlist:
module.save() module.save()
def _xmlrpc_shutdown(self):
"""Shut down the XML-RPC server."""
if self.xmlrpc is not None:
self.xmlrpc.shutdown()
self.xmlrpc.server_close()
def save_config(self): def save_config(self):
with open('dr.botzo.cfg', 'w') as cfg: with open('dr.botzo.cfg', 'w') as cfg:
self.config.write(cfg) self.config.write(cfg)
@ -379,6 +459,7 @@ class DrBotIRC(irclib.IRC):
module.shutdown() module.shutdown()
print(self.save_config()) print(self.save_config())
self._xmlrpc_shutdown()
sys.exit() sys.exit()
# vi:tabstop=4:expandtab:autoindent # vi:tabstop=4:expandtab:autoindent

View File

@ -1,112 +0,0 @@
"""
XmlRpcServer - access dr.botzo functionality via XML-RPC
Copyright (C) 2012 Brian S. Stephan
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
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 thread
from SimpleXMLRPCServer import SimpleXMLRPCServer
from extlib import irclib
from Module import Module
class DrBotzoMethods:
"""Methods to expose to the XML-RPC server."""
def __init__(self, irc, config, server):
"""Store the same stuff the core module would, since we'll probably need it."""
self.irc = irc
self.config = config
self.server = server
def echo(self, message):
"""
Just reply to the client, for testing purposes.
Arguments: message - the message to echo
"""
return message
def say(self, target, message):
"""
Say a message in a channel/to a nick.
Arguments: target - the nick/channel to privmsg
message - the message to send
"""
self.irc.server.privmsg(target, message)
return "OK"
def execute_module_method(self, modname, method, args):
"""
Execute the method (with arguments) of the specified module.
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:
if modname == module.__class__.__name__:
try:
func = getattr(module, method)
except AttributeError:
return "couldn't find " + method + " in found module " + modname
if hasattr(func, '__call__'):
return func(*args)
else:
return method + " in found module " + modname + " is not callable"
return "couldn't find " + modname
class XmlRpcServer(Module):
"""A module to expose an XML-RPC service, to achieve various things."""
def __init__(self, irc, config, server):
"""Create the XML-RPC server."""
Module.__init__(self, irc, config, server)
self.xmlrpc = None
self.funcs = DrBotzoMethods(irc, config, server)
self.xmlrpc = SimpleXMLRPCServer(("localhost", 8180))
self.xmlrpc.register_introspection_functions()
self.xmlrpc.register_instance(self.funcs)
thread.start_new_thread(self._listen, ())
def _listen(self):
"""Begin listening. Hopefully this was called in a new thread."""
self.xmlrpc.serve_forever()
def do(self, connection, event, nick, userhost, what, admin_unlocked):
"""Do nothing."""
return
def shutdown(self):
"""Shut down the XML-RPC server."""
if self.xmlrpc is not None:
self.xmlrpc.shutdown()
self.xmlrpc.server_close()
# vi:tabstop=4:expandtab:autoindent