"""cupybot, a CherryPy front-end to supybot and irclog2html. You'll have to obtain irclog2html yourself, from http://mg.pov.lt/irclog2html/ Then, either stick this file in that folder, or put irclog2html in your Python path (and any .css files, etc in this folder). """ import os CUPYBOT_DIR = '/var/www/flexo.structuredabstraction.com/supybot/cupybot' logcss = os.path.join(CUPYBOT_DIR, 'irclog.css') import shutil import sys sys.path.insert(0, CUPYBOT_DIR) try: import cStringIO as StringIO except ImportError: import StringIO import threading import time import textwrap started = time.time() import supybot import supybot.utils as utils import supybot.registry as registry import supybot.questions as questions import irclog2html import cherrypy class Root: style = irclog2html.XHTMLStyle irclog_css = cherrypy.tools.staticfile.handler(filename=logcss) def default(self, server, channel, page=None, q=None): outfile = StringIO.StringIO() logdir = conf.supybot.directories.log.dirize('ChannelLogger') chandir = os.path.join(logdir, server, '#' + channel) cherrypy.log(chandir) try: fnames = [fname.rsplit(".", 1)[0] for fname in os.listdir(chandir) if fname.endswith(".log")] fnames.sort() except: raise cherrypy.NotFound() if page is None: # Grab the last page; assume they're in order pos = len(fnames) - 1 elif page in fnames: pos = fnames.index(page) else: # Grab the nearest previous page. fnames.append(page) fnames.sort() pos = fnames.index(page) - 1 fnames.remove(page) if pos < 0: pos = 0 elif pos > len(fnames) - 1: pos = len(fnames) - 1 page = fnames[pos] if pos > 0: # Must use relative URL's since irclog2html urllib.quote's it prev = cherrypy.url('/%s/%s/%s' % (server, channel, fnames[pos - 1]), relative=True) else: prev = '' if pos < len(fnames) - 1: # Must use relative URL's since irclog2html urllib.quote's it next = cherrypy.url('/%s/%s/%s' % (server, channel, fnames[pos + 1]), relative=True) else: next = '' chanfile = os.path.join(chandir, "%s.log" % page) # Prevent uplevel attacks if not os.path.normpath(chanfile).startswith(chandir): raise cherrypy.NotFound() try: infile = open(chanfile, 'rb') except IOError: raise cherrypy.NotFound() parser = irclog2html.LogParser(infile) formatter = self.style(outfile) irclog2html.convert_irc_log( parser, formatter, "IRC Log for #%s %s" % (channel, page), ('Previous', prev), ('', ''), ('Next', next), searchbox=False) outfile.seek(0) data = outfile.read() # Due to our use of directories, we need absolute links to irclog.css if """""" in data: data = data.replace( """""", """""" ) return data default.exposed = True def main(): import supybot.conf as conf import supybot.world as world import supybot.drivers as drivers import supybot.schedule as schedule # We schedule this event rather than have it actually run because if there # is a failure between now and the time it takes the Owner plugin to load # all the various plugins, our registry file might be wiped. That's bad. interrupted = False when = conf.supybot.upkeepInterval() schedule.addPeriodicEvent(world.upkeep, when, name='upkeep', now=False) world.startedAt = started while world.ircs: try: drivers.run() except KeyboardInterrupt: if interrupted: # Interrupted while waiting for queues to clear. Let's clear # them ourselves. for irc in world.ircs: irc._reallyDie() continue else: interrupted = True log.info('Exiting due to Ctrl-C. ' 'If the bot doesn\'t exit within a few seconds, ' 'feel free to press Ctrl-C again to make it exit ' 'without flushing its message queues.') world.upkeep() for irc in world.ircs: quitmsg = conf.supybot.plugins.Owner.quitMsg() or \ 'Ctrl-C at console.' irc.queueMsg(ircmsgs.quit(quitmsg)) irc.die() except SystemExit, e: s = str(e) if s: log.info('Exiting due to %s', s) break except: try: # Ok, now we're *REALLY* paranoid! log.exception('Exception raised out of drivers.run:') except Exception, e: print 'Exception raised in log.exception. This is *really*' print 'bad. Hopefully it won\'t happen again, but tell us' print 'about it anyway, this is a significant problem.' print 'Anyway, here\'s the exception: %s' % \ utils.gen.exnToString(e) except: print 'Man, this really sucks. Not only did log.exception' print 'raise an exception, but freaking-a, it was a string' print 'exception. People who raise string exceptions should' print 'die a slow, painful death.' now = time.time() seconds = now - world.startedAt log.info('Total uptime: %s.', utils.gen.timeElapsed(seconds)) (user, system, _, _, _) = os.times() log.info('Total CPU time taken: %s seconds.', user+system) log.info('No more Irc objects, exiting.') CUPYBOT_CONF = os.path.join(CUPYBOT_DIR, 'structuredabstraction.com.conf') cherrypy.config.update(CUPYBOT_CONF) cherrypy.tree.mount(Root(), '/', CUPYBOT_CONF) registryFilename = cherrypy.config.get('registryFilename') try: # The registry *MUST* be opened before importing log or conf. cherrypy.engine.log("Opening registry file %r" % registryFilename) registry.open(registryFilename) cherrypy.engine.log("Backing up registry file %r" % registryFilename) shutil.copy(registryFilename, registryFilename + '.bak') except registry.InvalidRegistryFile, e: s = '%s in %s. Please fix this error and start supybot again.' % \ (e, registryFilename) s = textwrap.fill(s) cherrypy.log(s) raise except EnvironmentError, e: cherrypy.log(str(e)) sys.exit(-1) cherrypy.engine.log("Importing supybot.log") try: import supybot.log as log except supybot.registry.InvalidRegistryValue, e: # This is raised here because supybot.log imports supybot.conf. name = e.value._name errmsg = textwrap.fill('%s: %s' % (name, e), width=78, subsequent_indent=' '*len(name)) cherrypy.log(errmsg) sys.exit(-1) import supybot.conf as conf import supybot.world as world world.starting = True def closeRegistry(): # We only print if world.dying so we don't see these messages during # upkeep. logger = log.debug if world.dying: logger = log.info logger('Writing registry file to %s', registryFilename) registry.close(conf.supybot, registryFilename) logger('Finished writing registry file.') world.flushers.append(closeRegistry) world.registryFilename = registryFilename networks = conf.supybot.networks() if not networks: cherrypy.log("No networks defined. Perhaps you should re-run the wizard?") sys.exit(-1) if not os.path.exists(conf.supybot.directories.log()): os.mkdir(conf.supybot.directories.log()) if not os.path.exists(conf.supybot.directories.conf()): os.mkdir(conf.supybot.directories.conf()) if not os.path.exists(conf.supybot.directories.data()): os.mkdir(conf.supybot.directories.data()) if not os.path.exists(conf.supybot.directories.data.tmp()): os.mkdir(conf.supybot.directories.tmp()) userdataFilename = os.path.join(conf.supybot.directories.conf(), 'userdata.conf') # Let's open this now since we've got our directories setup. if not os.path.exists(userdataFilename): fd = file(userdataFilename, 'w') fd.write('\n') fd.close() cherrypy.engine.log("Opening userdata file %r" % userdataFilename) registry.open(userdataFilename) import supybot.irclib as irclib import supybot.ircmsgs as ircmsgs import supybot.drivers as drivers import supybot.callbacks as callbacks import supybot.plugins.Owner as Owner owner = Owner.Class() if __name__ == '__main__': cherrypy.engine.start() try: main() finally: cherrypy.engine.exit() else: # modpython import threading threading.Thread(target=main).start()