diff --git a/irc.py b/irc.py index f48debc..2e86c9c 100644 --- a/irc.py +++ b/irc.py @@ -1,16 +1,12 @@ import socket +from sys import exit class IRC: - """A set of methods for basic IRC communication.""" + """Methods for basic IRC communication.""" - def __init__(self): - self.debug = False - self.sock = "" + debug = False - def is_debug(self, boolean): - self.debug = boolean - def send(self, command, text, *args, **kwargs): """Send messages given the IRC command and text. Optionally specify a message recipient with `recvr=user`.""" @@ -21,23 +17,23 @@ class IRC: print("[debug][send] " + command + " " + recvr + text) bs = bytes(command + " " + recvr + text + "\r\n", "utf-8") try: - if kwargs.get("sock", "") != "": - public_ss = kwargs.get("sock", "") - public_ss.sendall(bs) - else: - self.sock.sendall(bs) - except BrokenPipeError: - print("[debug][broken_pipe_err] " + command + " " + recvr + text) + self.sock.sendall(bs) + except BrokenPipeError as err: + if self.debug: + print("[debug] " + str(err) + " at `" + \ + bs.decode("utf-8").strip() + "`") pass def connect(self, server, bot_nick): """Connect to the server and sends user/nick information.""" - self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - self.sock.connect(server) + try: + self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + self.sock.connect(server) + except ConnectionError as err: + exit("[debug] " + str(err)) self.send("USER", bot_nick + " " + bot_nick + " " + \ bot_nick + " " + bot_nick) self.send("NICK", bot_nick) - return self.sock def disconnect(self, resp_msg, quit_msg, admin_user): """Notify the admin user and disconnect from the server.""" @@ -45,6 +41,7 @@ class IRC: self.send("QUIT", ":" + quit_msg) def receive(self, *args, **kwargs): + """Get messages from the connected socket.""" data = self.sock.recv(2040).decode("utf-8").strip("\n\r") if self.debug: print("[debug][recv] " + data) @@ -56,7 +53,7 @@ class IRC: self.send("PONG", ":" + line.split(":", 2)[1].split(" ", 1)[0]) def join_channels(self, channels): - """Join channels from a list in the config.""" + """Join channels given a list of channel names.""" for c in channels: if c.strip() != "" or c.strip() != "#": self.send("JOIN", c) diff --git a/ramen.py b/ramen.py index f0946b4..f6020eb 100644 --- a/ramen.py +++ b/ramen.py @@ -1,49 +1,56 @@ -from os import _exit +from sys import exit from random import randint +from time import sleep import config as cfg from irc import IRC class Ramen: + """Functions for ramenkan.""" - def __init__(self): - self.irc = IRC() - self.irc.is_debug = cfg.debug - self.bot_nick = cfg.bot_nick - self.admin_user = cfg.admin_user - self.admin_code = cfg.admin_code - self.req_prefix = cfg.req_prefix + irc = IRC() + irc.debug = cfg.debug - def attach(self, socket): - self.sock = socket + def run(self): + """Connect to the server and channels, initialise the listener in the + application loop.""" + self.irc.connect(cfg.server, cfg.bot_nick) + self.irc.join_channels(cfg.channels) + while 1: + sleep(2) + data = self.irc.receive(debug=cfg.debug) + self.irc.keep_alive(data) + self.msg = self.irc.parse_msg(data, cfg.req_prefix) + for chan in cfg.channels: + self.handle(chan) - def handle(self, channel, data): - """Listen for requests in a channel and match responses.""" - self.msg = self.irc.parse_msg(data, self.req_prefix) - - if self.msg["req_chan"] == self.bot_nick: + def handle(self, channel): + """Listen for requests in a channel and pass them to handler + functions.""" + if self.msg["req_chan"] == cfg.bot_nick: # Respond to some commands only from admin user - if self.msg["user"].lower() == self.admin_user.lower() and \ - self.admin_code in self.msg["req"]: - self.handle_admin_req(self.msg["req"], self.admin_user) + if self.msg["user"].lower() == cfg.admin_user.lower() and \ + cfg.admin_code in self.msg["req"]: + self.handle_admin_req(self.msg["req"], cfg.admin_user) # Respond only in the channel the request was made if channel == self.msg["req_chan"]: # General commands if self.msg["req"] == "rollcall" or self.msg["req"] == "help": self.handle_rollcall() - elif self.msg["req"] == ("water " + self.bot_nick): + elif self.msg["req"] == ("water " + cfg.bot_nick): self.handle_water() - elif self.msg["req"] == ("botsnack " + self.bot_nick): + elif self.msg["req"] == ("botsnack " + cfg.bot_nick): self.handle_botsnack() def handle_admin_req(self, req, admin_user): + """Perform admin functions.""" if "exit" in req: self.irc.send("PRIVMSG", "Okay, okay, I'll leave. (´・ω・`)", \ - recvr=admin_user, sock=self.sock) - self.irc.send("QUIT", ":noodling off", sock=self.sock) - _exit(0) + recvr=admin_user) + self.irc.send("QUIT", ":noodling off") + exit("Shutting down ...") def handle_rollcall(self): resp = ( @@ -53,8 +60,7 @@ class Ramen: "!help " "Support: +81 012-700-1MIO どうぞめしあがれ。" ) - self.irc.send("PRIVMSG", resp, recvr=self.msg["req_chan"], \ - sock=self.sock) + self.irc.send("PRIVMSG", resp, recvr=self.msg["req_chan"]) def handle_water(self): resp = [ @@ -64,8 +70,12 @@ class Ramen: "Water Level [/////////] 200% - Thanks! (^▽^)" ] self.irc.send("PRIVMSG", resp[randint(0, len(resp)-1)], \ - recvr=self.msg["req_chan"], sock=self.sock) + recvr=self.msg["req_chan"]) def handle_botsnack(self): self.irc.send("PRIVMSG", "Ramen time anytime! ヽ(´▽`)/", \ - recvr=self.msg["req_chan"], sock=self.sock) + recvr=self.msg["req_chan"]) + + +app = Ramen() +app.run() diff --git a/run.py b/run.py deleted file mode 100644 index 73b2de0..0000000 --- a/run.py +++ /dev/null @@ -1,22 +0,0 @@ -from time import sleep - -import config as cfg -from irc import IRC -from ramen import Ramen - - -irc = IRC() -irc.is_debug(cfg.debug) -socket = irc.connect(cfg.server, cfg.bot_nick) - -irc.join_channels(cfg.channels) -ramen = Ramen() -# Have run.py and ramen.py share the same socket connection -ramen.attach(socket) - -while 1: - sleep(2) - data = irc.receive(debug=cfg.debug) - irc.keep_alive(data) - for chan in cfg.channels: - ramen.handle(chan, data)