itte/irc.py

88 lines
3.3 KiB
Python
Raw Normal View History

2018-09-12 20:01:24 +00:00
import socket
from sys import exit
2018-09-14 05:54:21 +00:00
from time import sleep
2018-09-12 20:01:24 +00:00
class IRC:
"""Methods for basic IRC communication."""
2018-09-12 20:01:24 +00:00
debug = False
2018-09-12 20:01:24 +00:00
2018-09-14 05:54:21 +00:00
def run(self, handler, conf):
"""A routine that connects to a server, joins channels, and initialises
the request handler in a loop."""
self.connect(conf.server, conf.bot_nick)
self.join_channels(conf.channels)
while 1:
sleep(2)
data = self.receive(debug=conf.debug)
self.keep_alive(data)
self.msg = self.parse_msg(data, conf.req_prefix)
for c in conf.channels:
handler(self.msg, c)
2018-09-12 20:01:24 +00:00
def connect(self, server, bot_nick):
2018-09-12 20:01:24 +00:00
"""Connect to the server and sends user/nick information."""
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)
def disconnect(self, resp_msg, quit_msg, admin_user):
"""Notify the admin user and disconnect from the server."""
self.send("PRIVMSG", resp_msg, recvr=admin_user)
self.send("QUIT", ":" + quit_msg)
2018-09-14 05:54:21 +00:00
def send(self, command, text, *args, **kwargs):
"""Send messages given the IRC command and text. Optionally specify a
message recipient with `recvr=user`."""
recvr = kwargs.get("recvr", "")
if recvr != "":
recvr += " :"
if self.debug:
print("[debug][send] " + command + " " + recvr + text)
bs = bytes(command + " " + recvr + text + "\r\n", "utf-8")
try:
self.sock.sendall(bs)
except BrokenPipeError as err:
if self.debug:
print("[debug] " + str(err) + " at `" + \
bs.decode("utf-8").strip() + "`")
pass
def receive(self, *args, **kwargs):
"""Get messages from the connected socket."""
2018-09-14 05:54:21 +00:00
data = self.sock.recv(2040).decode("utf-8").strip("\r\n")
if self.debug:
print("[debug][recv] " + data)
return data
def keep_alive(self, line):
"""Stay connected to a server by responding to server pings."""
if "PING" in line:
self.send("PONG", ":" + line.split(":", 2)[1].split(" ", 1)[0])
def join_channels(self, channels):
"""Join channels given a list of channel names."""
for c in channels:
if c.strip() != "" or c.strip() != "#":
self.send("JOIN", c)
2018-09-12 20:01:24 +00:00
def parse_msg(self, line, req_prefix):
2018-09-14 05:54:21 +00:00
"""Using received data from a socket, extract the request, the nick and
username of the requester, the channel where the request originated and
return a dictionary of values."""
2018-09-12 20:01:24 +00:00
data = {"req": "", "req_chan": "", "nick": "", "user": ""}
if (":" + req_prefix) in line:
2018-09-12 20:01:24 +00:00
data["req"] = line.split("PRIVMSG", 1)[1].split(":" + \
req_prefix, 1)[1].strip()
data["req_chan"] = line.split("PRIVMSG ", \
1)[1].split(" :", 1)[0]
2018-09-12 20:01:24 +00:00
data["nick"] = line.split("!~", 1)[0][1:]
data["user"] = line.split("!~", 2)[1][0:].split("@", 1)[0]
return data