#!/bin/python import asyncio import time import sys from irctokens import build, Line from ircrobots import Bot as BaseBot from ircrobots import Server as BaseServer from ircrobots import ConnectionParams from ircrobots.glob import compile as gcompile SERVERS = [ ("tilde", "localhost") ] SPAMSERVERS = [ ("0", "localhost"), ("1", "localhost"), ("2", "localhost"), ("3", "localhost"), ("4", "localhost"), ("5", "localhost"), ("6", "localhost"), ("7", "localhost"), ("8", "localhost"), ("9", "localhost"), ("10", "localhost"), ("11", "localhost"), ("12", "localhost"), ("13", "localhost"), ("14", "localhost"), ("15", "localhost"), ("16", "localhost"), ("17", "localhost"), ("18", "localhost"), ("19", "localhost"), ] KICKEES = [] KICKEES_HOSTMASK = [] EXEMPT = [] MESSAGES = { "revenge": "no u", "kick": "error 418", "quit": "bonk", "kickadd": "user added to kicklist", "kickadderr": "adding failed: user on exemption list", "kicklist": "kickees: ", "kickrm": "user removed from kicklist", "kickrmerr": "error removing user from kicklist", "exemptadd": "user added to exemptlist", "exemptlist": "exempt: ", "exemptrm": "user removed from exemptlist", "exemptrmerr": "error removing user from exemptlist", "writeexempt": "writing exempt data", "writekickee": "writing kickee data", "writekickeehostmask": "writing kickee_hostmask data", "writedone": "done!", "writeerr": "error writing files" } CHANNEL = "#chaos" PASSWORD = "hellothereperson" BOTNAME = "rndbot" OWNER = "rndusr" TOPIC = "rule one: you are now a duck. ・゜゜・。。・゜゜\\_o< QUACK!" SPAMUSER = "" LOGFILE = open(CHANNEL + ".log", "w") class SpamServer(BaseServer): async def line_read(self, line: Line): print(f"{self.name} < {line.format()}") if line.command == "001": asyncio.create_task(self.send(build("JOIN", [CHANNEL]))) if line.command == "PRIVMSG" and line.params[0] == CHANNEL: if "quit" in line.params[1] and line.hostmask.nickname == OWNER: asyncio.create_task(self.send(build("PRIVMSG", [CHANNEL, "merp"]))) asyncio.create_task(self.send(build("PART", [CHANNEL, "merp"]))) asyncio.create_task(self.send(build("QUIT"))) else: asyncio.create_task(self.send(build("PRIVMSG", [CHANNEL, "ALL HAIL IRES"]))) if line.command == "KICK": if line.params[1] == BOTNAME: time.sleep(1) asyncio.create_task(self.send(build("JOIN", [CHANNEL]))) # asyncio.create_task(build('KICK', [CHANNEL, line.params[2], MESSAGES['revenge']])) async def line_send(self, line: Line): print(f"{self.name} > {line.format()}") class Server(BaseServer): async def line_read(self, line: Line): print(f"{self.name} < {line.format()}") LOGFILE.write(f"{self.name} < {line.format()}") if line.command == "001": await self.send(build("PRIVMSG", ["NickServ", "identify " + PASSWORD])) await self.send(build("MODE", [BOTNAME, "+B"])) await self.send(build("JOIN", [CHANNEL])) if line.command == "474": await self.send(build("PRIVMSG", ["ChanServ", "unban " + CHANNEL + " " + BOTNAME])) await self.send(build("PRIVMSG", ["ChanServ", "owner " + CHANNEL + " " + BOTNAME])) await self.send(build("PRIVMSG", ["ChanServ", "invite " + CHANNEL + " " + BOTNAME])) await self.send(build("JOIN", [CHANNEL])) if line.command == "PRIVMSG" and line.params[0] == CHANNEL: if line.hostmask.nickname == OWNER: if BOTNAME + ": quit" == line.params[1]: await self.send(build('PART', [CHANNEL, MESSAGES['quit']])) exit(100) if BOTNAME + ": kickadd" in line.params[1]: if gcompile("*!*@*").match(line.params[1].split(' ')[2]): KICKEES_HOSTMASK.append(line.params[1].split(' ')[2]) await self.send(build('PRIVMSG', [CHANNEL, \ MESSAGES['kickadd']])) else: if not line.params[1].split(' ')[1] in EXEMPT: KICKEES.append(line.params[1].split(' ')[2]) await self.send(build('PRIVMSG', [CHANNEL, \ MESSAGES['kickadd']])) else: await self.send(build('PRIVMSG', [CHANNEL, \ MESSAGES['kickadderr']])) if BOTNAME + ": kicklist" in line.params[1]: await self.send(build('PRIVMSG', [CHANNEL, \ MESSAGES['kicklist'] + ' '.join(KICKEES)])) await self.send(build('PRIVMSG', [CHANNEL, \ MESSAGES['kicklist'] + ' '.join(KICKEES_HOSTMASK)])) if BOTNAME + ": kickrm" in line.params[1]: try: if gcompile("*!*@*").match(line.params[1].split(' ')[2]): KICKEES_HOSTMASK.remove(line.params[1].split(' ')[2]) else: KICKEES.remove(line.params[1].split(' ')[2]) await self.send(build('PRIVMSG', [CHANNEL, \ MESSAGES['kickrm']])) except ValueError: await self.send(build('PRIVMSG', [CHANNEL, \ MESSAGES['kickrmerr']])) if BOTNAME + ": exemptadd" in line.params[1]: EXEMPT.append(line.params[1].split(' ')[2]) await self.send(build('PRIVMSG', [CHANNEL, \ MESSAGES['exemptadd']])) if BOTNAME + ": exemptlist" in line.params[1]: await self.send(build('PRIVMSG', [CHANNEL, \ MESSAGES['exemptlist'] + ' '.join(EXEMPT)])) if BOTNAME + ": exemptrm" in line.params[1]: try: EXEMPT.remove(line.params[1].split(' ')[2]) await self.send(build('PRIVMSG', [CHANNEL, \ MESSAGES['exemptrm']])) except ValueError: await self.send(build('PRIVMSG', [CHANNEL, \ MESSAGES['exemptrmerr']])) if BOTNAME + ": ping" in line.params[1]: tmp = "" for i in self.channels[CHANNEL].users.keys(): tmp += i tmp += ' ' if len(tmp) > 100: await self.send(build('PRIVMSG', [CHANNEL, \ tmp])) tmp = "" await self.send(build('PRIVMSG', [CHANNEL, \ tmp])) if BOTNAME + ": savestate" in line.params[1]: try: fd = open("kickees", "w") await self.send(build('PRIVMSG', [CHANNEL, MESSAGES['writekickee']])) fd.writelines(i + '\n' for i in KICKEES) fd.close() fd = open("kickees_mask", "w") await self.send(build('PRIVMSG', [CHANNEL, MESSAGES['writekickeehostmask']])) fd.writelines(i + '\n' for i in KICKEES_HOSTMASK) fd.close() await self.send(build('PRIVMSG', [CHANNEL, MESSAGES['writeexempt']])) fd = open("exempt", "w") fd.writelines(i + '\n' for i in EXEMPT) fd.close() await self.send(build('PRIVMSG', [CHANNEL, MESSAGES['writedone']])) except: await self.send(build('PRIVMSG', [CHANNEL, MESSAGES['writeerr']])) if BOTNAME + ": bots" in line.params[1]: bot = SpamBot() for name, host in SPAMSERVERS: await bot.add_server(name, \ ConnectionParams(BOTNAME + name, host, 6667, False, BOTNAME)) asyncio.create_task(bot.run()) if BOTNAME + ": kick" in line.params[1]: for i in self.channels[CHANNEL].users: if i != OWNER: asyncio.create_task(self.send(build('KICK', [CHANNEL, i, 'nope']))) if line.command == "JOIN": if line.hostmask.nickname in KICKEES: await self.send(build('KICK', [CHANNEL, line.hostmask.nickname, MESSAGES['kick']])) else: for i in KICKEES_HOSTMASK: if gcompile(i).match(str(line.hostmask)): await self.send(build('KICK', [CHANNEL, line.hostmask.nickname, MESSAGES['kick']])) break if line.hostmask.nickname == "bot": global TASKCACHE TASKCACHE = asyncio.create_task(self.julian()) if line.command == "PART": if line.hostmask.nickname == 'bot' and 'TASKCACHE' in globals(): TASKCACHE.cancel() if line.command == "QUIT": if line.hostmask.nickname == 'bot' and 'TASKCACHE' in globals(): TASKCACHE.cancel() if line.command == "MODE": try: if 'l' in self.channels[CHANNEL].modes: await self.send(build('MODE', [CHANNEL, '-l'])) if 'n' in self.channels[CHANNEL].modes: await self.send(build('MODE', [CHANNEL, '-n'])) if 'm' in self.channels[CHANNEL].modes: await self.send(build('MODE', [CHANNEL, '-m'])) if 's' in self.channels[CHANNEL].modes: await self.send(build('MODE', [CHANNEL, '-s'])) if not 'q' in self.channels[CHANNEL].users[OWNER].modes: await self.send(build('MODE', [CHANNEL, '+q', OWNER])) if 'b' in self.channels[CHANNEL].users[BOTNAME].modes: await self.send(build("PRIVMSG", ["ChanServ", "unban " + CHANNEL + " " + BOTNAME])) if not 'q' in self.channels[CHANNEL].users[BOTNAME].modes: await self.send(build("PRIVMSG", ["ChanServ", "owner " + CHANNEL + " " + BOTNAME])) else: print(self.channels[CHANNEL].modes) except KeyError: pass if line.command == "KICK" and line.params[0] == CHANNEL: if line.params[1] == OWNER: await self.send(build('KICK', [CHANNEL, line.hostmask.nickname, MESSAGES['revenge']])) await self.send(build('INVITE', [CHANNEL, line.params[1]])) if line.params[1] == BOTNAME: time.sleep(1) await self.send(build('JOIN', [CHANNEL])) time.sleep(0.5) await self.send(build('KICK', [CHANNEL, line.hostmask.nickname, MESSAGES['revenge']])) if line.command == "TOPIC" and line.params[0] == CHANNEL: if line.hostmask.nickname != OWNER and \ line.hostmask.nickname != BOTNAME and \ not line.hostmask.nickname in EXEMPT: await self.send(build('TOPIC', [CHANNEL, TOPIC])) if line.command == "482": await self.send(build('TOPIC', [CHANNEL, TOPIC])) async def line_send(self, line: Line): print(f"{self.name} > {line.format()}") LOGFILE.write(f"{self.name} > {line.format()}") async def julian(self): while True: self.send(build('PRIVMSG', [CHANNEL, "hi"])) class Bot(BaseBot): def create_server(self, name: str): return Server(self, name) class SpamBot(BaseBot): def create_server(self, name: str): return SpamServer(self, name) async def main(): try: fd = open("kickees", "r") for i in fd.readlines(): if not i in EXEMPT: KICKEES.append(i.rstrip('\n')) fd.close() fd = open("kickees_mask", "r") for i in fd.readlines(): if not i in EXEMPT: KICKEES_HOSTMASK.append(i.rstrip('\n')) fd.close() fd = open("exempt", "r") for i in fd.readlines(): EXEMPT.append(i.rstrip('\n')) fd.close() except FileNotFoundError: print("warning: save state files are missing") print("proceeding without save state files") bot = Bot() for name, host in SERVERS: params = ConnectionParams(BOTNAME, host, 6667, False, BOTNAME, "totally not rndusr's bot lol") await bot.add_server(name, params) await bot.run() if __name__ == "__main__": asyncio.run(main())