class IPstats:
def __init__(self):
+ self.redirected = 0
self.short_total = 0
self.short_api = 0
self.long_total = 0
def add_long(self, logentry):
self.long_total += 1
+ if logentry.retcode == 301:
+ return
if logentry.request is not None:
self.long_api += 1
if not self.bad_ua:
def add_short(self, logentry):
self.short_total += 1
+ if logentry.retcode == 301:
+ self.redirected += 1
+ return
if logentry.request is not None:
self.short_api += 1
self.add_long(logentry)
def add_block(self, logentry):
self.block_total += 1
- def ignores_warnings(self):
- return self.block_total > 5
+ def ignores_warnings(self, wasblocked):
+ return self.block_total > 5 or (wasblocked and self.redirected > 5)
def new_state(self, was_blocked, was_bulked):
if was_blocked:
# deblock only if the IP has been really quiet
# (properly catches the ones that simply ignore the HTTP error)
return None if self.long_total < 20 else 'block'
- if self.long_api > BLOCK_UPPER or self.short_api > BLOCK_UPPER / 3:
+ if self.long_api > BLOCK_UPPER \
+ or self.short_api > BLOCK_UPPER / 3 \
+ or (self.redirected > 100 and self.short_total == self.redirected):
# client totally overdoing it
return 'block'
if was_bulked:
if blocked:
fd.write(logstr % ('new block:', ', '.join(blocked)))
for k,v in stats.items():
- if v.ignores_warnings() and k not in notlogged:
+ if v.ignores_warnings(k in bl.prevblocks) and k not in notlogged and ':' not in k:
fd.write(logstr % ('Warning ignored:', k))
fd.close()