diff --git a/plugins/FunDB.py b/plugins/FunDB.py index c0ba92d00..1b8869b4a 100755 --- a/plugins/FunDB.py +++ b/plugins/FunDB.py @@ -87,10 +87,6 @@ tableCreateStatements = { word TEXT UNIQUE ON CONFLICT IGNORE )""", """CREATE INDEX sorted_words_word ON sorted_words (word)"""), - 'uptime': ("""CREATE TABLE uptime ( - started INTEGER UNIQUE ON CONFLICT IGNORE, - ended INTEGER - )""",) } def makeDb(dbfilename, replace=False): @@ -108,15 +104,6 @@ def makeDb(dbfilename, replace=False): db.commit() return db -def uptimeEnder(started): - def endUptime(): - db = makeDb(dbFilename) - cursor = db.cursor() - cursor.execute("""UPDATE uptime SET ended=%s WHERE started=%s""", - int(time.time()), started) - db.commit() - return endUptime - def addWord(db, word, commit=False): word = word.strip().lower() L = list(word) @@ -142,42 +129,12 @@ class FunDB(callbacks.Privmsg): callbacks.Privmsg.__init__(self) self.db = makeDb(dbFilename) cursor = self.db.cursor() - started = int(world.startedAt) - cursor.execute("""INSERT INTO uptime VALUES (%s, NULL)""", started) - self.db.commit() - world.flushers.append(uptimeEnder(started)) def die(self): self.db.commit() self.db.close() del self.db - def bestuptime(self, irc, msg, args): - """takes no arguments. - - Returns the highest uptimes attained by the bot. - """ - cursor = self.db.cursor() - cursor.execute("""SELECT started, ended FROM uptime - WHERE started <> 0 AND ended NOTNULL - ORDER BY ended-started DESC""") - L = [] - lenSoFar = 0 - counter = cursor.rowcount - if cursor.rowcount == 0: - irc.reply(msg, 'I don\'t have enough data to answer that.') - return - while counter and lenSoFar < 400: - (started, ended) = map(int, cursor.fetchone()) - s = '%s; up for %s' % \ - (time.strftime(conf.humanTimestampFormat, - time.localtime(ended)), - utils.timeElapsed(ended-started)) - lenSoFar += len(s) - counter -= 1 - L.append(s) - irc.reply(msg, '; '.join(L)) - def insult(self, irc, msg, args): """ diff --git a/plugins/Status.py b/plugins/Status.py index a5dd4bf83..2e0b424e0 100644 --- a/plugins/Status.py +++ b/plugins/Status.py @@ -36,10 +36,13 @@ current status and statistics. import plugins import os +import sys import sets import time import threading +from itertools import islice, ifilter +import conf import utils import world import privmsgs @@ -58,6 +61,49 @@ example = utils.wrapLines(""" Add an example IRC session using this module here. """) +class UptimeDB(object): + def __init__(self, filename='uptimes'): + self.filename = os.path.join(conf.dataDir, filename) + if os.path.exists(self.filename): + fd = file(self.filename) + s = fd.read() + fd.close() + s = s.replace('\n', ' ') + self.uptimes = eval(s) + else: + self.uptimes = [] + + def die(self): + fd = file(self.filename, 'w') + fd.write(repr(self.uptimes)) + fd.write('\n') + fd.close() + + def add(self): + if not any(lambda t: t[0] == world.startedAt, self.uptimes): + self.uptimes.append((world.startedAt, None)) + + def top(self, n=3): + def decorator(t): + if t[1] is None: + return 0.0 + else: + t[1] - t[0] + def invertCmp(cmp): + def f(x, y): + return -cmp(x, y) + return f + def notNone(t): + return t[1] is not None + utils.sortBy(decorator, self.uptimes, cmp=invertCmp(cmp)) + return list(islice(ifilter(notNone, self.uptimes), 3)) + + def update(self): + for (i, t) in enumerate(self.uptimes): + if t[0] == world.startedAt: + self.uptimes[i] = (t[0], time.time()) + + class Status(callbacks.Privmsg): def __init__(self): callbacks.Privmsg.__init__(self) @@ -65,6 +111,8 @@ class Status(callbacks.Privmsg): self.recvdMsgs = 0 self.sentBytes = 0 self.recvdBytes = 0 + self.uptimes = UptimeDB() + self.uptimes.add() def inFilter(self, irc, msg): self.recvdMsgs += 1 @@ -76,6 +124,29 @@ class Status(callbacks.Privmsg): self.sentBytes += len(str(msg)) return msg + def die(self): + self.uptimes.update() + self.uptimes.die() + + def bestuptime(self, irc, msg, args): + """takes no arguments + + Returns the highest uptimes attained by the bot. + """ + L = self.uptimes.top() + if not L: + irc.error(msg, 'I don\'t have enough data to answer that.') + return + def format((started, ended)): + return '%s until %s; up for %s' % \ + (time.strftime(conf.humanTimestampFormat, + time.localtime(started)), + time.strftime(conf.humanTimestampFormat, + time.localtime(ended)), + utils.timeElapsed(ended-started)) + L = map(format, L) + irc.reply(msg, utils.commaAndify(L)) + def netstats(self, irc, msg, args): """takes no arguments diff --git a/test/test_Status.py b/test/test_Status.py index 0fd35a536..16ba4acc2 100644 --- a/test/test_Status.py +++ b/test/test_Status.py @@ -32,7 +32,13 @@ from test import * class StatusTestCase(PluginTestCase, PluginDocumentation): - plugins = ('Status',) + plugins = ('Status', 'OwnerCommands') + def testBestuptime(self): + self.assertError('bestuptime') + self.assertNotError('unload Status') + self.assertNotError('load Status') + self.assertNotError('bestuptime') + def testNetstats(self): self.assertNotError('netstats')