Stash dead repository MiRCARTools.

This commit is contained in:
Lucio Andrés Illanes Albornoz 2018-10-25 03:06:28 +02:00
parent b42eb4e7da
commit fed2fbe90e
2 changed files with 57 additions and 28 deletions

View File

@ -38,12 +38,15 @@ class IrcClient:
self.clientSocket.close() self.clientSocket.close()
self.clientSocket = self.clientSocketFile = None; self.clientSocket = self.clientSocketFile = None;
# }}} # }}}
# {{{ connect(self, preferFamily=socket.AF_INET, timeout=None): Connect to server and register w/ optional timeout # {{{ connect(self, localAddr=None, preferFamily=socket.AF_INET, timeout=None): Connect to server and register w/ optional timeout
def connect(self, preferFamily=socket.AF_INET, timeout=None): def connect(self, localAddr=None, preferFamily=socket.AF_INET, timeout=None):
gaiInfo = socket.getaddrinfo(self.serverHname, self.serverPort, gaiInfo = socket.getaddrinfo(self.serverHname, self.serverPort,
preferFamily, socket.SOCK_STREAM, socket.IPPROTO_TCP) preferFamily, socket.SOCK_STREAM, socket.IPPROTO_TCP)
self.clientSocket = socket.socket(*gaiInfo[0][:3]) self.clientSocket = socket.socket(*gaiInfo[0][:3])
self.clientSocket.setblocking(0) self.clientSocket.setblocking(0)
if localAddr != None:
gaiInfo_ = socket.getaddrinfo(localAddr, None, preferFamily, socket.SOCK_STREAM, socket.IPPROTO_TCP)
self.clientSocket.bind(gaiInfo_[0][4])
try: try:
self.clientSocket.connect(gaiInfo[0][4]) self.clientSocket.connect(gaiInfo[0][4])
except BlockingIOError: except BlockingIOError:
@ -60,16 +63,21 @@ class IrcClient:
self.queue("USER", self.clientIdent, "0", "0", self.clientGecos) self.queue("USER", self.clientIdent, "0", "0", self.clientGecos)
return True return True
# }}} # }}}
# {{{ readline(self): Read and parse single line from server into canonicalised list, honouring timers # {{{ readline(self, timeout=30): Read and parse single line from server into canonicalised list, honouring timers
def readline(self): def readline(self, timeout=30):
if self.clientNextTimeout: if self.clientNextTimeout:
timeNow = time.time() timeNow = time.time()
if self.clientNextTimeout <= timeNow: if self.clientNextTimeout <= timeNow:
return "" return ""
else: else:
readySet = select.select([self.clientSocket.fileno()], [], [], self.clientNextTimeout - timeNow) readySet = select.select([self.clientSocket.fileno()], [], [], self.clientNextTimeout - timeNow)
if len(readySet[0]) == 0 \
and (time.time() - timeNow) >= timeout:
return ""
else: else:
readySet = select.select([self.clientSocket.fileno()], [], []) readySet = select.select([self.clientSocket.fileno()], [], [], timeout)
if len(readySet[0]) == 0:
return ""
msg = self.clientSocketFile.readline() msg = self.clientSocketFile.readline()
if len(msg): if len(msg):
msg = msg.rstrip("\r\n") msg = msg.rstrip("\r\n")
@ -99,24 +107,31 @@ class IrcClient:
msg += args[argNum] + " " msg += args[argNum] + " "
self.clientQueue.append((msg + "\r\n").encode()) self.clientQueue.append((msg + "\r\n").encode())
# }}} # }}}
# {{{ unqueue(self): Send all queued lines to server, honouring timers # {{{ unqueue(self, timeout=15): Send all queued lines to server, honouring timers
def unqueue(self): def unqueue(self, timeout=15):
while self.clientQueue: while self.clientQueue:
msg = self.clientQueue[0]; msgLen = len(msg); msgBytesSent = 0; msg = self.clientQueue[0]; msgLen = len(msg); msgBytesSent = 0;
while msgBytesSent < msgLen: while msgBytesSent < msgLen:
if self.clientNextTimeout: if self.clientNextTimeout:
timeNow = time.time() timeNow = time.time()
if self.clientNextTimeout <= timeNow: if self.clientNextTimeout <= timeNow:
self.clientQueue[0] = msg; return; self.clientQueue[0] = msg; return True;
else: else:
readySet = select.select([], [self.clientSocket.fileno()], [], self.clientNextTimeout - timeNow) readySet = select.select([], [self.clientSocket.fileno()], [], min(self.clientNextTimeout - timeNow, timeout))
if len(readySet[1]) == 0: if len(readySet[1]) == 0:
self.clientQueue[0] = msg; return; timeNow_ = time.time()
if (timeNow_ - timeNow) >= timeout:
return False
else: else:
readySet = select.select([], [self.clientSocket.fileno()], []) self.clientQueue[0] = msg; return True;
else:
readySet = select.select([], [self.clientSocket.fileno()], [], timeout)
if len(readySet[1]) == 0:
return False
msgBytesSent = self.clientSocket.send(msg) msgBytesSent = self.clientSocket.send(msg)
msg = msg[msgBytesSent:]; msgLen -= msgBytesSent; msg = msg[msgBytesSent:]; msgLen -= msgBytesSent;
del self.clientQueue[0] del self.clientQueue[0]
return True
# }}} # }}}
# #

