dr.botzo/dr.botzo.py

128 lines
4.3 KiB
Python

# dr.botzo - a pluggable IRC bot written in Python
# Copyright (C) 2010 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/>.
from ConfigParser import ConfigParser, NoSectionError, NoOptionError
from datetime import datetime
import os
import random
import re
import sys
import inspect
from urllib2 import urlopen
from urllib import urlencode
from dateutil.parser import *
from dateutil.relativedelta import *
from dateutil.tz import *
from irclib import irclib
from modules import *
modlist = []
moduleList = [ "Countdown", "Dice", "IrcAdmin", "GoogleTranslate", "Seen", "FactFile" ]
modObjs = []
class DrBotServerConnection(irclib.ServerConnection):
def privmsg(self, target, text):
# Send a PRIVMSG command.
# TODO: length limiting or splitting
self.send_raw("PRIVMSG %s :%s" % (target, text))
class DrBotIRC(irclib.IRC):
def server(self):
c = DrBotServerConnection(self)
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'})
config.read([os.path.expanduser('~/.dr.botzo.cfg'), 'dr.botzo.cfg'])
# load necessary options
try:
# load connection info
botserver = config.get('IRC', 'server')
botport = config.getint('IRC', 'port')
botnick = config.get('IRC', 'nick')
botircname = config.get('IRC', 'name')
except NoSectionError as e:
sys.exit("Aborted due to error with necessary configuration: " + str(e))
except NoOptionError as e:
sys.exit("Aborted due to error with necessary configuration: " + str(e))
# load additional options
irclib.DEBUG = config.getboolean('IRC', 'debug')
# start up the IRC bot
# create IRC and server objects and connect
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)
# loop forever
irc.process_forever()
# vi:tabstop=4:expandtab:autoindent
# kate: indent-mode python;indent-width 4;replace-tabs on;