From c32d749675f3ddeb2e39f0ae94a997329f7566b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucio=20Andr=C3=A9s=20Illanes=20Albornoz?= Date: Wed, 3 Jan 2018 02:33:12 +0100 Subject: [PATCH] IrcClient.py: split from IrcMiRCARTBot.py. IrcMiRCARTBot.py: renamed from pngbot.py, importing IrcClient.IrcClient. MiRCART.py: renamed from mirc2png.py. README.md: updated. --- IrcClient.py | 110 ++++++++++++++++++++++++++++++++++ pngbot.py => IrcMiRCARTBot.py | 93 ++-------------------------- mirc2png.py => MiRCART.py | 5 +- README.md | 6 +- 4 files changed, 122 insertions(+), 92 deletions(-) create mode 100644 IrcClient.py rename pngbot.py => IrcMiRCARTBot.py (77%) rename mirc2png.py => MiRCART.py (99%) diff --git a/IrcClient.py b/IrcClient.py new file mode 100644 index 0000000..b8eccb9 --- /dev/null +++ b/IrcClient.py @@ -0,0 +1,110 @@ +#!/usr/bin/env python3 +# +# mirc2png -- convert ASCII w/ mIRC control codes to monospaced PNG (for EFnet #MiRCART) +# Copyright (c) 2018 Lucio Andrés Illanes Albornoz +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# + +from itertools import chain +import select, socket, time + +class IrcClient: + """Non-blocking abstraction over the IRC protocol""" + serverHname = serverPort = None; + clientNick = clientIdent = clientGecos = None; + clientSocket = clientSocketFile = None; + clientNextTimeout = None + + # {{{ connect(): Connect to server and register w/ optional timeout + def connect(self, timeout=None): + self.clientSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + self.clientSocket.setblocking(0) + try: + self.clientSocket.connect((self.serverHname, int(self.serverPort))) + except BlockingIOError: + pass + if timeout: + readySet = select.select([], [self.clientSocket.fileno()], [], timeout) + if len(readySet[1]) == 0: + self.close(); return False; + else: + select.select([], [self.clientSocket.fileno()], []) + self.clientSocketFile = self.clientSocket.makefile() + self.sendline("NICK", self.clientNick) + self.sendline("USER", self.clientIdent, "0", "0", self.clientGecos) + return True + # }}} + # {{{ close(): Close connection to server + def close(self): + if self.clientSocket != None: + self.clientSocket.close() + self.clientSocket = self.clientSocketFile = None; + # }}} + # {{{ readline(): Read and parse single line from server into canonicalised list, honouring timers + def readline(self): + if self.clientNextTimeout: + timeNow = time.time() + if self.clientNextTimeout <= timeNow: + return "" + else: + readySet = select.select([self.clientSocket.fileno()], [], [], self.clientNextTimeout - timeNow) + else: + readySet = select.select([self.clientSocket.fileno()], [], []) + msg = self.clientSocketFile.readline() + if len(msg): + msg = msg.rstrip("\r\n") + else: + if len(readySet[0]) == 0: + return "" + else: + return None + msg = msg.split(" :", 1) + if len(msg) == 1: + msg = list(chain.from_iterable(m.split(" ") for m in msg)) + elif len(msg) == 2: + msg = msg[0].split(" ") + [msg[1]] + if msg[0][0] == ':': + msg = [msg[0][1:]] + msg[1:] + else: + msg = [""] + msg[0:] + return msg + # }}} + # {{{ sendline(): Parse and send single line to server from list, ignoring timers + def sendline(self, *args): + msg = ""; argNumMax = len(args); + for argNum in range(0, argNumMax): + if argNum == (argNumMax - 1): + msg += ":" + args[argNum] + else: + msg += args[argNum] + " " + msg = (msg + "\r\n").encode(); msgLen = len(msg); msgBytesSent = 0; + while msgBytesSent < msgLen: + readySet = select.select([], [self.clientSocket.fileno()], []) + msgBytesSent = self.clientSocket.send(msg) + msg = msg[msgBytesSent:]; msgLen -= msgBytesSent; + # }}} + + # + # Initialisation method + def __init__(self, serverHname, serverPort, clientNick, clientIdent, clientGecos): + self.serverHname = serverHname; self.serverPort = serverPort; + self.clientNick = clientNick; self.clientIdent = clientIdent; self.clientGecos = clientGecos; + +# vim:expandtab foldmethod=marker sw=8 ts=8 tw=120 diff --git a/pngbot.py b/IrcMiRCARTBot.py similarity index 77% rename from pngbot.py rename to IrcMiRCARTBot.py index ca701a6..5ab59ba 100755 --- a/pngbot.py +++ b/IrcMiRCARTBot.py @@ -22,95 +22,13 @@ # SOFTWARE. # -from itertools import chain import base64 -import errno, os, select, socket, sys, time +import os, sys, time import json -import mirc2png +import IrcClient, MiRCART import requests, urllib.request -class IrcBot: - """Non-blocking abstraction over the IRC protocol""" - serverHname = serverPort = None; - clientNick = clientIdent = clientGecos = None; - clientSocket = clientSocketFile = None; - clientNextTimeout = None - - # {{{ connect(): Connect to server and register w/ optional timeout - def connect(self, timeout=None): - self.clientSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - self.clientSocket.setblocking(0) - try: - self.clientSocket.connect((self.serverHname, int(self.serverPort))) - except BlockingIOError: - pass - if timeout: - readySet = select.select([], [self.clientSocket.fileno()], [], timeout) - if len(readySet[1]) == 0: - self.close(); return False; - else: - select.select([], [self.clientSocket.fileno()], []) - self.clientSocketFile = self.clientSocket.makefile() - self.sendline("NICK", self.clientNick) - self.sendline("USER", self.clientIdent, "0", "0", self.clientGecos) - return True - # }}} - # {{{ close(): Close connection to server - def close(self): - if self.clientSocket != None: - self.clientSocket.close() - self.clientSocket = self.clientSocketFile = None; - # }}} - # {{{ readline(): Read and parse single line from server into canonicalised list, honouring timers - def readline(self): - if self.clientNextTimeout: - timeNow = time.time() - if self.clientNextTimeout <= timeNow: - return "" - else: - readySet = select.select([self.clientSocket.fileno()], [], [], self.clientNextTimeout - timeNow) - else: - readySet = select.select([self.clientSocket.fileno()], [], []) - msg = self.clientSocketFile.readline() - if len(msg): - msg = msg.rstrip("\r\n") - else: - if len(readySet[0]) == 0: - return "" - else: - return None - msg = msg.split(" :", 1) - if len(msg) == 1: - msg = list(chain.from_iterable(m.split(" ") for m in msg)) - elif len(msg) == 2: - msg = msg[0].split(" ") + [msg[1]] - if msg[0][0] == ':': - msg = [msg[0][1:]] + msg[1:] - else: - msg = [""] + msg[0:] - return msg - # }}} - # {{{ sendline(): Parse and send single line to server from list, ignoring timers - def sendline(self, *args): - msg = ""; argNumMax = len(args); - for argNum in range(0, argNumMax): - if argNum == (argNumMax - 1): - msg += ":" + args[argNum] - else: - msg += args[argNum] + " " - msg = (msg + "\r\n").encode(); msgLen = len(msg); msgBytesSent = 0; - while msgBytesSent < msgLen: - readySet = select.select([], [self.clientSocket.fileno()], []) - msgBytesSent = self.clientSocket.send(msg) - msg = msg[msgBytesSent:]; msgLen -= msgBytesSent; - # }}} - # {{{ Initialisation method - def __init__(self, serverHname, serverPort, clientNick, clientIdent, clientGecos): - self.serverHname = serverHname; self.serverPort = serverPort; - self.clientNick = clientNick; self.clientIdent = clientIdent; self.clientGecos = clientGecos; - # }}} - -class IrcMiRCARTBot(IrcBot): +class IrcMiRCARTBot(IrcClient.IrcClient): """IRC<->MiRCART bot""" clientChannelLastMessage = clientChannelOps = clientChannel = None clientChannelRejoin = None @@ -277,11 +195,12 @@ class IrcMiRCARTBot(IrcBot): else: return [responseHttp.status_code] # }}} - # {{{ Initialisation method + + # + # Initialisation method def __init__(self, serverHname, serverPort="6667", clientNick="pngbot", clientIdent="pngbot", clientGecos="pngbot", clientChannel="#MiRCART"): super().__init__(serverHname, serverPort, clientNick, clientIdent, clientGecos) self.clientChannel = clientChannel - # }}} # # Entry point diff --git a/mirc2png.py b/MiRCART.py similarity index 99% rename from mirc2png.py rename to MiRCART.py index a3c34f2..9fac4cb 100755 --- a/mirc2png.py +++ b/MiRCART.py @@ -165,7 +165,9 @@ class MiRCART: self.outCurColourBg = 1; self.outCurColourFg = 15; self.inCurColourSpec = ""; self.state = self.State.STATE_CHAR; # }}} - # {{{ Initialisation method + + # + # Initialisation method def __init__(self, inFilePath, imgFilePath, fontFilePath="DejaVuSansMono.ttf", fontSize=11): self.inFilePath = inFilePath; self.inFile = open(inFilePath, "r"); self.inLines = self.inFile.readlines() @@ -189,7 +191,6 @@ class MiRCART: self.outCurX = 0; self.outCurY += 13; self.inFile.close(); self.outImg.save(imgFilePath); - # }}} # # Entry point diff --git a/README.md b/README.md index 12d6ca8..6239374 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ # mirc2png -- convert ASCII w/ mIRC control codes to monospaced PNG (for EFnet #MiRCART) -* Prerequisites: python3 && python3-pil (&& python3-{json,requests,urllib3} for pngbot.py) on Debian-family Linux distributions -* mirc2png.py usage: mirc2png.py `` `` [``] [``] -* pngbot.py usage: pngbot.py `` [``] [``] [``] [``] [``] +* Prerequisites: python3 && python3-pil (&& python3-{json,requests,urllib3} for IrcMiRCARTBot.py) on Debian-family Linux distributions +* IrcMiRCARTBot.py usage: IrcMiRCARTBot.py `` [``] [``] [``] [``] [``] +* MiRCART.py usage: MiRCART.py `` `` [``] [``]