View File

@ -34,8 +34,6 @@ from MiRCARTToPngFile import MiRCARTToPngFile
class IrcMiRCARTBot(IrcClient.IrcClient): class IrcMiRCARTBot(IrcClient.IrcClient):
"""IRC<->MiRC2png bot""" """IRC<->MiRC2png bot"""
clientChannelLastMessage = clientChannelOps = clientChannel = None
clientChannelRejoin = None
imgurApiKey = MiRCARTImgurApiKey.imgurApiKey imgurApiKey = MiRCARTImgurApiKey.imgurApiKey
# {{{ ContentTooLargeException(Exception): Raised by _urlretrieveReportHook() given download size > 1 MB # {{{ ContentTooLargeException(Exception): Raised by _urlretrieveReportHook() given download size > 1 MB
@ -111,7 +109,7 @@ class IrcMiRCARTBot(IrcClient.IrcClient):
def _dispatchPrivmsg(self, message): def _dispatchPrivmsg(self, message):
if message[2].lower() == self.clientChannel.lower() \ if message[2].lower() == self.clientChannel.lower() \
and message[3].startswith("!pngbot "): and message[3].startswith("!pngbot "):
if (int(time.time()) - self.clientLastMessage) < 5: if (int(time.time()) - self.clientChannelLastMessage) < 5:
self._log("Ignoring request on {} from {} due to rate limit: {}".format(message[2].lower(), message[0], message[3])) self._log("Ignoring request on {} from {} due to rate limit: {}".format(message[2].lower(), message[0], message[3]))
return return
elif message[0].split("!")[0].lower() not in self.clientChannelOps: elif message[0].split("!")[0].lower() not in self.clientChannelOps:
@ -161,7 +159,7 @@ class IrcMiRCARTBot(IrcClient.IrcClient):
if imgurResponse[0] == 200: if imgurResponse[0] == 200:
self._log("Uploaded as: {}".format(imgurResponse[1])) self._log("Uploaded as: {}".format(imgurResponse[1]))
self.queue("PRIVMSG", message[2], "8/!\\ Uploaded as: {}".format(imgurResponse[1])) self.queue("PRIVMSG", message[2], "8/!\\ Uploaded as: {}".format(imgurResponse[1]))
self.clientLastMessage = int(time.time()) self.clientChannelLastMessage = int(time.time())
else: else:
self._log("Upload failed with HTTP status code {}".format(imgurResponse[0])) self._log("Upload failed with HTTP status code {}".format(imgurResponse[0]))
self._log("Message from website: {}".format(imgurResponse[1])) self._log("Message from website: {}".format(imgurResponse[1]))
@ -207,14 +205,15 @@ class IrcMiRCARTBot(IrcClient.IrcClient):
if (totalSize > pow(2,20)): if (totalSize > pow(2,20)):
raise IrcMiRCARTBot.ContentTooLargeException raise IrcMiRCARTBot.ContentTooLargeException
# }}} # }}}
# {{{ connect(self, preferFamily=0, timeout=None): Connect to server and (re)initialise w/ optional timeout # {{{ connect(self, localAddr=None, preferFamily=0, timeout=None): Connect to server and (re)initialise w/ optional timeout
def connect(self, preferFamily=0, timeout=None): def connect(self, localAddr=None, preferFamily=0, timeout=None):
self._log("Connecting to {}:{}...".format(self.serverHname, self.serverPort)) self._log("Connecting to {}:{}...".format(self.serverHname, self.serverPort))
if super().connect(preferFamily=preferFamily, timeout=timeout): if super().connect(localAddr=localAddr, preferFamily=preferFamily, timeout=timeout):
self._log("Connected to {}:{}.".format(self.serverHname, self.serverPort)) self._log("Connected to {}:{}.".format(self.serverHname, self.serverPort))
self._log("Registering on {}:{} as {}, {}, {}...".format(self.serverHname, self.serverPort, self.clientNick, self.clientIdent, self.clientGecos)) self._log("Registering on {}:{} as {}, {}, {}...".format(self.serverHname, self.serverPort, self.clientNick, self.clientIdent, self.clientGecos))
self.clientLastMessage = 0; self.clientChannelOps = []; self.clientChannelLastMessage = 0; self.clientChannelOps = [];
self.clientChannelRejoin = False self.clientChannelRejoin = False
self.clientHasPing = False
return True return True
else: else:
return False return False
@ -226,13 +225,21 @@ class IrcMiRCARTBot(IrcClient.IrcClient):
timeNow = time.time() timeNow = time.time()
if self.clientNextTimeout <= timeNow: if self.clientNextTimeout <= timeNow:
self._dispatchTimer() self._dispatchTimer()
self.unqueue() if self.unqueue() == False:
self._dispatchNone(); break;
else:
serverMessage = self.readline() serverMessage = self.readline()
if serverMessage == None: if serverMessage == None:
self._dispatchNone(); break; self._dispatchNone(); break;
elif serverMessage == "": elif serverMessage == "":
if self.clientHasPing:
self._dispatchNone(); break;
else:
self.clientHasPing = True
self.queue("PING", str(time.time()))
self._log("Ping...")
continue continue
elif serverMessage[1] == "001": if serverMessage[1] == "001":
self._dispatch001(serverMessage) self._dispatch001(serverMessage)
elif serverMessage[1] == "353": elif serverMessage[1] == "353":
self._dispatch353(serverMessage) self._dispatch353(serverMessage)
@ -244,6 +251,9 @@ class IrcMiRCARTBot(IrcClient.IrcClient):
self._dispatchMode(serverMessage) self._dispatchMode(serverMessage)
elif serverMessage[1] == "PING": elif serverMessage[1] == "PING":
self._dispatchPing(serverMessage) self._dispatchPing(serverMessage)
elif serverMessage[1] == "PONG":
self._log("Pong.")
self.clientHasPing = False
elif serverMessage[1] == "PRIVMSG": elif serverMessage[1] == "PRIVMSG":
self._dispatchPrivmsg(serverMessage) self._dispatchPrivmsg(serverMessage)
# }}} # }}}
@ -259,22 +269,26 @@ class IrcMiRCARTBot(IrcClient.IrcClient):
def main(optdict, *argv): def main(optdict, *argv):
_IrcMiRCARTBot = IrcMiRCARTBot(*argv) _IrcMiRCARTBot = IrcMiRCARTBot(*argv)
while True: while True:
if "-l" in optdict:
localAddr = optdict["-l"]
else:
localAddr = None
if "-4" in optdict: if "-4" in optdict:
preferFamily = socket.AF_INET preferFamily = socket.AF_INET
elif "-6" in optdict: elif "-6" in optdict:
preferFamily = socket.AF_INET6 preferFamily = socket.AF_INET6
else: else:
preferFamily = 0 preferFamily = 0
if _IrcMiRCARTBot.connect(preferFamily=preferFamily, timeout=15): if _IrcMiRCARTBot.connect(localAddr=localAddr, preferFamily=preferFamily, timeout=15):
_IrcMiRCARTBot.dispatch() _IrcMiRCARTBot.dispatch()
_IrcMiRCARTBot.close() _IrcMiRCARTBot.close()
time.sleep(15) time.sleep(15)
if __name__ == "__main__": if __name__ == "__main__":
optlist, argv = getopt(sys.argv[1:], "46") optlist, argv = getopt(sys.argv[1:], "46l:")
optdict = dict(optlist) optdict = dict(optlist)
if len(argv) < 1 or len(argv) > 4: if len(argv) < 1 or len(argv) > 4:
print("usage: {} [-4|-6] " \ print("usage: {} [-4|-6] [-l <local hostname>]" \
"<IRC server hostname> " \ "<IRC server hostname> " \
"[<IRC server port; defaults to 6667>] " \ "[<IRC server port; defaults to 6667>] " \
"[<IRC bot nick name; defaults to pngbot>] " \ "[<IRC bot nick name; defaults to pngbot>] " \