You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
84 lines
2.9 KiB
84 lines
2.9 KiB
2 weeks ago
|
#!/usr/bin/env python3
|
||
|
|
||
|
import irc.bot
|
||
|
import irc.strings
|
||
|
import configparser
|
||
|
|
||
|
from expiringdict import ExpiringDict
|
||
|
|
||
|
configfile = 'spamkicker.ini'
|
||
|
|
||
|
class BotConfig:
|
||
|
def __init__(self, config):
|
||
|
general = config['general']
|
||
|
|
||
|
connections = []
|
||
|
for connection in general['connections'].split():
|
||
|
connections.append((config[connection]['server'], int(config[connection]['port'])))
|
||
|
|
||
|
self.server_list=connections
|
||
|
self.nickname=general['nick']
|
||
|
self.realname=general['real']
|
||
|
self.honeypots=[x.strip() for x in general['honeypots'].split(',')]
|
||
|
self.announce=[x.strip() for x in general['announce'].split(',')]
|
||
|
self.password=general['password']
|
||
|
self.ban_type=general['ban_type']
|
||
|
self.ban_duration=general['ban_duration']
|
||
|
|
||
|
def __repr__(self):
|
||
|
return "BotConfig(server_list={},nickname='{}',realname='{}',honeypots={},announce={},password='{}',ban_type='{}',ban_duration='{}')".format(self.server_list, self.nickname, self.realname, self.honeypots, self.announce, self.password, self.ban_type, self.ban_duration)
|
||
|
|
||
|
class SpamKickerBot(irc.bot.SingleServerIRCBot):
|
||
|
def __init__(self, botconfig):
|
||
|
self.botconfig = botconfig
|
||
|
irc.bot.SingleServerIRCBot.__init__(self, botconfig.server_list, botconfig.nickname, botconfig.realname)
|
||
|
self.spammers = ExpiringDict(max_age_seconds=300, max_len=100)
|
||
|
|
||
|
def on_nicknameinuse(self, c, e):
|
||
|
c.nick(c.get_nickname() + "_")
|
||
|
|
||
|
def on_welcome(self, c, e):
|
||
|
for channel in self.botconfig.honeypots:
|
||
|
c.join(channel)
|
||
|
for channel in self.botconfig.announce:
|
||
|
c.join(channel)
|
||
|
c.send_raw("OPER {} {}".format(c.get_nickname(), self.botconfig.password))
|
||
|
|
||
|
def on_privmsg(self, c, e):
|
||
|
self.flag_spammer(c, e.source)
|
||
|
|
||
|
def on_pubmsg(self, c, e):
|
||
|
if e.target in self.botconfig.honeypots:
|
||
|
self.flag_spammer(c, e.source)
|
||
|
|
||
|
|
||
|
def flag_spammer(self, c, source):
|
||
|
if source in self.spammers:
|
||
|
print("Spammer already flagged")
|
||
|
else:
|
||
|
self.spammers[source] = 1
|
||
|
print("Spammer flagged: {}".format(source.nick))
|
||
|
for target in self.botconfig.announce:
|
||
|
c.privmsg(target, 'Spammer identified: {} ({})'.format(source.nick, source.userhost))
|
||
|
if self.botconfig.ban_type == 'GLINE':
|
||
|
spec = source.userhost
|
||
|
elif self.botconfig.ban_type == 'ZLINE':
|
||
|
spec = source.host
|
||
|
else:
|
||
|
spec = source.userhost # Just in case, right?
|
||
|
command = ' '.join(filter(None, [self.botconfig.ban_type, spec, self.botconfig.ban_duration, ':SpamKicker']))
|
||
|
print(command)
|
||
|
c.send_raw(command)
|
||
|
|
||
|
def main():
|
||
|
config = configparser.ConfigParser()
|
||
|
config.read(configfile)
|
||
|
|
||
|
botconfig = BotConfig(config)
|
||
|
|
||
|
bot = SpamKickerBot(botconfig)
|
||
|
bot.start()
|
||
|
|
||
|
if __name__ == "__main__":
|
||
|
main()
|