Scrap the Old 'n' Busted. Bring in the New Hotness (aka, freshly abstracted).

This commit is contained in:
James Vega 2004-09-10 19:37:49 +00:00
parent 82167728e4
commit 9c8c505de5
2 changed files with 170 additions and 127 deletions

View File

@ -41,28 +41,66 @@ import supybot.plugins as plugins
import os import os
import time import time
import supybot.dbi as dbi
import supybot.conf as conf import supybot.conf as conf
import supybot.ircdb as ircdb import supybot.ircdb as ircdb
import supybot.utils as utils import supybot.utils as utils
import supybot.ircutils as ircutils
import supybot.privmsgs as privmsgs import supybot.privmsgs as privmsgs
import supybot.callbacks as callbacks import supybot.callbacks as callbacks
try:
import sqlite
except ImportError:
raise callbacks.Error, 'You need to have PySQLite installed to use this ' \
'plugin. Download it at <http://pysqlite.sf.net/>'
class News(plugins.ChannelDBHandler, callbacks.Privmsg): class NewsRecord(object):
__metaclass__ = dbi.Record
__fields__ = [
'subject',
'text',
'at',
'expires',
'by'
]
def __str__(self):
format = conf.supybot.humanTimestampFormat()
try:
user = ircdb.users.getUser(int(self.by)).name
except ValueError:
user = self.by
except KeyError:
user = 'a user that is no longer registered'
if int(self.expires) == 0:
s = '%s (Subject: "%s", added by %s on %s)' % \
(self.text, self.subject, self.by,
time.strftime(format, time.localtime(int(self.at))))
else:
s = '%s (Subject: "%s", added by %s on %s, expires at %s)' % \
(self.text, self.subject, self.by,
time.strftime(format, time.localtime(int(self.at))),
time.strftime(format, time.localtime(int(self.expires))))
return s
class SqliteNewsDB(object):
def __init__(self): def __init__(self):
plugins.ChannelDBHandler.__init__(self) self.dbs = ircutils.IrcDict()
callbacks.Privmsg.__init__(self)
self.removeOld = False
def makeDb(self, filename): def close(self):
for db in self.dbs.itervalues():
db.close()
def _getDb(self, channel):
try:
import sqlite
except ImportError:
raise callbacks.Error, 'You need to have PySQLite installed to ' \
'use this plugin. Download it at ' \
'<http://pysqlite.sf.net/>'
filename = plugins.makeChannelFilename(channel, 'News.db')
if filename in self.dbs:
return self.dbs[filename]
if os.path.exists(filename): if os.path.exists(filename):
return sqlite.connect(filename) self.dbs[filename] = sqlite.connect(filename)
return self.dbs[filename]
db = sqlite.connect(filename) db = sqlite.connect(filename)
self.dbs[filename] = db
cursor = db.cursor() cursor = db.cursor()
cursor.execute("""CREATE TABLE news ( cursor.execute("""CREATE TABLE news (
id INTEGER PRIMARY KEY, id INTEGER PRIMARY KEY,
@ -75,6 +113,76 @@ class News(plugins.ChannelDBHandler, callbacks.Privmsg):
db.commit() db.commit()
return db return db
def add(self, channel, subject, text, added_at, expires, by):
db = self._getDb(channel)
cursor = db.cursor()
cursor.execute("INSERT INTO news VALUES (NULL, %s, %s, %s, %s, %s)",
subject, text, added_at, expires, by)
db.commit()
def get(self, channel, id=None, old=False):
db = self._getDb(channel)
cursor = db.cursor()
if id:
cursor.execute("""SELECT item, subject, added_at,
expires_at, added_by
FROM news
WHERE id=%s""", id)
if cursor.rowcount == 0:
raise dbi.NoRecordError, id
(text, subject, at, expires, by) = cursor.fetchone()
return NewsRecord(id, text=text, subject=subject, at=int(at),
expires=int(expires), by=by)
else:
if old:
cursor.execute("""SELECT id, subject
FROM news
WHERE expires_at <> 0 AND expires_at < %s
ORDER BY id DESC""", int(time.time()))
else:
cursor.execute("""SELECT id, subject
FROM news
WHERE expires_at > %s OR expires_at=0""",
int(time.time()))
if cursor.rowcount == 0:
raise dbi.NoRecordError
else:
return cursor.fetchall()
def remove(self, channel, id):
db = self._getDb(channel)
cursor = db.cursor()
cursor.execute("""DELETE FROM news WHERE id = %s""", id)
db.commit()
if cursor.rowcount == 0:
raise dbi.NoRecordError, id
def change(self, channel, id, replacer):
db = self._getDb(channel)
cursor = db.cursor()
cursor.execute("""SELECT subject, item FROM news WHERE id=%s""", id)
if cursor.rowcount == 0:
raise dbi.NoRecordError, id
(subject, item) = cursor.fetchone()
s = '%s: %s' % (subject, item)
s = replacer(s)
(newSubject, newItem) = s.split(': ', 1)
cursor.execute("""UPDATE news SET subject=%s, item=%s WHERE id=%s""",
newSubject, newItem, id)
def NewsDB():
return SqliteNewsDB()
class News(callbacks.Privmsg):
def __init__(self):
super(News, self).__init__()
self.db = NewsDB()
self.removeOld = False
def die(self):
super(News, self).die()
self.db.close()
def add(self, irc, msg, args, channel): def add(self, irc, msg, args, channel):
"""[<channel>] <expires> <subject>: <text> """[<channel>] <expires> <subject>: <text>
@ -83,89 +191,47 @@ class News(plugins.ChannelDBHandler, callbacks.Privmsg):
now. <channel> is only necessary if the message isn't sent in the now. <channel> is only necessary if the message isn't sent in the
channel itself. channel itself.
""" """
# Parse out the args (expire_interval, news) = privmsgs.getArgs(args, required=2)
i = 0 try:
for i, arg in enumerate(args): expire_interval = int(expire_interval)
if arg.endswith(':'): (subject, text) = news.split(': ', 1)
i += 1 except ValueError:
break
if not i:
raise callbacks.ArgumentError raise callbacks.ArgumentError
added_at = int(time.time()) added_at = int(time.time())
expire_interval = int(args[0])
expires = expire_interval and (added_at + expire_interval) expires = expire_interval and (added_at + expire_interval)
subject = ' '.join(args[1:i])
text = ' '.join(args[i:])
# Set the other stuff needed for the insert. # Set the other stuff needed for the insert.
if ircdb.users.hasUser(msg.prefix): try:
name = ircdb.users.getUser(msg.prefix).name by = ircdb.users.getUserId(msg.prefix)
else: except KeyError:
name = msg.nick by = msg.nick
self.db.add(channel, subject, text, added_at, expires, by)
db = self.getDb(channel)
cursor = db.cursor()
cursor.execute("INSERT INTO news VALUES (NULL, %s, %s, %s, %s, %s)",
subject[:-1], text, added_at, expires, name)
db.commit()
irc.replySuccess() irc.replySuccess()
add = privmsgs.checkChannelCapability(add, 'news') add = privmsgs.checkChannelCapability(add, 'news')
def _readnews(self, irc, msg, args):
"""[<channel>] <number>
Display the text for news item with id <number> from <channel>.
<channel> is only necessary if the message isn't sent in the channel
itself.
"""
channel = privmsgs.getChannel(msg, args)
id = privmsgs.getArgs(args)
db = self.getDb(channel)
cursor = db.cursor()
cursor.execute("""SELECT news.item, news.subject, news.added_at,
news.expires_at, news.added_by FROM news
WHERE news.id=%s""", id)
if cursor.rowcount == 0:
irc.error('No news item matches that id.')
else:
item, subject, added_at, expires_at, added_by = cursor.fetchone()
if int(expires_at) == 0:
s = '%s (Subject: "%s", added by %s on %s)' % \
(item, subject, added_by,
time.strftime(conf.supybot.humanTimestampFormat(),
time.localtime(int(added_at))))
else:
s = '%s (Subject: "%s", added by %s on %s, expires at %s)' % \
(item, subject, added_by,
time.strftime(conf.supybot.humanTimestampFormat(),
time.localtime(int(added_at))),
time.strftime(conf.supybot.humanTimestampFormat(),
time.localtime(int(expires_at))))
irc.reply(s)
def news(self, irc, msg, args): def news(self, irc, msg, args):
"""[<channel>] [<number>] """[<channel>] [<id>]
Display the news items for <channel> in the format of '(#id) subject'. Display the news items for <channel> in the format of '(#id) subject'.
If <number> is given, retrieve only that news item; otherwise retrieve If <id> is given, retrieve only that news item; otherwise retrieve all
all news items. <channel> is only necessary if the message isn't sent news items. <channel> is only necessary if the message isn't sent in
in the channel itself. the channel itself.
""" """
channel = privmsgs.getChannel(msg, args) channel = privmsgs.getChannel(msg, args)
number = privmsgs.getArgs(args, required=0, optional=1) id = privmsgs.getArgs(args, required=0, optional=1)
if number: if id:
self._readnews(irc, msg, [channel, number]) try:
return record = self.db.get(channel, int(id))
db = self.getDb(channel) irc.reply(str(record))
cursor = db.cursor() except dbi.NoRecordError, id:
cursor.execute("""SELECT news.id, news.subject FROM news irc.errorInvalid('news item id', id)
WHERE news.expires_at > %s
OR news.expires_at=0""", int(time.time()))
if cursor.rowcount == 0:
irc.reply('No news for %s.' % channel)
else: else:
items = ['(#%s) %s' % (id, s) for (id, s) in cursor.fetchall()] try:
s = 'News for %s: %s' % (channel, '; '.join(items)) records = self.db.get(channel)
irc.reply(s) items = ['(#%s) %s' % (id, s) for (id, s) in records]
s = 'News for %s: %s' % (channel, '; '.join(items))
irc.reply(s)
except dbi.NoRecordError:
irc.reply('No news for %s.' % channel)
def remove(self, irc, msg, args, channel): def remove(self, irc, msg, args, channel):
"""[<channel>] <number> """[<channel>] <number>
@ -174,15 +240,11 @@ class News(plugins.ChannelDBHandler, callbacks.Privmsg):
only necessary if the message isn't sent in the channel itself. only necessary if the message isn't sent in the channel itself.
""" """
id = privmsgs.getArgs(args) id = privmsgs.getArgs(args)
db = self.getDb(channel) try:
cursor = db.cursor() self.db.remove(channel, id)
cursor.execute("""SELECT * FROM news WHERE id=%s""", id)
if cursor.rowcount == 0:
irc.error('No news item matches that id.')
else:
cursor.execute("""DELETE FROM news WHERE news.id = %s""", id)
db.commit()
irc.replySuccess() irc.replySuccess()
except dbi.NoRecordError:
irc.errorInvalid('news item id', id)
remove = privmsgs.checkChannelCapability(remove, 'news') remove = privmsgs.checkChannelCapability(remove, 'news')
def change(self, irc, msg, args, channel): def change(self, irc, msg, args, channel):
@ -199,19 +261,11 @@ class News(plugins.ChannelDBHandler, callbacks.Privmsg):
except ValueError, e: except ValueError, e:
irc.error(str(e)) irc.error(str(e))
return return
db = self.getDb(channel) try:
cursor = db.cursor() self.db.change(channel, id, replacer)
cursor.execute("""SELECT subject, item FROM news WHERE id=%s""", id) irc.replySuccess()
if cursor.rowcount == 0: except dbi.NoRecordError:
irc.error('No news item matches that id.') irc.errorInvalid('news item id', id)
return
(subject, item) = cursor.fetchone()
s = '%s: %s' % (subject, item)
s = replacer(s)
(newSubject, newItem) = s.split(': ')
cursor.execute("""UPDATE news SET subject=%s, item=%s WHERE id=%s""",
newSubject, newItem, id)
irc.replySuccess()
change = privmsgs.checkChannelCapability(change, 'news') change = privmsgs.checkChannelCapability(change, 'news')
def old(self, irc, msg, args): def old(self, irc, msg, args):
@ -223,31 +277,20 @@ class News(plugins.ChannelDBHandler, callbacks.Privmsg):
""" """
channel = privmsgs.getChannel(msg, args) channel = privmsgs.getChannel(msg, args)
id = privmsgs.getArgs(args, required=0, optional=1) id = privmsgs.getArgs(args, required=0, optional=1)
db = self.getDb(channel)
cursor = db.cursor()
if id: if id:
try: try:
id = int(id) record = self.db.get(channel, id, old=True)
except ValueError: irc.reply(str(record))
irc.error('%r isn\'t a valid id.' % id) except dbi.NoRecordError, id:
return irc.errorInvalid('news item id', id)
cursor.execute("""SELECT subject, item FROM news WHERE id=%s""",id)
if cursor.rowcount == 0:
irc.error('No news item matches that id.')
else:
(subject, item) = cursor.fetchone()
irc.reply('%s: %s' % (cursor, item))
else: else:
cursor.execute("""SELECT id, subject FROM news try:
WHERE expires_at <> 0 AND expires_at < %s records = self.db.get(channel, old=True)
ORDER BY id DESC""", int(time.time())) items = ['(#%s) %s' % (id, s) for (id, s) in records]
if cursor.rowcount == 0: s = 'Old news for %s: %s' % (channel, '; '.join(items))
irc.error('I have no news for that channel.') irc.reply(s)
return except dbi.NoRecordError:
subjects = ['#%s: %s' % (id, s) for (id, s) in cursor.fetchall()] irc.reply('No old news for %s.' % channel)
irc.reply(utils.commaAndify(subjects))
Class = News Class = News

View File

@ -75,11 +75,11 @@ if sqlite is not None:
self.assertRegexp('news 1', 'baz') self.assertRegexp('news 1', 'baz')
def testOldnews(self): def testOldnews(self):
self.assertError('old') self.assertRegexp('old', 'No old news')
self.assertNotError('add 0 a: b') self.assertNotError('add 0 a: b')
self.assertError('old') self.assertRegexp('old', 'No old news')
self.assertNotError('add 5 foo: bar') self.assertNotError('add 5 foo: bar')
self.assertError('old') self.assertRegexp('old', 'No old news')
print print
print 'Sleeping to expire the news item (testOldnews)' print 'Sleeping to expire the news item (testOldnews)'
time.sleep(6) time.sleep(6)