"""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()