@banremoval command now accepts time in different units, such as "2 weeks", "1 month", "24h" and so on.

The units are: minutes, hours, days, weeks, months and years. One letter shortcuts allowed.
This commit is contained in:
Elián Hanisch 2012-07-04 19:23:37 -03:00
parent 3e584e6880
commit a3266bc1de
2 changed files with 109 additions and 14 deletions

View File

@ -78,6 +78,65 @@ def nowSeconds():
def fromTime(x):
return cPickle.dumps(datetime.datetime(*time.gmtime(x)[:6], **{'tzinfo': pytz.timezone("UTC")}))
timeUnits = {
'm': 60, 'minutes': 60, 'minute': 60, 'min': 60,
'h': 3600, 'hours': 3600, 'hour': 3600,
'd': 86400, 'days': 86400, 'day': 86400,
'w': 604800, 'weeks': 604800, 'week': 604800,
'M': 2592000, 'months': 2592000, 'month': 2592000,
'y': 31536000, 'years': 31536000, 'year': 31536000,
}
def readTimeDelta(s):
"""convert a string like "2 days" or "1h2d3w" into seconds"""
# split number and words
L = []
digit = buffer = None
for c in s:
if c.isdigit():
if buffer is None:
digit, buffer = True, ''
elif digit is False:
digit = True
# add unit to list
buffer = buffer.strip()
if buffer:
L.append(buffer)
buffer = ''
buffer += c
else:
if digit is None:
# need a number first
continue
if digit is True:
digit = False
# add number to list
L.append(int(buffer))
buffer = ''
buffer += c
# check last
if buffer.isdigit():
L.append(int(buffer))
else:
buffer = buffer.strip()
if buffer:
L.append(buffer)
# sum
seconds = 0
number = None
for item in L:
if isinstance(item, int):
number = item
else:
mult = timeUnits[item]
seconds += number * mult
number = None
if number:
seconds += number
return seconds
def capab(user, capability):
capability = capability.lower()
capabilities = list(user.capabilities)
@ -1289,24 +1348,44 @@ class Bantracker(callbacks.Plugin):
Sets expiration time.
"""
L = self.db_run("SELECT mask, channel FROM bans WHERE id = %s", id,
expect_result=True)
if not L:
irc.reply("I don't know any ban with that id.")
try:
seconds = readTimeDelta(timespec)
except KeyError:
irc.error("bad time format.")
return
mask, channel = L[0]
for ban in self.bans[channel]:
if mask == ban.mask:
# lets check if is already managed first
for idx, remove in enumerate(self.managedBans):
if id == remove.ban.id:
ban = remove.ban
del self.managedBans.shelf[idx]
break
else:
# no active ban it seems
irc.reply("Ban '%s' isn't active in %s." % (mask, channel))
return
L = self.db_run("SELECT mask, channel, removal FROM bans WHERE id = %s",
id, expect_result=True)
if not L:
irc.reply("I don't know any ban with that id.")
return
self.managedBans.add(BanRemoval(ban, timespec))
mask, channel, removal = L[0]
self.log.debug('asd %s', removal)
if removal:
irc.reply("Ban '%s' was already removed in %s." % (mask, channel))
return
for ban in self.bans[channel]:
if mask == ban.mask:
if ban.id is None:
ban.id = id
break
else:
# ban not in sync it seems, shouldn't happen normally.
irc.reply("Ban '%s' isn't active in %s." % (mask, channel))
return
self.managedBans.add(BanRemoval(ban, seconds))
irc.replySuccess()
banremove = wrap(banremove, ['id', 'int'])
banremove = wrap(banremove, ['id', 'text'])
def banlink(self, irc, msg, args, id, highlight):
"""<id> [<highlight>]

View File

@ -369,8 +369,24 @@ class BantrackerTestCase(ChannelPluginTestCase):
self.irc.feedMsg(ircmsgs.unban(self.channel, 'asd!*@*',
'op!user@host.net'))
self.assertResponse('banremove 1 0',
"Ban 'asd!*@*' isn't active in #test.")
"Ban 'asd!*@*' was already removed in #test.")
def testBanremoveTimeFormat(self):
cb = self.getCallback()
self.feedBan('asd!*@*')
self.assertNotError('banremove 1 10m')
self.assertEqual(cb.managedBans.shelf[0].expires, 600)
self.assertNotError('banremove 1 2 weeks')
self.assertEqual(cb.managedBans.shelf[0].expires, 1209600)
self.assertNotError('banremove 1 1m 2 days')
self.assertEqual(cb.managedBans.shelf[0].expires, 172860)
self.assertNotError('banremove 1 24h 1day')
self.assertEqual(cb.managedBans.shelf[0].expires, 172800)
self.assertNotError('banremove 1 1m1h1d1w1M1y')
self.assertEqual(cb.managedBans.shelf[0].expires, 34822860)
def testBanremoveTimeFormatBad(self):
self.assertError('banremove 1 10 apples')