summaryrefslogtreecommitdiff
path: root/stuff.py
diff options
context:
space:
mode:
Diffstat (limited to 'stuff.py')
-rw-r--r--stuff.py291
1 files changed, 291 insertions, 0 deletions
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()