some refactoing.
* added Ban.type property * PersistentCache renamed to ReviewStore and made it work more like defaultdict.
This commit is contained in:
parent
fcbe5e92ec
commit
5ffcf6511a
|
@ -130,6 +130,7 @@ class MsgQueue(object):
|
||||||
|
|
||||||
queue = MsgQueue()
|
queue = MsgQueue()
|
||||||
|
|
||||||
|
|
||||||
class Ban(object):
|
class Ban(object):
|
||||||
"""Hold my bans"""
|
"""Hold my bans"""
|
||||||
def __init__(self, args=None, **kwargs):
|
def __init__(self, args=None, **kwargs):
|
||||||
|
@ -171,17 +172,31 @@ class Ban(object):
|
||||||
def time(self):
|
def time(self):
|
||||||
return datetime.datetime.fromtimestamp(self.when)
|
return datetime.datetime.fromtimestamp(self.when)
|
||||||
|
|
||||||
def guessBanType(mask):
|
@property
|
||||||
if mask[0] == '%':
|
def type(self):
|
||||||
return 'quiet'
|
mask = self.mask
|
||||||
elif ircutils.isUserHostmask(mask) or mask.endswith('(realname)'):
|
if mask[0] == '%':
|
||||||
return 'ban'
|
return 'quiet'
|
||||||
return 'removal'
|
elif ircutils.isUserHostmask(mask) or mask.endswith('(realname)'):
|
||||||
|
if not ('*' in mask or '?' in mask or '$' in mask):
|
||||||
|
# XXX hack over hack, we are supposing these are marks as normal
|
||||||
|
# bans aren't usually set to exact match, while marks are.
|
||||||
|
return 'mark'
|
||||||
|
return 'ban'
|
||||||
|
return 'removal'
|
||||||
|
|
||||||
class PersistentCache(dict):
|
|
||||||
|
class ReviewStore(dict):
|
||||||
def __init__(self, filename):
|
def __init__(self, filename):
|
||||||
self.filename = conf.supybot.directories.data.dirize(filename)
|
self.filename = conf.supybot.directories.data.dirize(filename)
|
||||||
self.time = 0
|
self.lastReview = 0
|
||||||
|
|
||||||
|
def __getitem__(self, k):
|
||||||
|
try:
|
||||||
|
return dict.__getitem__(self, k)
|
||||||
|
except KeyError:
|
||||||
|
self[k] = L = []
|
||||||
|
return L
|
||||||
|
|
||||||
def open(self):
|
def open(self):
|
||||||
import csv
|
import csv
|
||||||
|
@ -189,7 +204,7 @@ class PersistentCache(dict):
|
||||||
reader = csv.reader(open(self.filename, 'rb'))
|
reader = csv.reader(open(self.filename, 'rb'))
|
||||||
except IOError:
|
except IOError:
|
||||||
return
|
return
|
||||||
self.time = int(reader.next()[1])
|
self.lastReview = int(reader.next()[1])
|
||||||
for row in reader:
|
for row in reader:
|
||||||
host, value = self.deserialize(*row)
|
host, value = self.deserialize(*row)
|
||||||
try:
|
try:
|
||||||
|
@ -205,7 +220,7 @@ class PersistentCache(dict):
|
||||||
writer = csv.writer(open(self.filename, 'wb'))
|
writer = csv.writer(open(self.filename, 'wb'))
|
||||||
except IOError:
|
except IOError:
|
||||||
return
|
return
|
||||||
writer.writerow(('time', str(int(self.time))))
|
writer.writerow(('time', str(int(self.lastReview))))
|
||||||
for host, values in self.iteritems():
|
for host, values in self.iteritems():
|
||||||
for v in values:
|
for v in values:
|
||||||
writer.writerow(self.serialize(host, v))
|
writer.writerow(self.serialize(host, v))
|
||||||
|
@ -254,7 +269,7 @@ class Bantracker(callbacks.Plugin):
|
||||||
self.db = None
|
self.db = None
|
||||||
self.get_bans(irc)
|
self.get_bans(irc)
|
||||||
self.get_nicks(irc)
|
self.get_nicks(irc)
|
||||||
self.pendingReviews = PersistentCache('bt.reviews.db')
|
self.pendingReviews = ReviewStore('bt.reviews.db')
|
||||||
self.pendingReviews.open()
|
self.pendingReviews.open()
|
||||||
self._banreviewfix()
|
self._banreviewfix()
|
||||||
# add scheduled event for check bans that need review, check every hour
|
# add scheduled event for check bans that need review, check every hour
|
||||||
|
@ -464,7 +479,7 @@ class Bantracker(callbacks.Plugin):
|
||||||
return
|
return
|
||||||
# check the type of the action taken
|
# check the type of the action taken
|
||||||
mask = ban.mask
|
mask = ban.mask
|
||||||
type = guessBanType(mask)
|
type = ban.type
|
||||||
if type == 'quiet':
|
if type == 'quiet':
|
||||||
mask = mask[1:]
|
mask = mask[1:]
|
||||||
# check if type is enabled
|
# check if type is enabled
|
||||||
|
@ -479,11 +494,12 @@ class Bantracker(callbacks.Plugin):
|
||||||
if nickMatch(nick, self.registryValue('request.ignore', channel)):
|
if nickMatch(nick, self.registryValue('request.ignore', channel)):
|
||||||
return
|
return
|
||||||
if nickMatch(nick, self.registryValue('request.forward', channel)):
|
if nickMatch(nick, self.registryValue('request.forward', channel)):
|
||||||
|
# somebody else should comment this (like with bans set by bots)
|
||||||
s = "Please somebody comment on the %s of %s in %s done by %s, use:"\
|
s = "Please somebody comment on the %s of %s in %s done by %s, use:"\
|
||||||
" %scomment %s <comment>" %(type, mask, channel, nick, prefix, ban.id)
|
" %scomment %s <comment>" %(type, mask, channel, nick, prefix, ban.id)
|
||||||
self._sendForward(irc, s, 'request', channel)
|
self._sendForward(irc, s, 'request', channel)
|
||||||
else:
|
else:
|
||||||
# send to op
|
# send to operator
|
||||||
s = "Please comment on the %s of %s in %s, use: %scomment %s <comment>" \
|
s = "Please comment on the %s of %s in %s, use: %scomment %s <comment>" \
|
||||||
%(type, mask, channel, prefix, ban.id)
|
%(type, mask, channel, prefix, ban.id)
|
||||||
irc.reply(s, to=nick, private=True)
|
irc.reply(s, to=nick, private=True)
|
||||||
|
@ -494,11 +510,11 @@ class Bantracker(callbacks.Plugin):
|
||||||
# time is zero, do nothing
|
# time is zero, do nothing
|
||||||
return
|
return
|
||||||
now = time.mktime(time.gmtime())
|
now = time.mktime(time.gmtime())
|
||||||
lastreview = self.pendingReviews.time
|
lastReview = self.pendingReviews.lastReview
|
||||||
self.pendingReviews.time = now # update last time reviewed
|
self.pendingReviews.lastReview = now # update last time reviewed
|
||||||
if not lastreview:
|
if not lastReview:
|
||||||
# initialize last time reviewed timestamp
|
# initialize last time reviewed timestamp
|
||||||
lastreview = now - reviewTime
|
lastReview = now - reviewTime
|
||||||
|
|
||||||
for channel, bans in self.bans.iteritems():
|
for channel, bans in self.bans.iteritems():
|
||||||
if not self.registryValue('enabled', channel) \
|
if not self.registryValue('enabled', channel) \
|
||||||
|
@ -510,15 +526,14 @@ class Bantracker(callbacks.Plugin):
|
||||||
# the less I touch it the better.
|
# the less I touch it the better.
|
||||||
if ban.mask.endswith('$#ubuntu-read-topic'):
|
if ban.mask.endswith('$#ubuntu-read-topic'):
|
||||||
continue
|
continue
|
||||||
type = guessBanType(ban.mask)
|
|
||||||
if type == 'removal':
|
type = ban.type
|
||||||
# skip kicks
|
if type in ('removal', 'mark'):
|
||||||
continue
|
# skip kicks and marks
|
||||||
if not ('*' in ban.mask or '?' in ban.mask or '$' in ban.mask):
|
|
||||||
# XXX hack over hack, we are supposing these are marks.
|
|
||||||
continue
|
continue
|
||||||
|
|
||||||
banAge = now - ban.when
|
banAge = now - ban.when
|
||||||
reviewWindow = lastreview - ban.when
|
reviewWindow = lastReview - ban.when
|
||||||
#self.log.debug('review ban: %s ban %s by %s (%s/%s/%s %s)', channel, ban.mask,
|
#self.log.debug('review ban: %s ban %s by %s (%s/%s/%s %s)', channel, ban.mask,
|
||||||
# ban.who, reviewWindow, reviewTime, banAge, reviewTime - reviewWindow)
|
# ban.who, reviewWindow, reviewTime, banAge, reviewTime - reviewWindow)
|
||||||
if reviewWindow <= reviewTime < banAge:
|
if reviewWindow <= reviewTime < banAge:
|
||||||
|
@ -563,11 +578,8 @@ class Bantracker(callbacks.Plugin):
|
||||||
self.registryValue('bansite'),
|
self.registryValue('bansite'),
|
||||||
ban.id)
|
ban.id)
|
||||||
msg = ircmsgs.privmsg(nick, s)
|
msg = ircmsgs.privmsg(nick, s)
|
||||||
if host in self.pendingReviews \
|
if (nick, msg) not in self.pendingReviews[host]:
|
||||||
and (nick, msg) not in self.pendingReviews[host]:
|
|
||||||
self.pendingReviews[host].append((nick, msg))
|
self.pendingReviews[host].append((nick, msg))
|
||||||
else:
|
|
||||||
self.pendingReviews[host] = [(nick, msg)]
|
|
||||||
elif banAge < reviewTime:
|
elif banAge < reviewTime:
|
||||||
# since we made sure bans are sorted by time, the bans left are more recent
|
# since we made sure bans are sorted by time, the bans left are more recent
|
||||||
break
|
break
|
||||||
|
@ -596,10 +608,7 @@ class Bantracker(callbacks.Plugin):
|
||||||
self.pendingReviews.clear()
|
self.pendingReviews.clear()
|
||||||
|
|
||||||
for host, nick, msg in nodups:
|
for host, nick, msg in nodups:
|
||||||
if host in self.pendingReviews:
|
self.pendingReviews[host].append((nick, msg))
|
||||||
self.pendingReviews[host].append((nick, msg))
|
|
||||||
else:
|
|
||||||
self.pendingReviews[host] = [(nick, msg)]
|
|
||||||
|
|
||||||
def _sendReviews(self, irc, msg):
|
def _sendReviews(self, irc, msg):
|
||||||
host = ircutils.hostFromHostmask(msg.prefix)
|
host = ircutils.hostFromHostmask(msg.prefix)
|
||||||
|
@ -1225,9 +1234,9 @@ class Bantracker(callbacks.Plugin):
|
||||||
nick, host = key.split('@', 1)
|
nick, host = key.split('@', 1)
|
||||||
else:
|
else:
|
||||||
nick, host = key, None
|
nick, host = key, None
|
||||||
try:
|
if host in self.pendingReviews:
|
||||||
reviews = self.pendingReviews[host]
|
reviews = self.pendingReviews[host]
|
||||||
except KeyError:
|
else:
|
||||||
irc.reply('No reviews for %s, use --verbose for check the correct nick@host key.' % key)
|
irc.reply('No reviews for %s, use --verbose for check the correct nick@host key.' % key)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
|
@ -286,7 +286,7 @@ class BantrackerTestCase(ChannelPluginTestCase):
|
||||||
# check not pending anymore
|
# check not pending anymore
|
||||||
self.assertFalse(cb.pendingReviews)
|
self.assertFalse(cb.pendingReviews)
|
||||||
|
|
||||||
def testPersistentCache(self):
|
def testReviewStore(self):
|
||||||
"""Save pending reviews and when bans were last checked. This is needed for plugin
|
"""Save pending reviews and when bans were last checked. This is needed for plugin
|
||||||
reloads"""
|
reloads"""
|
||||||
msg1 = ircmsgs.privmsg('nick', 'Hello World')
|
msg1 = ircmsgs.privmsg('nick', 'Hello World')
|
||||||
|
|
Loading…
Reference in New Issue