def _parse_property(self, prop): """ >>> parse_property(b'key=value') ('key', 'value') >>> parse_property(b'foo') ('foo', '') >>> parse_property(b'client_unique_identifier=gZ7K[...]GIik=') ('client_unique_identifier', 'gZ7K[...]GIik=') """ prop = prop.split(b"=") if len(prop) == 1: key = prop[0] val = bytes() elif len(prop) == 2: key, val = prop else: key = prop[0] val = b"=".join(prop[1:]) try: key = key.decode() val = val.decode() except UnicodeDecodeError as err: # Todo: - Should we simply ignore decode errors? # - Is decoding reasonable? raise TS3ParserError(self, err) key = TS3Escape.unescape(key) val = TS3Escape.unescape(val) return (key, val)
def send(self, command, common_parameters=None, unique_parameters=None, options=None, timeout=None): """ The general structure of a query command is:: <command> <options> <common parameters> <unique parameters>|<unique parameters>|... Examples are here worth a thousand words: >>> # clientaddperm cldbid=16 permid=17276 permvalue=50 permskip=1|permid=21415 permvalue=20 permskip=0 >>> ts3conn.send( ... command = "clientaddperm", ... common_paramters = {"cldbid": 16}, ... parameterlist = [ ... {"permid": 17276, "permvalue": 50, "permskip": 1}, ... {"permid": 21415, "permvalue": 20, "permskip": 0} ... ] ... ) >>> # clientlist -uid -away >>> ts3conn.send( ... command = "clientlist", ... options = ["uid", "away"] ... ) .. seealso:: :meth:`recv`, :meth:`wait_for_resp` """ # Escape the command and build the final query command string. if not isinstance(command, str): raise TypeError("*command* has to be a string.") command = command common_parameters = TS3Escape.escape_parameters(common_parameters) unique_parameters = TS3Escape.escape_parameterlist(unique_parameters) options = TS3Escape.escape_options(options) query_command = command\ + " " + common_parameters\ + " " + unique_parameters\ + " " + options \ + "\n\r" query_command = query_command.encode() # Send the command. with self._send_lock: self._telnet_conn.write(query_command) # To identify the response when we receive it. self._query_counter += 1 query_id = self._query_counter # Make sure, that we receive the command if we are not in # threading mode. try: self.recv() except RuntimeError: pass return self.wait_for_resp(query_id, timeout)
def _parse_property(self, prop): """ >>> parse_property(b'key=value') ('key', 'value') >>> parse_property(b'foo') ('foo', '') >>> parse_property(b'client_unique_identifier=gZ7K[...]GIik=') ('client_unique_identifier', 'gZ7K[...]GIik=') """ prop = prop.split(b"=") if len(prop) == 1: key = prop[0] val = bytes() elif len(prop) == 2: key, val = prop else: key = prop[0] val = b"=".join(prop[1:]) # Take a look at https://github.com/benediktschmitt/py-ts3/issues/34 # to find out, why we simply ignore the decode errors. try: key = key.decode() except UnicodeDecodeError as err: LOG.warning("Failed to decode the key part properly: '%s'.", err) key = key.decode(errors="ignore") try: val = val.decode() except UnicodeDecodeError as err: LOG.warning("Failed to decode the value part properly: '%s'.", err) val = val.decode(errors="ignore") key = TS3Escape.unescape(key) val = TS3Escape.unescape(val) return (key, val)