Code cleanup and refactoring

Created send_privmsg to reduce repetition and verbosity of code

Refactored many recently-written command functions to further reduce
repetition.
This commit is contained in:
Jake Bauer 2021-10-18 03:42:25 -04:00
parent d67f7d93ec
commit d4c88f6025
2 changed files with 82 additions and 72 deletions

151
bot.py
View File

@ -1,4 +1,3 @@
# TODO: Clean up message sending by consolidating all those PRIVMSG bits
# TODO: Make separate adminhelp command for admin-only commands
import sys
@ -134,43 +133,47 @@ class Bot:
return False
def send_message(self, message):
message = message + "\n"
self.ircsock.sendall(message.encode('utf-8'))
print("\033[31m<<\033[0m " + message, end='', flush=True)
def send_privmsg(self, channel, message):
self.send_message("PRIVMSG " + channel + " :" + message)
def announce(self, message):
for channel in self.channels:
self.send_message(message)
self.send_privmsg(channel, message)
def handle_exception(self, incoming, exception):
self.exception = exception
self.send_message("PRIVMSG " + self.get_channel(incoming) + " :An unexpected error occurred. Run +showexception to see what went wrong.\n")
self.send_privmsg(self.get_channel(incoming), "An unexpected error occurred. Run +showexception to see what went wrong.")
def repeat(self, channel, message):
self.send_message("PRIVMSG " + channel + " :" + message + "\n")
self.send_privmsg(channel, message)
def connect(self):
sys.stderr.write("Connecting to: " + self.server + ":" + str(self.port) + "\n")
sys.stderr.write("Connecting to: " + self.server + ":" + str(self.port))
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((self.server, self.port))
self.ircsock = ssl.wrap_socket(s)
self.send_message("USER " + self.nick + " 0 * " + self.nick + "\n")
self.send_message("NICK "+ self.nick + "\n")
self.send_message("USER " + self.nick + " 0 * " + self.nick)
self.send_message("NICK "+ self.nick)
self.sasl_auth() or self.nickserv_auth()
for channel in self.channels:
self.send_message("JOIN "+ channel +"\n")
self.send_message("JOIN "+ channel)
def sasl_auth(self):
self.send_message("CAP REQ :sasl\n")
self.send_message("CAP REQ :sasl")
incoming = self.waitfor("CAP")
if "ACK :sasl" in incoming:
self.send_message("AUTHENTICATE PLAIN\n")
self.send_message("AUTHENTICATE PLAIN")
self.waitfor("+")
creds = self.nick + "\0" + self.nick + "\0" + self.password
creds = base64.b64encode(creds.encode('utf8')).decode('utf8')
self.send_message("AUTHENTICATE " + creds + "\n")
self.send_message("AUTHENTICATE " + creds)
incoming = self.waitfor(":SASL authentication")
if ("903" in incoming):
self.send_message("CAP END\n")
self.send_message("CAP END")
return True
else:
return False
@ -178,7 +181,7 @@ class Bot:
return False
def nickserv_auth(self):
self.send_message("PRIVMSG NickServ :" + self.password + "\n")
self.send_privmsg("NickServ", "IDENTIFY " + self.password)
incoming = self.waitfor("NickServ")
if ("You are now identified"):
return True
@ -186,129 +189,135 @@ class Bot:
return False
def disconnect(self):
self.send_message("QUIT :Quitting...\n")
self.send_message("QUIT :Quitting...")
self.ircsock.close()
def quit (self, incoming):
if self.is_admin(get_user(incoming)):
self.send_message("PRIVMSG " + self.get_channel(incoming) + " :*sigh* alright then...\n")
self.send_privmsg(self.get_channel(incoming), "*sigh* alright then...")
self.disconnect()
self.save_config()
return True
else:
self.send_message("PRIVMSG " + self.get_channel(incoming) + " :You don't have permission to use this command.\n")
self.send_privmsg(self.get_channel(incoming), "You don't have permission to use this command.")
return False
def command_help(self, incoming):
try:
self.send_message("PRIVMSG " + self.get_channel(incoming) + " :" + self.commandList[incoming.split(' ')[4]] + "\n")
self.send_privmsg(self.get_channel(incoming), self.commandList[incoming.split(' ')[4]])
except:
self.send_message("PRIVMSG " + self.get_channel(incoming) + " :Available commands: " + " ".join(("+" + x) for x in self.commandList.keys()) + "\n")
self.send_message("PRIVMSG " + self.get_channel(incoming) + " :+help <command> for more information" + "\n")
self.send_privmsg(self.get_channel(incoming), "Available commands: " + " ".join(("+" + x) for x in self.commandList.keys()))
self.send_privmsg(self.get_channel(incoming), "+help <command> for more information")
def command_version(self, incoming):
self.send_message("PRIVMSG " + self.get_channel(incoming) + " :" + self.nick + "version " + self.VERSION + " by " + self.AUTHOR + ".\n")
self.send_privmsg(self.get_channel(incoming), self.nick + "version " + self.VERSION + " by " + self.AUTHOR)
def command_quote(self, incoming):
with open(self.quotesfile, "r") as f:
lines = f.read().splitlines()
selectedLine = random.choice(lines)
self.send_message("PRIVMSG " + self.get_channel(incoming) + " :" + selectedLine + "\n")
self.send_privmsg(self.get_channel(incoming), selectedLine)
def command_time(self, incoming):
try:
message = "PRIVMSG " + self.get_channel(incoming) + " :" + datetime.now(timezone(incoming.split(' ')[4])).strftime('%Y-%m-%d %H:%M:%S') + "\n"
message = datetime.now(timezone(incoming.split(' ')[4])).strftime('%Y-%m-%d %H:%M:%S')
except:
message = "PRIVMSG " + self.get_channel(incoming) + " :Please specify a valid timezone (e.g. +time America/Toronto).\n"
self.send_message(message)
message = "Please specify a valid timezone (e.g. +time America/Toronto)."
self.send_privmsg(self.get_channel(incoming), message)
def command_roll(self, incoming):
try:
message = "PRIVMSG " + self.get_channel(incoming) + " :" + str(random.randint(1, int(incoming.split(' ')[4]))) + "\n"
message = str(random.randint(1, int(incoming.split(' ')[4])))
except:
message = "PRIVMSG " + self.get_channel(incoming) + " :Please specify a maximum number (e.g. '+roll 20').\n"
self.send_message(message)
message = "Please specify a maximum number (e.g. '+roll 20')."
self.send_privmsg(self.get_channel(incoming), message)
def command_weather(self, incoming):
try:
city = incoming.split(' ')[4]
url = "https://wttr.in/" + city + "?m&format=3"
response = requests.get(url)
message = "PRIVMSG " + self.get_channel(incoming) + " :" + response.text.strip('\n\r') + "\n"
message = response.text.strip('\n\r')
except:
message = "PRIVMSG " + self.get_channel(incoming) + " :Please specify a city (e.g. '+weather Toronto').\n"
self.send_message(message)
message = "Please specify a city (e.g. '+weather Toronto')."
self.send_privmsg(self.get_channel(incoming), message)
def command_eightball(self, incoming):
try:
incoming.split(' ')[4]
message = "PRIVMSG " + self.get_channel(incoming) + " :" + random.choice(self.eightBallResponses) + "\n"
except Exception as e:
print(e)
message = "PRIVMSG " + self.get_channel(incoming) + " :Please ask me a question.\n"
self.send_message(message)
message = random.choice(self.eightBallResponses)
except:
message = "Please ask me a question."
self.send_privmsg(self.get_channel(incoming), message)
def command_repeatsetup(self, incoming):
if not self.is_admin(incoming):
self.send_message("PRIVMSG " + self.get_channel(incoming) + " :You don't have permission to use this command.\n")
return
try:
channel = self.get_channel(incoming)
interval = int(incoming.split(' ')[4])
message = ' '.join(incoming.split(' ')[5:])
except Exception as e:
print(e)
self.send_message("PRIVMSG " + self.get_channel(incoming) + " :Invalid syntax. Expected +repeat <seconds> <message>\n")
rt = RepeatedTimer(interval, self.repeat, channel, message)
message = "You don't have permission to use this command."
else:
try:
channel = self.get_channel(incoming)
interval = int(incoming.split(' ')[4])
message = ' '.join(incoming.split(' ')[5:])
rt = RepeatedTimer(interval, self.repeat, channel, message)
message = "Repeating message every " + interval + " seconds."
except:
message = "Invalid syntax. Expected +repeat <seconds> <message>"
self.send_privmsg(self.get_channel(incoming), message)
def command_admins(self, incoming):
self.send_message("PRIVMSG " + self.get_channel(incoming) + " :Admins: " + ', '.join(self.admins) + "\n")
self.send_privmsg(self.get_channel(incoming), "Admins: " + ', '.join(self.admins))
def command_addadmin(self, incoming):
try:
candidate = incoming.split(' ')[4]
if self.is_admin(self.get_user(incoming)):
candidate = incoming.split(' ')[4]
if self.is_admin(candidate):
message = candidate + " is already an admin."
else:
self.admins.append(candidate)
message = candidate + " granted admin privileges."
else:
message = "You don't have permission to use this command."
except:
self.send_message("PRIVMSG " + self.get_channel(incoming) + " :Invalid syntax. Expected +addadmin <nick>\n")
if self.is_admin(self.get_user(incoming)):
if self.is_admin(candidate):
self.send_message("PRIVMSG " + self.get_channel(incoming) + " :" + candidate + " is already an admin.\n")
self.admins.append(candidate)
self.send_message("PRIVMSG " + self.get_channel(incoming) + " :" + candidate + " granted admin privileges.\n")
else:
self.send_message("PRIVMSG " + self.get_channel(incoming) + " :You don't have permission to use this command.\n")
message = "Invalid syntax. Expected +addadmin <nick>"
self.send_privmsg(self.get_channel(incoming), message)
def command_rmadmin(self, incoming):
try:
candidate = incoming.split(' ')[4]
if self.is_admin(self.get_user(incoming)):
candidate = incoming.split(' ')[4]
if not self.is_admin(candidate):
message = candidate + " is not an admin."
else:
self.admins.remove(candidate)
message = "Revoked " + candidate + "'s admin privileges."
else:
message = "You don't have permission to use this command."
except:
self.send_message("PRIVMSG " + self.get_channel(incoming) + " :Invalid syntax. Expected +rmadmin <nick>\n")
if self.is_admin(self.get_user(incoming)):
if not self.is_admin(candidate):
self.send_message("PRIVMSG " + self.get_channel(incoming) + " :" + candidate + " is not an admin.\n")
self.admins.remove(candidate)
self.send_message("PRIVMSG " + self.get_channel(incoming) + " : Revoked " + candidate + "'s admin privileges.\n")
else:
self.send_message("PRIVMSG " + self.get_channel(incoming) + " :You don't have permission to use this command.\n")
message = "Invalid syntax. Expected +rmadmin <nick>"
self.send_privmsg(self.get_channel(incoming), message)
def command_showexception(self, incoming):
if self.is_admin(self.get_user(incoming)):
if not self.exception:
self.send_message("PRIVMSG " + self.get_channel(incoming) + " : No exceptions occurred... yet.\n")
message = "No exceptions occurred... yet."
else:
self.send_message("PRIVMSG " + self.get_channel(incoming) + " :" + str(self.exception) + "\n")
message = str(self.exception)
else:
self.send_message("PRIVMSG " + self.get_channel(incoming) + " :You don't have permission to use this command.\n")
message = "You don't have permission to use this command."
self.send_privmsg(self.get_channel(incoming), message)
def command_chgpass(self, incoming):
try:
password = incoming.split(' ')[4]
if self.is_admin(self.get_user(incoming)):
self.send_message("PRIVMSG NickServ :SET PASSWORD " + password + "\n")
self.send_privmsg("NickServ", "SET PASSWORD " + password)
response = self.waitfor("NickServ")
if "successfully" in response:
self.password = password
self.send_message("PRIVMSG " + self.get_channel(incoming) + " :Password changed.\n")
message = + "Password changed."
else:
self.send_message("PRIVMSG " + self.get_channel(incoming) + " :Failed to change password.\n")
message = + "Failed to change password."
except:
self.send_message("PRIVMSG " + self.get_channel(incoming) + " :Invalid syntax. Expected +chgpass <new_password>\n")
message = "Invalid syntax. Expected +chgpass <new_password>"
self.send_privmsg(self.get_channel(incoming), message)

3
run.py
View File

@ -24,7 +24,7 @@ def main():
# Respond to pings
if "PING " in incoming:
print("Responding to PING.")
message = "PONG :" + bot.nick + "\n"
message = "PONG :" + bot.nick
bot.send_message(message)
continue
@ -66,6 +66,7 @@ def main():
except Exception as e:
# Don't die when something goes wrong
bot.handle_exception(incoming, e)
print(e)
continue