FireBot/handlers.py

184 lines
6.1 KiB
Python
Raw Normal View History

2023-11-20 23:52:18 +00:00
#!/usr/bin/python3
2023-11-09 03:20:50 +00:00
import random as r
import config as conf
import commands as cmds
2023-11-18 05:23:46 +00:00
from typing import Union, Callable
2023-11-09 03:20:50 +00:00
from overrides import bytes, bbytes
from importlib import reload
2023-11-20 23:52:18 +00:00
import bare, re, checks
2023-11-09 03:20:50 +00:00
2023-11-09 21:37:08 +00:00
def CTCP(bot: bare.bot, msg: str) -> bool:
sender = msg.split("!", 1)[0][1:]
2023-11-09 03:20:50 +00:00
kind = msg.split("\x01")[1].split(" ", 1)[0]
bot.log(f'Responding to CTCP "{kind}" from {sender}')
if kind == "VERSION":
bot.notice(
f"\x01VERSION FireBot {conf.__version__} (https://git.amcforum.wiki/Firepup650/fire-ircbot)\x01",
sender,
True,
)
return True
elif kind == "USERINFO":
bot.notice("\x01USERINFO FireBot (Firepup's bot)\x01", sender, True)
return True
elif kind == "SOURCE":
bot.notice(
"\x01SOURCE https://git.amcforum.wiki/Firepup650/fire-ircbot\x01",
sender,
True,
)
return True
elif kind == "FINGER":
bot.notice("\x01FINGER Firepup's bot\x01", sender, True)
return True
elif kind == "CLIENTINFO":
bot.notice(
"\x01CLIENTINFO ACTION VERSION USERINFO SOURCE FINGER\x01", sender, True
)
return True
bot.log(f'Unknown CTCP "{kind}"', "WARN")
return False
2023-11-09 21:37:08 +00:00
2023-11-18 05:23:46 +00:00
def PRIVMSG(bot: bare.bot, msg: str) -> Union[tuple[None, None], tuple[str, str]]:
2023-11-09 03:20:50 +00:00
# Format of ":[Nick]![ident]@[host|vhost] PRIVMSG [channel] :[message]”
name = msg.split("!", 1)[0][1:]
host = msg.split("@", 1)[1].split(" ", 1)[0]
bridge = False
2023-11-20 23:52:18 +00:00
bot.current = "user"
2023-11-15 05:26:02 +00:00
if (
(name.startswith("saxjax") and bot.server == "efnet")
or (name == "ReplIRC" and bot.server == "replirc")
2023-11-21 02:18:48 +00:00
or (
name in ["FirePyLink_", "FirePyLink"]
and bot.server in ["ircnow", "backupbox"]
)
2023-11-15 05:26:02 +00:00
):
2023-11-15 00:50:26 +00:00
if "<" in msg and ">" in msg:
bridge = True
2023-11-20 23:52:18 +00:00
bot.current = "bridge"
2023-11-09 03:20:50 +00:00
Nname = msg.split("<", 1)[1].split(">", 1)[0].strip()
if name == "ReplIRC":
name = Nname[4:]
elif name in ["FirePyLink_", "FirePyLink"]:
name = Nname.lstrip("@%~+")[3:-1]
2023-11-09 03:20:50 +00:00
else:
name = Nname
message = msg.split(">", 1)[1].strip()
else:
2023-11-09 21:37:08 +00:00
message = msg.split("PRIVMSG", 1)[1].split(":", 1)[1].strip()
2023-11-09 03:20:50 +00:00
elif name == bot.nick:
2023-11-09 21:42:17 +00:00
return None, None
2023-11-09 03:20:50 +00:00
else:
message = msg.split("PRIVMSG", 1)[1].split(":", 1)[1].strip()
chan = msg.split("PRIVMSG", 1)[1].split(":", 1)[0].strip()
2023-11-24 07:15:33 +00:00
message = conf.sub(message, bot, chan, name)
2023-11-09 03:20:50 +00:00
bot.log(
2023-11-20 23:52:18 +00:00
f'Got "{bytes(message).lazy_decode()}" from "{name}" in "{chan}" ({bot.current})',
2023-11-09 03:20:50 +00:00
)
if len(name) > bot.nicklen:
bot.log(f"Name too long ({len(name)} > {bot.nicklen})")
if not bridge:
return None, None
else:
bot.log("This user is a bridge, overriding")
2023-11-09 03:20:50 +00:00
elif chan not in bot.channels:
if not chan == bot.nick:
bot.log(
f"Channel not in channels ({chan} not in {bot.channels})",
"WARN",
)
2023-11-09 03:20:50 +00:00
if not chan.startswith(("#", "+", "&")):
chan = name
else:
bot.channels[chan] += 1
if "goat" in name.lower() and bot.gmode == True:
cmds.goat(bot, chan, name, message)
handled = False
for cmd in cmds.data:
triggers = [cmd]
triggers.extend(cmds.data[cmd]["aliases"])
2023-11-09 21:37:08 +00:00
triggers = list(call.replace("$BOTNICK", bot.nick.lower()) for call in triggers)
2023-11-09 03:20:50 +00:00
if conf.mfind(
message.lower(),
triggers,
cmds.data[cmd]["prefix"],
):
2023-11-21 02:18:48 +00:00
if "check" in cmds.data[cmd] and cmds.data[cmd]["check"]:
2023-11-20 23:52:18 +00:00
if cmds.data[cmd]["check"](bot, name, host, chan, cmd):
cmds.call[cmd](bot, chan, name, message)
2023-11-09 03:20:50 +00:00
else:
cmds.call[cmd](bot, chan, name, message)
handled = True
break
if not handled:
2023-11-20 23:52:18 +00:00
for check in cmds.regexes:
2023-11-09 03:20:50 +00:00
if re.search(
2023-11-09 21:37:08 +00:00
check.replace("$MAX", str(bot.nicklen)).replace("$BOTNICK", bot.nick),
2023-11-09 03:20:50 +00:00
message,
):
cmds.call[check](bot, chan, name, message)
handled = True
break
if not handled and conf.mfind(message, ["reload"]):
2023-11-20 23:52:18 +00:00
if checks.admin(bot, name, host, chan, "reload"):
2023-11-09 21:42:17 +00:00
return "reload", chan
2023-11-09 03:20:50 +00:00
handled = True
if not handled and len(message.split("\x01")) == 3:
2023-11-09 21:36:34 +00:00
if not CTCP(bot, message):
kind = message.split("\x01")[1]
if kind == "ACTION ducks":
2023-11-09 03:20:50 +00:00
bot.msg("\x01ACTION gets hit by a duck\x01", chan)
2023-11-09 21:36:34 +00:00
elif kind.startswith("ACTION ducks"):
2023-11-09 03:20:50 +00:00
bot.msg(
2023-11-09 21:36:34 +00:00
f"\x01ACTION gets hit by {kind.split(' ', 2)[2]}\x01",
2023-11-09 03:20:50 +00:00
chan,
)
if chan in bot.channels and bot.channels[chan] >= bot.interval:
r.seed()
bot.channels[chan] = 0
2023-11-21 02:18:30 +00:00
with open("mastermessages.txt", "r") as mm:
sel = conf.decode_escapes(
2023-11-21 02:18:48 +00:00
str(r.sample(mm.readlines(), 1))
.strip("[]'")
.replace("\\n", "")
.strip('"')
2023-11-21 02:18:30 +00:00
)
bot.msg(f"[QUOTE] {sel}", chan)
2023-11-09 21:42:17 +00:00
return None, None
2023-11-18 03:24:10 +00:00
2023-11-18 05:23:46 +00:00
def NICK(bot: bare.bot, msg: str) -> tuple[None, None]:
name = msg.split("!", 1)[0][1:]
if name == bot.nick:
bot.nick = msg.split("NICK", 1)[1].split(":", 1)[1].strip()
return None, None
2023-11-18 03:24:10 +00:00
2023-11-18 05:23:46 +00:00
def KICK(bot: bare.bot, msg: str) -> tuple[None, None]:
important = msg.split("KICK", 1)[1].split(":", 1)[0].strip().split(" ")
channel = important[0]
kicked = important[1]
if kicked == bot.nick:
bot.channels.pop(channel, None)
return None, None
2023-11-18 03:24:10 +00:00
2023-11-18 05:23:46 +00:00
def PART(bot: bare.bot, msg: str) -> tuple[None, None]:
parted = msg.split("!", 1)[0][1:]
2023-11-18 03:24:10 +00:00
channel = msg.split("PART", 1)[1].split(":", 1)[0].strip()
if parted == bot.nick:
bot.channels.pop(channel, None)
return None, None
2023-11-09 21:37:08 +00:00
2023-11-18 03:24:10 +00:00
2023-11-21 02:18:48 +00:00
handles: dict[
str, Callable[[bare.bot, str], Union[tuple[None, None], tuple[str, str]]]
] = {
"PRIVMSG": PRIVMSG,
"NICK": NICK,
"KICK": KICK,
"PART": PART,
}