mirror of
https://github.com/lalbornoz/roar.git
synced 2024-11-22 15:26:37 +00:00
pngbot.py:IrcBot.connect(): set socket non-blocking, ignore BlockingIOError, and select() for writability & optionally specified timeout.
pngbot.py:IrcBot.readline(): replace settimeout()/socket.timeout-based logic w/ select() for readability & optionally specified timeout. pngbot.py:IrcBot.sendline(): select() for writability & optionally specified timeout and send() full buffer until failure. pngbot.py:IrcMiRCARTBot.dispatch(): dispatch expired timers prior to calling readline(). pngbot.py:main(): default (maximum) connect timeout to 15 seconds.
This commit is contained in:
parent
09a7995a50
commit
3a207fc53c
61
pngbot.py
61
pngbot.py
@ -24,22 +24,29 @@
|
|||||||
|
|
||||||
from itertools import chain
|
from itertools import chain
|
||||||
import base64
|
import base64
|
||||||
|
import errno, os, select, socket, sys, time
|
||||||
import json
|
import json
|
||||||
import mirc2png
|
import mirc2png
|
||||||
import os, socket, sys, time
|
import requests, urllib.request
|
||||||
import requests
|
|
||||||
import urllib.request
|
|
||||||
|
|
||||||
class IrcBot:
|
class IrcBot:
|
||||||
"""Blocking abstraction over the IRC protocol"""
|
"""Non-blocking abstraction over the IRC protocol"""
|
||||||
serverHname = serverPort = None;
|
serverHname = serverPort = None;
|
||||||
clientNick = clientIdent = clientGecos = None;
|
clientNick = clientIdent = clientGecos = None;
|
||||||
clientSocket = clientSocketFile = None;
|
clientSocket = clientSocketFile = None;
|
||||||
|
|
||||||
# {{{ connect(): Connect to server and register
|
# {{{ connect(): Connect to server and register w/ optional timeout
|
||||||
def connect(self):
|
def connect(self, timeout=None):
|
||||||
self.clientSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
self.clientSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||||
self.clientSocket.connect((self.serverHname, int(self.serverPort)))
|
self.clientSocket.setblocking(0)
|
||||||
|
try:
|
||||||
|
self.clientSocket.connect((self.serverHname, int(self.serverPort)))
|
||||||
|
except BlockingIOError:
|
||||||
|
pass
|
||||||
|
if timeout:
|
||||||
|
select.select([], [self.clientSocket.fileno()], [], timeout)
|
||||||
|
else:
|
||||||
|
select.select([], [self.clientSocket.fileno()], [])
|
||||||
self.clientSocketFile = self.clientSocket.makefile()
|
self.clientSocketFile = self.clientSocket.makefile()
|
||||||
self.sendline("NICK", self.clientNick)
|
self.sendline("NICK", self.clientNick)
|
||||||
self.sendline("USER", self.clientIdent, "0", "0", self.clientGecos)
|
self.sendline("USER", self.clientIdent, "0", "0", self.clientGecos)
|
||||||
@ -51,13 +58,12 @@ class IrcBot:
|
|||||||
self.clientSocket = self.clientSocketFile = None;
|
self.clientSocket = self.clientSocketFile = None;
|
||||||
# }}}
|
# }}}
|
||||||
# {{{ readline(): Read and parse single line from server into canonicalised list w/ optional timeout
|
# {{{ readline(): Read and parse single line from server into canonicalised list w/ optional timeout
|
||||||
def readline(self, timeout=0):
|
def readline(self, timeout=None):
|
||||||
if timeout:
|
if timeout:
|
||||||
self.clientSocket.settimeout(timeout)
|
select.select([self.clientSocket.fileno()], [], [], timeout)
|
||||||
try:
|
else:
|
||||||
msg = self.clientSocketFile.readline()
|
select.select([self.clientSocket.fileno()], [], [])
|
||||||
except socket.timeout:
|
msg = self.clientSocketFile.readline()
|
||||||
return "TIMEOUT"
|
|
||||||
if len(msg):
|
if len(msg):
|
||||||
msg = msg.rstrip("\r\n")
|
msg = msg.rstrip("\r\n")
|
||||||
else:
|
else:
|
||||||
@ -73,15 +79,24 @@ class IrcBot:
|
|||||||
msg = [""] + msg[0:]
|
msg = [""] + msg[0:]
|
||||||
return msg
|
return msg
|
||||||
# }}}
|
# }}}
|
||||||
# {{{ sendline(): Parse and send single line to server from list
|
# {{{ sendline(): Parse and send single line to server from list w/ optional timeout
|
||||||
def sendline(self, *args):
|
def sendline(self, *args, timeout=None):
|
||||||
msg = ""; argNumMax = len(args);
|
msg = ""; argNumMax = len(args);
|
||||||
for argNum in range(0, argNumMax):
|
for argNum in range(0, argNumMax):
|
||||||
if argNum == (argNumMax - 1):
|
if argNum == (argNumMax - 1):
|
||||||
msg += ":" + args[argNum]
|
msg += ":" + args[argNum]
|
||||||
else:
|
else:
|
||||||
msg += args[argNum] + " "
|
msg += args[argNum] + " "
|
||||||
return self.clientSocket.send((msg + "\r\n").encode())
|
msg = (msg + "\r\n").encode(); msgLen = len(msg); msgBytesSent = 0;
|
||||||
|
while msgBytesSent < msgLen:
|
||||||
|
if timeout:
|
||||||
|
timeLast = time.time()
|
||||||
|
select.select([], [self.clientSocket.fileno()], [], timeout)
|
||||||
|
timeNow = time.time(); timeout -= timeNow - timeLast;
|
||||||
|
else:
|
||||||
|
select.select([], [self.clientSocket.fileno()], [])
|
||||||
|
msgBytesSent = self.clientSocket.send(msg)
|
||||||
|
msg = msg[msgBytesSent:]; msgLen -= msgBytesSent;
|
||||||
# }}}
|
# }}}
|
||||||
# {{{ Initialisation method
|
# {{{ Initialisation method
|
||||||
def __init__(self, serverHname, serverPort, clientNick, clientIdent, clientGecos):
|
def __init__(self, serverHname, serverPort, clientNick, clientIdent, clientGecos):
|
||||||
@ -94,10 +109,10 @@ class IrcMiRCARTBot(IrcBot):
|
|||||||
clientChannelLastMessage = clientChannelOps = clientChannel = None
|
clientChannelLastMessage = clientChannelOps = clientChannel = None
|
||||||
clientChannelRejoinTimerNext = clientChannelRejoin = None
|
clientChannelRejoinTimerNext = clientChannelRejoin = None
|
||||||
|
|
||||||
# {{{ connect(): Connect to server and (re)initialise
|
# {{{ connect(): Connect to server and (re)initialise w/ optional timeout
|
||||||
def connect(self):
|
def connect(self, timeout=None):
|
||||||
print("Connecting to {}:{}...".format(self.serverHname, self.serverPort))
|
print("Connecting to {}:{}...".format(self.serverHname, self.serverPort))
|
||||||
super().connect()
|
super().connect(timeout)
|
||||||
print("Connected to {}:{}.".format(self.serverHname, self.serverPort))
|
print("Connected to {}:{}.".format(self.serverHname, self.serverPort))
|
||||||
print("Registering on {}:{} as {}, {}, {}...".format(self.serverHname, self.serverPort, self.clientNick, self.clientIdent, self.clientGecos))
|
print("Registering on {}:{} as {}, {}, {}...".format(self.serverHname, self.serverPort, self.clientNick, self.clientIdent, self.clientGecos))
|
||||||
self.clientLastMessage = 0; self.clientChannelOps = [];
|
self.clientLastMessage = 0; self.clientChannelOps = [];
|
||||||
@ -216,11 +231,13 @@ class IrcMiRCARTBot(IrcBot):
|
|||||||
timeNow = time.time()
|
timeNow = time.time()
|
||||||
if self.clientChannelRejoinTimerNext > timeNow:
|
if self.clientChannelRejoinTimerNext > timeNow:
|
||||||
clientTimerNextDelta = self.clientChannelRejoinTimerNext - timeNow
|
clientTimerNextDelta = self.clientChannelRejoinTimerNext - timeNow
|
||||||
|
if clientTimerNextDelta:
|
||||||
|
timeNow = time.time()
|
||||||
|
if self.clientChannelRejoinTimerNext <= timeNow:
|
||||||
|
self.dispatchTimer()
|
||||||
serverMessage = self.readline(clientTimerNextDelta)
|
serverMessage = self.readline(clientTimerNextDelta)
|
||||||
if serverMessage == None:
|
if serverMessage == None:
|
||||||
self.dispatchNone(); break;
|
self.dispatchNone(); break;
|
||||||
elif serverMessage == "TIMEOUT":
|
|
||||||
self.dispatchTimer()
|
|
||||||
elif serverMessage[1] == "001":
|
elif serverMessage[1] == "001":
|
||||||
self.dispatch001(serverMessage)
|
self.dispatch001(serverMessage)
|
||||||
elif serverMessage[1] == "353":
|
elif serverMessage[1] == "353":
|
||||||
@ -265,7 +282,7 @@ class IrcMiRCARTBot(IrcBot):
|
|||||||
def main(*argv):
|
def main(*argv):
|
||||||
_IrcMiRCARTBot = IrcMiRCARTBot(*argv[1:])
|
_IrcMiRCARTBot = IrcMiRCARTBot(*argv[1:])
|
||||||
while True:
|
while True:
|
||||||
_IrcMiRCARTBot.connect()
|
_IrcMiRCARTBot.connect(15)
|
||||||
_IrcMiRCARTBot.dispatch()
|
_IrcMiRCARTBot.dispatch()
|
||||||
_IrcMiRCARTBot.close()
|
_IrcMiRCARTBot.close()
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user