56 lines
1.3 KiB
Python
56 lines
1.3 KiB
Python
|
|
from collections import defaultdict
|
|
import signal
|
|
|
|
|
|
RATELIMIT_THRESHOLD = 20
|
|
GRAYLIST_LENGTH = 8
|
|
|
|
class SpamError(ValueError):
|
|
def __str__(self):
|
|
return ' '.join(self.args)
|
|
|
|
|
|
def loadlist(fn):
|
|
try:
|
|
with open(fn) as f:
|
|
return [ l for l in ( l.strip() for l in f.readlines() if not l.startswith('#')) if l ]
|
|
except:
|
|
return []
|
|
|
|
greenlist = set()
|
|
|
|
graylist = []
|
|
def do_graylist(msg):
|
|
global graylist
|
|
graylist = [msg] + graylist[:GRAYLIST_LENGTH-1]
|
|
|
|
blacklist = loadlist('blacklist')
|
|
badwords = loadlist('badwords')
|
|
def signal_handler(_signum, _frame):
|
|
global blacklist, badwords
|
|
blacklist = load_blacklist()
|
|
badwords = load_badwords()
|
|
signal.signal(signal.SIGHUP, signal_handler)
|
|
|
|
ratelimitdict = defaultdict(lambda: 0)
|
|
def empty_ratelimit(_signum, _frame):
|
|
global ratelimitdict
|
|
ratelimitdict = defaultdict(lambda: 0)
|
|
signal.signal(signal.SIGALRM, empty_ratelimit)
|
|
signal.setitimer(signal.ITIMER_REAL, 60)
|
|
|
|
def check_spam(addr, data):
|
|
ratelimitdict[addr] += 1
|
|
try:
|
|
if ratelimitdict[addr] > RATELIMIT_THRESHOLD:
|
|
raise SpamError('rate-limit')
|
|
if any(word in data.lower() for word in badwords):
|
|
raise SpamError('badwords filter')
|
|
if addr not in greenlist and data in graylist:
|
|
raise SpamError('graylist')
|
|
except SpamError as err:
|
|
do_graylist(data)
|
|
blacklist.append(addr)
|
|
raise err
|
|
greenlist.add(addr)
|