Modifed protocal module to accept non spec confirming ircd's, Daemonize bot

This commit is contained in:
Matt Arnold 2022-03-08 14:17:15 -05:00
parent 37d0d9837e
commit 2b56dabda7
2 changed files with 64 additions and 39 deletions

26
IRC.py
View File

@ -4,6 +4,8 @@ import socket
import sys
import irctokens
import time
import logging
class IRCBadMessage(Exception):
pass
class IRCError(Exception):
@ -38,10 +40,11 @@ class IRCBot:
irc = None
def __init__(self, sock, config=None):
def __init__(self, sock, config=None, isBad=False):
self.irc = sock
self.connected = False
self.config = config
self.badircd = isBad
def send_cmd(self, line):
"""Send an IRC Command, takes an IRC command string without the CRLF
@ -68,7 +71,7 @@ class IRCBot:
def send_quit(self, quitmsg):
msg = irctokens.build("QUIT", [quitmsg])
print(msg)
logging.debug(msg)
self.send_cmd(msg)
def send_action(self, action_msg, dst):
@ -82,30 +85,35 @@ class IRCBot:
self.config["nick"] = botnick
self.config["channel"] = channel
self.config["nickpass"] = botnickpass
print("Connecting to: " + server)
logging.debug("Connecting to: " + server)
self.irc.connect((self.config["hostname"], self.config["port"]))
self.connected = True
# Perform user registration
usermsg = irctokens.build("USER", [botnick, "0","*", "RabbitEars Bot"]).format()
print(usermsg)
logging.debug(usermsg)
self.send_cmd(usermsg)
nickmsg = irctokens.build("NICK", [botnick])
self.send_cmd(nickmsg)
if self.badircd:
time.sleep(5)
authmsg = irctokens.build("NICKSERV", ['IDENTIFY', self.config['nickpass']])
self.send_cmd(authmsg)
time.sleep(5)
self.on_welcome([self.config["hostname"]])
def get_response(self):
# Get the response
resp = self.irc.recv(4096).decode("UTF-8")
msg = parsemsg(resp)
nwmsg = irctokens.tokenise(resp)
printred(nwmsg.command)
logging.info(nwmsg.command)
if nwmsg.command == "001":
self.on_welcome(nwmsg.params)
if nwmsg.command == "ERROR":
raise IRCError(str(nwmsg.params[0]))
if nwmsg.command == 'PING':
print('Sending pong')
self.irc.send(
bytes('PONG ' + LINEEND, "UTF-8"))
logging.debug('Sending pong')
pongmsg = irctokens.build("PONG", [nwmsg.params[0]])
self.send_cmd(pongmsg)
return msg

View File

@ -9,6 +9,15 @@ import sys
import irctokens
import json
import sqlite3
import logging
from daemonize import Daemonize
logging.basicConfig(filename='bot.log', encoding='utf-8', level=logging.DEBUG)
class NullDevice:
def write(self,s):
pass
LINEEND = '\r\n'
# IRC Config
config = None
@ -16,27 +25,33 @@ with open('config.json') as f:
jld = f.read()
config = json.loads(jld)
con = sqlite3.connect(config['db'])
cur = con.cursor()
# Need to pass the IRCBot class a socket the reason it doesn't do this itself is
# so you can set up TLS or not as you need it
# These provide good defaults. But your milage may vary
oursock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
context = ssl.SSLContext()
context.check_hostname = False
context.verify_mode = ssl.CERT_NONE
oursock = context.wrap_socket(oursock, server_hostname=config['hostname'])
irc = IRCBot(oursock)
irc.connect(config['hostname'],
config['port'],
config['channel'],
config['nick'],
config['nickpass'])
def do_connect():
oursock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
context = ssl.SSLContext()
context.check_hostname = False
context.verify_mode = ssl.CERT_NONE
oursock = context.wrap_socket(oursock, server_hostname=config['hostname'])
irc = IRCBot(oursock, isBad=config["isBad"])
irc.connect(config['hostname'],
config['port'],
config['channel'],
config['nick'],
config['nickpass'])
return irc
def hup_handle(sig, fr):
sys.exit()
def do_mean():
con = sqlite3.connect(config['db'])
cur = con.cursor()
qr = cur.execute("SELECT count(*) from mean").fetchone()
maxrows = int(qr[0])
slrow = str(random.randint(1, maxrows))
@ -59,22 +74,24 @@ def generate_response(person, message):
else:
return None
while True:
try:
def do_main_loop():
irc = do_connect()
while True:
try:
text = irc.get_response()
print(text[0],text[1],text[2])
if text[1] == 'PRIVMSG' and text[2][0] == config['channel']:
r = generate_response(text[0],text[2][1])
if r is not None:
irc.send_privmsg(config['channel'],r)
except KeyboardInterrupt:
irc.send_quit("Ctrl-C Pressed")
msg = oursock.recv(4096)
print(msg)
sys.exit(0)
except IRCError as e:
printred(e)
sys.exit(1)
text = irc.get_response()
logging.debug(text[0],text[1],text[2])
if text[1] == "MODE": # in leiu of RPL_WELCOME
botmode = irctokens.build("MODE", [config['nick'], '+B'])
irc.send_cmd(botmode)
if text[1] == 'PRIVMSG' and text[2][0] == config['channel']:
r = generate_response(text[0],text[2][1])
if r is not None:
irc.send_privmsg(config['channel'],r)
except IRCError as e:
logging.error(e)
sys.exit(1)
pid = "bot.pid"
daemon = Daemonize(app="theodebot", pid=pid, action=do_main_loop)
daemon.start()