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.
		
		
		
		
		
			
		
			
				
					
					
						
							83 lines
						
					
					
						
							2.9 KiB
						
					
					
				
			
		
		
	
	
							83 lines
						
					
					
						
							2.9 KiB
						
					
					
				| #!/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()
 | |
| 
 |