WinError 10053 in script with Python and PyTS3

1

I have made a small script with Python and the PyTS3 module to mutate from my client automatically to all users connected to a TeamSpeak3 server that has not been added to my friends list.

It connects to the client through an add-on called ClientQuery, which brings Team Speak by default. (ClientQuery: offers a local telnet interface on port 25639 to remotely control the TeamSpeak 3 client).

My code is:

import ts3
import os
import sqlite3

#apikey
apikey = open("API-Key.txt", "r").read()

def TS3_Muter():

    #import friendlist
    friendlist = []

    with sqlite3.connect("C:/Users/" + str(os.getenv("username")) + "/AppData/Roaming/TS3Client/settings.db") as database:
        cursor = database.cursor()
        cursor.execute("SELECT * FROM Contacts;")
        rows = cursor.fetchall()
        for row in rows:
            row = str(row)
            nickname = row[(row.find("Nickname=") + 9):row.find("\nFriend")]
            code = int(row[(row.find("\nFriend=") + 9): row.find("\nAutomute")])
            if code == 0:
                friendlist.append(nickname)

    #ts3
    with ts3.query.TS3ClientConnection("localhost") as connection:
        connection.exec_("auth", apikey=apikey)
        connection.exec_("use")
        for client in connection.exec_("clientlist"):
            if client["client_nickname"] not in friendlist:
                connection.exec_("clientmute", clid=client["clid"])
            else:
                connection.exec_("clientunmute", clid=client["clid"])
        connection.exec_("quit")


while 1:
        TS3_Muter()

The script itself works perfectly, but after the first 1-3 minutes of execution, it ends up crashing with the following message in the console:

ConnectionAbortedError: [WinError 10053] A connection established by the software on your host computer has been aborted [Finished in 77.165s]

I have tried to run it by previously disabling the firewall, but the problem persists.

Would anyone know why this error is leaking, or how to fix it? Thank you very much in advance.

    
asked by psy 13.03.2018 в 16:04
source

1 answer

0

The error does not depend on your python script. It is the general error that appears when you try to write to a socket that has been closed from the other side.

It could be because there is a long-term connection with the TS3 client, which the client decides to close at a certain time, but it does not seem to be the case in your code. If I'm not mistaken, the function TS3_Muter() , within its second block with , establishes a connection with the client, authenticates, obtains the list of clients, executes a "mute" or "unmute" on each one of them , and then quit with the "quit" command. In addition, when leaving the block with , the socket that was connected will be automatically closed, so it does not seem to keep a connection open long time.

I suspect rather that it may be a client's own protection against what it takes as a DoS attack , since your main program simply calls TS3_Muter() in an infinite loop without giving it a break .

Add a time.sleep(1) for example in the main loop, which spans the requests 1 second. Not only will you give the client a break, but also your CPU, since having a infinite loop of polling without breaks is not highly recommended.

On the other hand, unless the database of friends is changing very frequently, you could optimize the access to it, making for example the database to be consulted only once every N access to the TS3 client. For example, with N = 60 the database would be consulted once per minute (assuming you space the calls to the client 1 second as recommended earlier).

Alternative implementation

Here I show you another way to implement it:

  • Use a single connection and recycle it
  • Does not saturate the client, spacing the commands 1 second
  • Only check the database of friends every minute

It's this:

import ts3
import os
import sqlite3

#apikey
apikey = open("API-Key.txt", "r").read()

def get_friendlist():
    #import friendlist
    friendlist = []

    with sqlite3.connect("C:/Users/" + str(os.getenv("username")) + "/AppData/Roaming/TS3Client/settings.db") as database:
        cursor = database.cursor()
        cursor.execute("SELECT * FROM Contacts;")
        rows = cursor.fetchall()
        for row in rows:
            row = str(row)
            nickname = row[(row.find("Nickname=") + 9):row.find("\nFriend")]
            code = int(row[(row.find("\nFriend=") + 9): row.find("\nAutomute")])
            if code == 0:
                friendlist.append(nickname)

def mute_not_friends(connection, friendlist):
    for client in connection.exec_("clientlist"):
        if client["client_nickname"] not in friendlist:
            connection.exec_("clientmute", clid=client["clid"])
        else:
            connection.exec_("clientunmute", clid=client["clid"])

def TS3_Muter():
    counter = 0
    N = 60
    with ts3.query.TS3ClientConnection("localhost") as connection:
        connection.exec_("auth", apikey=apikey)
        connection.exec_("use")
        while True:                            # Infinite loop
            if counter % N == 0:
                friendlist = get_friendlist()
            mute_not_friends(connection, friendlist)
            time.sleep(1)
            counter += 1

TS3_Muter()

Disclaimer :-) I have not been able to test the previous code because I do not have the rest of the software. In particular, I have doubts about whether the command "" use "" sent to the client is enough to do it once, as is the case in my code.

    
answered by 13.03.2018 / 16:31
source