mirror of
https://github.com/ncoevoet/ChanTracker.git
synced 2025-04-27 05:21:10 -05:00
modified a lot how channel's protection are handled and repeat / massRepeat behaviour
This commit is contained in:
parent
e0b3761f43
commit
c2b4200eae
197
plugin.py
197
plugin.py
@ -87,7 +87,6 @@ def matchHostmask (pattern,n):
|
||||
cache[host] = None
|
||||
except:
|
||||
cache[host] = None
|
||||
log.debug('checking %s / %s' % (pattern,n))
|
||||
if n.ip != None and ircutils.hostmaskPatternEqual(pattern,'%s!%s@%s' % (nick,ident,n.ip)):
|
||||
return '%s!%s@%s' % (nick,ident,n.ip)
|
||||
if ircutils.hostmaskPatternEqual(pattern,n.prefix):
|
||||
@ -269,69 +268,6 @@ def floatToGMT (t):
|
||||
return None
|
||||
return time.strftime('%Y-%m-%d %H:%M:%S GMT',time.gmtime(f))
|
||||
|
||||
class SpamQueue(object):
|
||||
timeout = 0
|
||||
def __init__(self, timeout=None, queues=None):
|
||||
if timeout is not None:
|
||||
self.timeout = timeout
|
||||
if queues is None:
|
||||
queues = ircutils.IrcDict()
|
||||
self.queues = queues
|
||||
|
||||
def __repr__(self):
|
||||
return 'SpamQueue(timeout=%r,queues=%s)' % (self.timeout,repr(self.queues))
|
||||
|
||||
def reset (self,data):
|
||||
q = self._getQueue(data,insert=False)
|
||||
if q is not None:
|
||||
q.reset()
|
||||
key = self.key(data)
|
||||
self.queues[key] = q
|
||||
|
||||
def key (self,data):
|
||||
return data[0]
|
||||
|
||||
def getTimeout(self):
|
||||
if isinstance(self.timeout, collections.Callable):
|
||||
return self.timeout()
|
||||
else:
|
||||
return self.timeout
|
||||
|
||||
def _getQueue(self,data,insert=True):
|
||||
try:
|
||||
return self.queues[self.key(data)]
|
||||
except KeyError:
|
||||
if insert:
|
||||
getTimeout = lambda : self.getTimeout()
|
||||
q = utils.structures.TimeoutQueue(getTimeout)
|
||||
self.queues[self.key(data)] = q
|
||||
return q
|
||||
else:
|
||||
return None
|
||||
|
||||
def enqueue(self,data,what=None):
|
||||
if what is None:
|
||||
what = data
|
||||
q = self._getQueue(data)
|
||||
q.enqueue(what)
|
||||
|
||||
def len (self,data):
|
||||
q = self._getQueue(data,insert=False)
|
||||
if q is not None:
|
||||
return len(q)
|
||||
else:
|
||||
return 0
|
||||
|
||||
def has (self,data,what):
|
||||
q = self._getQueue(data,insert=False)
|
||||
if q is not None:
|
||||
if what is None:
|
||||
what = data
|
||||
for elt in q:
|
||||
if elt == what:
|
||||
return True
|
||||
return False
|
||||
|
||||
class Ircd (object):
|
||||
# define an ircd, keeps Chan and Nick items
|
||||
def __init__(self,irc,logsSize):
|
||||
@ -853,12 +789,11 @@ class Chan (object):
|
||||
# now stuff here is related to protection
|
||||
self.spam = ircutils.IrcDict()
|
||||
self.repeatLogs = ircutils.IrcDict()
|
||||
self.massPattern = ircutils.IrcDict()
|
||||
self.nicks = ircutils.IrcDict()
|
||||
|
||||
def isWrong (self,pattern):
|
||||
if 'bad' in self.spam:
|
||||
if self.spam['bad'].len([pattern]) > 0:
|
||||
if 'bad' in self.spam and pattern in self.spam['bad']:
|
||||
if len(self.spam['bad'][pattern]) > 0:
|
||||
return True
|
||||
return False
|
||||
|
||||
@ -1372,23 +1307,16 @@ class ChanTracker(callbacks.Plugin,plugins.ChannelDBHandler):
|
||||
remove = wrap(remove,['op','nickInChannel',additional('text')])
|
||||
|
||||
def match (self,irc,msg,args,channel,prefix):
|
||||
"""[<channel>] <nick|pattern>
|
||||
"""[<channel>] <nick>
|
||||
|
||||
returns active mode that targets pattern or nick given"""
|
||||
returns active mode that targets nick given, nick must be in a channel shared by with the bot"""
|
||||
i = self.getIrc(irc)
|
||||
n = None
|
||||
if prefix in i.nicks:
|
||||
n = self.getNick(irc,prefix)
|
||||
else:
|
||||
n = Nick(0)
|
||||
if prefix.find('#') != -1:
|
||||
a = prefix.split('#')
|
||||
username = a[1]
|
||||
prefix = a[0]
|
||||
n.setPrefix(prefix)
|
||||
n.setUsername(username)
|
||||
else:
|
||||
n.setPrefix(prefix)
|
||||
irc.reply('unknow nick')
|
||||
return
|
||||
results = i.against(irc,channel,n,msg.prefix,self.getDb(irc.network))
|
||||
if len(results):
|
||||
irc.reply(' '.join(results), private=True)
|
||||
@ -2089,6 +2017,9 @@ class ChanTracker(callbacks.Plugin,plugins.ChannelDBHandler):
|
||||
del chan.nicks[nick]
|
||||
if best in chan.repeatLogs:
|
||||
del chan.repeatLogs[best]
|
||||
for k in chan.spam:
|
||||
if best in chan.spam[k]:
|
||||
del chan.spam[k][best]
|
||||
schedule.addEvent(nrm,time.time()+self.registryValue('cycleLife')+10)
|
||||
|
||||
def doQuit (self,irc,msg):
|
||||
@ -2300,30 +2231,17 @@ class ChanTracker(callbacks.Plugin,plugins.ChannelDBHandler):
|
||||
n.addLog(channel,'NOTICE | %s' % text)
|
||||
isVip = self._isVip(irc,channel,n)
|
||||
if not isVip:
|
||||
isPattern = False
|
||||
for pattern in chan.massPattern:
|
||||
if self._strcompare(chan.massPattern[pattern],text) >= self.registryValue('massRepeatPercent',channel=channel):
|
||||
isNotice = self._isSomething(irc,channel,best,'notice')
|
||||
isMass = self._isMassRepeat(irc,channel,text)
|
||||
isBad = False
|
||||
if isMass:
|
||||
kind = 'massRepeat'
|
||||
mode = self.registryValue('%sMode' % kind,channel=channel)
|
||||
duration = self.registryValue('%sDuration' % kind,channel=channel)
|
||||
comment = self.registryValue('%sComment' % kind,channel=channel)
|
||||
self._act(irc,channel,mode,best,duration,comment)
|
||||
self._isBad(irc,channel,best) # increment bad
|
||||
self._isBad(irc,channel,best)
|
||||
self.forceTickle = True
|
||||
isPattern = True
|
||||
if not isPattern:
|
||||
isNotice = self._isSomething(irc,channel,best,'notice')
|
||||
isMass = False
|
||||
isBad = False
|
||||
if len(text) >= self.registryValue('massRepeatChars',channel=channel):
|
||||
isMass = self._isSomething(irc,channel,text,'massRepeat')
|
||||
if isMass:
|
||||
if not text in chan.massPattern:
|
||||
chan.massPattern[text] = text
|
||||
def unpattern ():
|
||||
if text in chan.massPattern:
|
||||
del chan.massPattern[text]
|
||||
schedule.addEvent(unpattern,time.time()+self.registryValue('massRepeatDuration',channel=channel))
|
||||
if isNotice:
|
||||
isBad = self._isSomething(irc,channel,best,'bad')
|
||||
if isNotice or isBad:
|
||||
@ -2333,8 +2251,6 @@ class ChanTracker(callbacks.Plugin,plugins.ChannelDBHandler):
|
||||
else:
|
||||
kind = 'notice'
|
||||
mode = self.registryValue('%sMode' % kind,channel=channel)
|
||||
if len(mode) > 1:
|
||||
mode = mode[0]
|
||||
duration = self.registryValue('%sDuration' % kind,channel=channel)
|
||||
comment = self.registryValue('%sComment' % kind,channel=channel)
|
||||
self._act(irc,channel,mode,best,duration,comment)
|
||||
@ -2411,18 +2327,6 @@ class ChanTracker(callbacks.Plugin,plugins.ChannelDBHandler):
|
||||
isVip = self._isVip(irc,channel,n)
|
||||
# checking if message matchs living massRepeatPattern
|
||||
if not isVip:
|
||||
for pattern in chan.massPattern:
|
||||
if self._strcompare(chan.massPattern[pattern],text) >= self.registryValue('massRepeatPercent',channel=channel):
|
||||
kind = 'massRepeat'
|
||||
mode = self.registryValue('%sMode' % kind,channel=channel)
|
||||
duration = self.registryValue('%sDuration' % kind,channel=channel)
|
||||
comment = self.registryValue('%sComment' % kind,channel=channel)
|
||||
self._act(irc,channel,mode,best,duration,comment)
|
||||
self._isBad(irc,channel,best) # increment bad user count
|
||||
self.forceTickle = True
|
||||
# no needs to check others protection
|
||||
continue
|
||||
|
||||
isCtcp = False
|
||||
if isCtcpMsg and not isAction:
|
||||
isCtcp = self._isSomething(irc,channel,best,'ctcp')
|
||||
@ -2431,16 +2335,15 @@ class ChanTracker(callbacks.Plugin,plugins.ChannelDBHandler):
|
||||
isRepeat = self._isRepeat(irc,channel,best,text)
|
||||
isHilight = self._isHilight(irc,channel,best,text)
|
||||
isCap = self._isCap(irc,channel,best,text)
|
||||
isMass = False
|
||||
if len(text) >= self.registryValue('massRepeatChars',channel=channel):
|
||||
isMass = self._isSomething(irc,channel,text,'massRepeat')
|
||||
isMass = self._isMassRepeat(irc,channel,text)
|
||||
if isMass:
|
||||
if not text in chan.massPattern:
|
||||
chan.massPattern[text] = text
|
||||
def unpattern ():
|
||||
if text in chan.massPattern:
|
||||
del chan.massPattern[text]
|
||||
schedule.addEvent(unpattern,time.time()+self.registryValue('massRepeatDuration',channel=channel))
|
||||
kind = 'massRepeat'
|
||||
mode = self.registryValue('%sMode' % kind,channel=channel)
|
||||
duration = self.registryValue('%sDuration' % kind,channel=channel)
|
||||
comment = self.registryValue('%sComment' % kind,channel=channel)
|
||||
self._act(irc,channel,mode,best,duration,comment)
|
||||
self._isBad(irc,channel,best)
|
||||
self.forceTickle = True
|
||||
if isFlood or isHilight or isRepeat or isCap or isCtcp or isLowFlood:
|
||||
isBad = self._isBad(irc,channel,best)
|
||||
kind = None
|
||||
@ -2756,13 +2659,14 @@ class ChanTracker(callbacks.Plugin,plugins.ChannelDBHandler):
|
||||
return False
|
||||
chan = self.getChan(irc,channel)
|
||||
life = self.registryValue('%sLife' % prop,channel=channel)
|
||||
if not prop in chan.spam or chan.spam[prop].timeout != life:
|
||||
# reset queue if config has changed
|
||||
chan.spam[prop] = SpamQueue(life)
|
||||
chan.spam[prop].enqueue([key])
|
||||
if chan.spam[prop].len([key]) > limit:
|
||||
if not prop in chan.spam:
|
||||
chan.spam[prop] = {}
|
||||
if not key in chan.spam[prop] or chan.spam[prop][key].timeout != life:
|
||||
chan.spam[prop][key] = utils.structures.TimeoutQueue(life)
|
||||
chan.spam[prop][key].enqueue(key)
|
||||
if len(chan.spam[prop][key]) > limit:
|
||||
log.debug('[%s] %s is detected as %s' % (channel,key,prop))
|
||||
chan.spam[prop].reset([key])
|
||||
chan.spam[prop][key].reset()
|
||||
return True
|
||||
return False
|
||||
|
||||
@ -2795,31 +2699,43 @@ class ChanTracker(callbacks.Plugin,plugins.ChannelDBHandler):
|
||||
return count > limit
|
||||
|
||||
def _isRepeat(self,irc,channel,key,message):
|
||||
limit = self.registryValue('repeatPermit',channel=channel)
|
||||
if limit < 0:
|
||||
if self.registryValue('repeatPermit',channel=channel) < 0:
|
||||
return False
|
||||
chan = self.getChan(irc,channel)
|
||||
## needed to compare with previous text
|
||||
if limit == 0:
|
||||
max = 2
|
||||
else:
|
||||
max = limit*2
|
||||
if not key in chan.repeatLogs:
|
||||
chan.repeatLogs[key] = utils.structures.MaxLengthQueue(max)
|
||||
timeout = self.registryValue('repeatLife',channel=channel)
|
||||
if not key in chan.repeatLogs or chan.repeatLogs[key].timeout != timeout:
|
||||
chan.repeatLogs[key] = utils.structures.TimeoutQueue(timeout)
|
||||
logs = chan.repeatLogs[key]
|
||||
if max != logs.length:
|
||||
logs = chan.repeatLogs[key] = utils.structures.MaxLengthQueue(max)
|
||||
trigger = self.registryValue('repeatPercent',channel=channel)
|
||||
result = False
|
||||
if len(logs) > 0:
|
||||
flag = False
|
||||
for entry in logs:
|
||||
if self._strcompare(message,entry) >= trigger:
|
||||
for msg in logs:
|
||||
if self._strcompare(message,msg) >= trigger:
|
||||
flag = True
|
||||
break
|
||||
if flag:
|
||||
result = self._isSomething(irc,channel,key,'repeat')
|
||||
logs.enqueue(message)
|
||||
chan.repeatLogs[key].enqueue(message)
|
||||
return result
|
||||
|
||||
def _isMassRepeat(self,irc,channel,message):
|
||||
if self.registryValue('massRepeatPermit',channel=channel) < 0 or len(message) < self.registryValue('massRepeatChars',channel=channel):
|
||||
return False
|
||||
chan = self.getChan(irc,channel)
|
||||
life = self.registryValue('massRepeatLife',channel=channel)
|
||||
if not channel in chan.repeatLogs or chan.repeatLogs[channel].timeout != life:
|
||||
chan.repeatLogs[channel] = utils.structures.TimeoutQueue(life)
|
||||
logs = chan.repeatLogs[channel]
|
||||
trigger = self.registryValue('massRepeatPercent',channel=channel)
|
||||
result = False
|
||||
flag = False
|
||||
for msg in logs:
|
||||
if self._strcompare(message,msg) >= trigger:
|
||||
flag = True
|
||||
break
|
||||
if flag:
|
||||
result = self._isSomething(irc,channel,channel,'massRepeat')
|
||||
chan.repeatLogs[channel].enqueue(message)
|
||||
return result
|
||||
|
||||
def _isCap(self,irc,channel,key,message):
|
||||
@ -2851,3 +2767,4 @@ class ChanTracker(callbacks.Plugin,plugins.ChannelDBHandler):
|
||||
|
||||
Class = ChanTracker
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user