Add Teamspeak 3 Py3 compatibility (#705)

Replace sockets with telnetlib
Provides Python 2 and 3 compatibility
This commit is contained in:
Basraah 2017-02-12 13:05:18 +10:00 committed by Adarnof
parent 914c204a40
commit d7291f83c3

View File

@ -1,5 +1,5 @@
from __future__ import unicode_literals from __future__ import unicode_literals
import socket import telnetlib
import logging import logging
@ -23,37 +23,35 @@ ts3_escape = {'/': r"\/",
"\t": r'\t', "\t": r'\t',
"\v": r'\v'} "\v": r'\v'}
class TS3Proto: class TS3Proto:
bytesin = 0 bytesin = 0
bytesout = 0 bytesout = 0
_connected = False EOL = b'\n\r'
def __init__(self): def __init__(self):
self._log = logging.getLogger('%s.%s' % (__name__, self.__class__.__name__)) self._log = logging.getLogger('%s.%s' % (__name__, self.__class__.__name__))
pass self._conn = None
self._connected = False
def connect(self, ip, port): def connect(self, ip, port):
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try: try:
s.connect((ip, port)) self._conn = telnetlib.Telnet(host=ip, port=port)
self._connected = True
except: except:
# raise ConnectionError(ip, port) # raise ConnectionError(ip, port)
raise raise
else:
self._sock = s
self._sockfile = s.makefile('r', 0)
data = self._sockfile.readline() data = self._conn.read_until(self.EOL)
if data.strip() == "TS3": if data.strip() == "TS3":
self._sockfile.readline() self._conn.read_very_eager() # Clear buffer
self._connected = True self._connected = True
return True return True
def disconnect(self): def disconnect(self):
self.send_command("quit") self.send_command("quit")
self._sock.close() self._conn.close()
self._sock = None
self._connected = False self._connected = False
self._log.info('Disconnected') self._log.info('Disconnected')
@ -63,13 +61,22 @@ class TS3Proto:
data = [] data = []
max_loop = 10000
while True: while True:
resp = self._sockfile.readline() resp = self._conn.read_until(self.EOL)
resp = self.parse_command(resp) resp = self.parse_command(resp.decode('utf-8'))
if 'command' not in resp: if 'command' in resp:
data.append(resp)
else:
break break
else:
data.append(resp)
max_loop -= 1
# Prevent infinite loops
if max_loop <= 0:
self._log.error("Maximum loop counter reached, aborting to prevent infinite loop.")
break
# Clear read buffer of any stray bytes
self._conn.read_very_eager()
if resp['command'] == 'error': if resp['command'] == 'error':
if resp['keys']['id'] == '0': if resp['keys']['id'] == '0':
@ -97,7 +104,7 @@ class TS3Proto:
cstr = [command] cstr = [command]
# Add the keys and values, escape as needed # Add the keys and values, escape as needed
if keys: if keys:
for key in keys: for key in keys:
if isinstance(keys[key], list): if isinstance(keys[key], list):
@ -137,7 +144,7 @@ class TS3Proto:
v = key.strip().split('=') v = key.strip().split('=')
if len(v) > 1: if len(v) > 1:
# Key # Key
if len > 2: if len(v) > 2:
# Fix the stupidities in TS3 escaping # Fix the stupidities in TS3 escaping
v = [v[0], '='.join(v[1:])] v = [v[0], '='.join(v[1:])]
key, value = v key, value = v
@ -187,11 +194,11 @@ class TS3Proto:
def send(self, payload): def send(self, payload):
if self._connected: if self._connected:
self._log.debug('Sent: %s' % payload) self._log.debug('Sent: %s' % payload)
self._sockfile.write(payload) self._conn.write(payload.encode('utf-8'))
class TS3Server(TS3Proto): class TS3Server(TS3Proto):
def __init__(self, ip, port, id=0, sock=None): def __init__(self, ip, port, id=0):
""" """
Abstraction class for TS3 Servers Abstraction class for TS3 Servers
@param ip: IP Address @param ip: IP Address
@ -201,13 +208,7 @@ class TS3Server(TS3Proto):
""" """
TS3Proto.__init__(self) TS3Proto.__init__(self)
if not sock: self.connect(ip, port)
if self.connect(ip, port) and id > 0:
self.use(id)
else:
self._sock = sock
self._sockfile = sock.makefile('r', 0)
self._connected = True
def login(self, username, password): def login(self, username, password):
""" """