modstop = lib.modstop
# module code
+class BasicServer(lib.Socketlike):
+ def __init__(self, sock, data):
+ super(BasicServer, self).__init__(sock, data)
+ # NB neither directly referencing `channel`, nor trying to pass it through a default-arg-to-a-lambda like the python docs suggest, works here.
+ # Yay python. At least passing it via bind works.
+ self.chan = data
+
+ # default getdata() and send() methods are defined by lib.Socketlike
+ # suitable for line-based protocols like IRC
+
+ def parse(self, line):
+ try:
+ bot = lib.parent.channel(self.chan).bot
+ except AttributeError: # <class 'AttributeError'> 'NoneType' object has no attribute 'bot'
+ bot = lib.parent.randbot()
+ maxlen = bot.maxmsglen() - len("PRIVMSG :") - len(self.chan)
+ while len(line) > maxlen:
+ cutat = line.rfind(' ', 0, maxlen)
+ if cutat == -1:
+ cutat = maxlen
+ bot.msg(self.chan, line[0:cutat])
+ line = line[cutat:].strip()
+ bot.msg(self.chan, line)
+
+ # default __str__() and __repr__() methods are defined by lib.Socketlike
def gotParent(parent):
for bindto, channel in parent.cfg.items('sockets'):
- @lib.bind(bindto, data=channel)
- class BasicServer(object):
- def __init__(self, sock, data):
- # NB neither directly referencing `channel`, nor trying to pass it through a default-arg-to-a-lambda like the python docs suggest, works here.
- # Yay python. At least passing it via bind works.
- self.chan = data
- self.buffer = b''
- self.sock = sock
-
- def getdata(self):
- recvd = self.sock.recv(8192)
- if recvd == b"": # EOF
- if len(self.buffer) != 0:
- # Process what's left in the buffer. We'll get called again after.
- remaining_buf = self.buffer.decode('utf-8', 'backslashreplace')
- self.buffer = b""
- return [remaining_buf]
- else:
- # Nothing left in the buffer. Return None to signal the core to close this socket.
- return None
- self.buffer += recvd
- lines = []
-
- while b"\n" in self.buffer:
- pieces = self.buffer.split(b"\n", 1)
- s = pieces[0].decode('utf-8', 'backslashreplace').rstrip("\r")
- lines.append(pieces[0].decode('utf-8', 'backslashreplace'))
- self.buffer = pieces[1]
-
- return lines
-
- def parse(self, line):
- try:
- bot = lib.parent.channel(self.chan).bot
- except AttributeError: # <class 'AttributeError'> 'NoneType' object has no attribute 'bot'
- bot = lib.parent.randbot()
- maxlen = bot.maxmsglen() - len("PRIVMSG :") - len(self.chan)
- while len(line) > maxlen:
- cutat = line.rfind(' ', 0, maxlen)
- if cutat == -1:
- cutat = maxlen
- bot.msg(self.chan, line[0:cutat])
- line = line[cutat:].strip()
- bot.msg(self.chan, line)
-
- def send(self, line):
- if lib.parent.parent.cfg.getboolean('debug', 'io'):
- lib.parent.log(str(self), 'O', line)
- self.sock.sendall(line.encode('utf-8', 'backslashreplace')+b"\r\n")
-
- def _getsockerr(self):
- try: # SO_ERROR might not exist on all platforms
- return self.socket.getsockopt(socket.SOL_SOCKET, socket.SO_ERROR)
- except:
- return None
-
- def __str__(self):
- return '%s#%d' % (__name__, self.sock.fileno())
- def __repr__(self):
- return '<%s #%d %s:%d>' % ((__name__, self.sock.fileno())+self.sock.getpeername())
+ lib.bind(bindto, data=channel)(BasicServer)