AttackProtector: now allow all mode+X and mode-X in configuration, and add command punishment

master
Valentin Lorentz 2011-02-13 10:54:02 +01:00
parent 9a206c1655
commit f2800b2d48
3 changed files with 26 additions and 10 deletions

View File

@ -60,8 +60,15 @@ class XpY(registry.String):
self.error()
XpY = internationalizeDocstring(XpY)
class Punishment(registry.OnlySomeStrings):
validStrings = ('ban', 'kick', 'kban', 'mode+i', 'mode+N', 'mode+m')
class Punishment(registry.String):
"""Value must be a valid punishment ('ban', 'kick', 'kban', 'mode+X',
'mode-X', 'command XXX', ...)"""
def set(self, s):
if s not in ('ban', 'kick', 'kban') and not s.startswith('mode+') and \
not s.startswith('mode-') and not s.startswith('command '):
self.error()
return
self.setValue(s)
Punishment = internationalizeDocstring(Punishment)
AttackProtector = conf.registerPlugin('AttackProtector')

View File

@ -52,7 +52,7 @@ except:
filterParser=re.compile('(?P<number>[0-9]+)p(?P<seconds>[0-9]+)')
class AttackProtectorDatabaseItem:
def __init__(self, kind, prefix, channel, protector, irc):
def __init__(self, kind, prefix, channel, protector, irc, msg):
self.kind = kind
self.prefix = prefix
self.channel = channel
@ -60,6 +60,7 @@ class AttackProtectorDatabaseItem:
self.protector = protector
value = protector.registryValue('%s.detection' % kind, channel)
self.irc = irc
self.msg = msg
parsed = filterParser.match(value)
self.expire = self.time + int(parsed.group('seconds'))
@ -125,8 +126,8 @@ class AttackProtector(callbacks.Plugin):
item = None
if not self.registryValue('%s.detection' % kind, channel) == \
'0p0':
item = AttackProtectorDatabaseItem(kind, prefix,
channel, self, irc)
item = AttackProtectorDatabaseItem(kind, prefix, channel,
self, irc, msg)
self._database.add(item)
try:
@ -134,7 +135,7 @@ class AttackProtector(callbacks.Plugin):
channel) == '0p0':
item = AttackProtectorDatabaseItem('group%s' % kind,
'*!*@*', channel,
self, irc)
self, irc, msg)
self._database.add(item)
except registry.NonExistentRegistryEntry:
pass
@ -154,6 +155,7 @@ class AttackProtector(callbacks.Plugin):
def _slot(self, lastItem):
irc = lastItem.irc
msg = lastItem.msg
channel = lastItem.channel
prefix = lastItem.prefix
nick = prefix.split('!')[0]
@ -174,6 +176,9 @@ class AttackProtector(callbacks.Plugin):
elif punishment.startswith('mode'):
msg = ircmsgs.mode(channel, punishment[len('mode'):])
irc.queueMsg(msg)
elif punishment.startswith('command '):
tokens = callbacks.tokenize(punishment[len('command '):])
self.Proxy(irc, msg, tokens)
AttackProtector = internationalizeDocstring(AttackProtector)

View File

@ -32,8 +32,10 @@ import time
from supybot.test import *
class AttackProtectorTestCase(ChannelPluginTestCase):
plugins = ('AttackProtector',)
config = {'supybot.plugins.AttackProtector.join.detection': '5p2'}
plugins = ('AttackProtector', 'Utilities')
config = {'supybot.plugins.AttackProtector.join.detection': '5p2',
'supybot.plugins.AttackProtector.part.punishment':
'command echo hi !'}
#################################
# Utilities
@ -96,13 +98,15 @@ class AttackProtectorTestCase(ChannelPluginTestCase):
for i in range(1, 5):
msg = ircmsgs.part(self.channel, prefix=self.prefix)
self.irc.feedMsg(msg)
self.failIf(self._getIfAnswerIsThisBan() == False,
msg = ircmsgs.privmsg(self.channel, 'hi !')
self.failIf(self._getIfAnswerIsEqual(msg) == False,
'No reaction to part flood.')
def testPunishNotNoPartFlood(self):
for i in range(1, 4):
msg = ircmsgs.part(self.channel, prefix=self.prefix)
self.irc.feedMsg(msg)
self.failIf(self._getIfAnswerIsThisBan(),
msg = ircmsgs.privmsg(self.channel, 'hi !')
self.failIf(self._getIfAnswerIsEqual(msg),
'Reaction to no part flood.')
#################################