From ea30e6ff34f6c5356e42c23a3b0c74fbbaa17771 Mon Sep 17 00:00:00 2001 From: Pawky Laguish Date: Tue, 26 Nov 2024 21:16:05 +0000 Subject: wip --- stuff.py | 291 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 291 insertions(+) create mode 100644 stuff.py (limited to 'stuff.py') diff --git a/stuff.py b/stuff.py new file mode 100644 index 0000000..299555b --- /dev/null +++ b/stuff.py @@ -0,0 +1,291 @@ +import irctokens +from config import config as Config +from util import Util +from commands import Command +from youtube import YouTube +import sys, importlib, time + + +def stuff(bot, sock): + config = Config + util = Util(config, sock) + command = Command(config) + server = bot.server + send = util.send + + def mesg(msg: str, t=None): + util.mesg(msg, t) + + # mesg=util.mesg + server_caps = [] + wanted_caps = config.capabilities + chan = config.server.channel # main channel + autojoin_done = False + is_ctcp = False + is_pm = False + mode = "init" + nick_override = False + + def auth( + nick=config.self.nick, + passwd=config.server.nickserv_pass, + auth="nickserv", + nickserv_auth=config.server.nickserv_auth, + ): + # TODO: handle auth that isn't nickserv + if auth.lower() == "nickserv": # line.source.split("!")[0] + # TODO: on most network can probably do "PRIVMSG NickServ@services. :help" + # TODO: support actually checking the nickserv mask properly + if nickserv_auth: + nick_override = True + if config.server.nickserv_squery: + util.send( + irctokens.build( + "SQUERY", ["NickServ", f"IDENTIFY {nick} {passwd}"] + ).format() + ) + util.send( + irctokens.build( + "SQUERY", + ["NickServ", f"{config.server.nickserv_recover} {nick}"], + ).format() + ) + else: + util.mesg(f"IDENTIFY {nick} {passwd}", config.server.nickserv_path) + util.mesg( + f"{config.server.nickserv_recover} {nick}", + config.server.nickserv_path, + ) + # attempt to re-nick just in case + send(irctokens.build("NICK", [config.self.nick]).format()) + + def configure(): + config = importlib.reload(sys.modules["config"]).config + util = Util(config, sock) + command = importlib.reload(sys.modules["commands"]).Command(config) + command.YouTube = importlib.reload(sys.modules["youtube"]).YouTube + command.util = util + command.YouTube.util = util + prefixes = config.cmd.prefixes + admin_accounts = config.admin.accounts + admin_users = config.admin.hostmasks + admin_only = config.cmd.admin_only + return ( + command, + command.util, + config, + util, + prefixes, + admin_accounts, + admin_users, + admin_only, + ) + + ( + command, + command.util, + config, + util, + prefixes, + admin_accounts, + admin_users, + admin_only, + ) = configure() + send = util.send + + send(irctokens.build("NICK", [config.self.nick]).format()) + send( + irctokens.build( + "USER", [config.self.username, "0", "*", config.self.realname] + ).format() + ) + while True: + self_nick = server.nickname + recv_data = sock.recv(1024) + recv_lines = server.recv(recv_data) + + for line in recv_lines: + try: + server.parse_tokens(line) + except IndexError: + print("\x1b[31;1mNGIRCD SUCKS\x1b[0m ", line) + continue + stri = line.format() + for k, v in util.dict.items(): + stri = stri.replace(k, v) + print(f"{time.strftime('%H:%M:%S')} < {stri}") + del stri + + if line.command == "PING": + send(f"PONG :{line.params[0]}") + + if mode == "init": + if line.command == "NOTICE" and line.source != None: + if util.maskmatch(line.source, config.server.nickserv_mask): + if config.server.nickserv_auth == True: + auth() + if line.command == "433": # 433 is ERR_NICKNAMEINUSE + util.nick(config.self.nick + "_") + if ( + line.command == "376" or line.command == "422" + ): # 376 is RPL_ENDOFMOTD and 422 is ERR_NOMOTD + if config.server.nickserv_auth == True: + auth() + send(irctokens.build("CAP", ["LS", "302"]).format()) + elif line.command == "CAP" and line.params[1] == "LS": + if server_caps == []: + server_caps = line.params[2].split() + caps = [value for value in wanted_caps if value in server_caps] + # single-send is more efficient + # BUT a single invalid cap == no caps enabled at all!!! + send(irctokens.build("CAP", ["REQ", " ".join(caps)]).format()) + # for i in caps: + # send(irctokens.build("CAP", ["REQ",i]).format()) + send(irctokens.build("CAP", ["END"]).format()) + mode = "boot" + elif mode == "boot": + send(irctokens.build("JOIN", [chan]).format()) + mode = "normal" + elif mode == "normal" and autojoin_done == False: + try: + for channel in config.server.autojoin: + send("JOIN " + channel) + time.sleep(0.25) + except Exception: + True + autojoin_done = True + elif mode == "normal": + if line.command == "433" and nick_override != False: + mesg("nick in use!", chan) + util.nick(config.self.nick) + nick_override = False + else: + nick_override = False + if line.command == "INVITE": + ( + send(irctokens.build("JOIN", [line.params[1]]).format()) + if line.params[1] not in config.server.blacklisted_channels + else None + ) + elif line.command == "PRIVMSG": + if line.tags == None or "batch" not in line.tags: + is_pm = False + is_ctcp = False + target = line.params[0] + if target == self_nick: + target = line.source.split("!")[0] + is_pm = True + util.target = target + command.util.target = target + cmd = line.params[1] + + if cmd != "" and ( + is_pm + or cmd.startswith(self_nick) + or cmd[0] in prefixes + or "https://" in cmd + or "http://" in cmd + ): + # TODO: allow ignoring hostmasks + if line.hostmask.nickname in config.cmd.ignored_nicks: + continue + try: + # if message in a channel, remove prefixes + if is_pm: + command.prefix = None + else: + if cmd[0] in prefixes: + cmd = cmd.replace(cmd[0], "", 1) + command.prefix = cmd[0] + elif cmd.startswith(self_nick + ":"): + cmd = cmd.replace(self_nick + ":", "", 1) + command.prefix = self_nick + elif cmd.startswith(self_nick): + cmd = cmd.replace(self_nick, "", 1) + command.prefix = self_nick + else: + command.prefix = None + except IndexError: + continue # skip to next command + cmd = "echo IndexError or something" + try: + prefix = command.prefix or None + except UnboundLocalError or AttributeError: + prefix = None + command.prefix = prefix + cmd = cmd.strip() + try: + is_adm = ( + line.tags["account"] in admin_accounts + or line.source in admin_users + ) + except ( + KeyError, + TypeError, + ): # either no account tag, or no tags at all + is_adm = line.source in admin_users + + # update command module's info dynamically for line info + command.util.target = target + command._line = line + command.is_ctcp = is_ctcp + command.pm = is_pm + command.line = cmd + command.admin = is_adm + command.config = config + command.self_nick = self_nick + command.prefix = prefix + + if is_adm and cmd.startswith("reload"): + ( + command, + command.util, + config, + util, + prefixes, + admin_accounts, + admin_users, + admin_only, + ) = configure() + util.target = target + send = util.send + command._line = line + command.pm = is_pm + command.line = cmd + command.admin = is_adm + command.config = config + command.self_nick = self_nick + command.prefix = prefix + command.util = util + command.util.target = target + mesg("reloaded") + elif ( + cmd.startswith("eval ") + and "eval" not in config.cmd.disabled + ): + if is_adm: + try: + result = eval( + cmd[len("eval ") :].strip() or "None" + ) + except Exception as e: + mesg("Error: " + str(e)) + else: + mesg("Error: you're not authorized to eval") + elif ( + cmd.startswith("exec ") + and "exec" not in config.cmd.disabled + ): + if is_adm: + try: + result = exec( + cmd[len("exec ") :].strip() or "None" + ) + except Exception as e: + mesg("Error: " + str(e)) + else: + mesg("Error: you're not authorized to exec") + + # handle normal commands + else: + command.preq_cmd() -- cgit 1.4.1-2-gfad0