Python 3 (Bot) script stops working

I am trying to connect to a TeamSpeak server using QueryServer to make a bot. I got advice from this thread , however I still need help.

This is the TeamSpeak API that I use.

Before editing, this was a summary of what actually happened in my script (1 connection):

  • He is connecting.
  • It checks the channel identifier (and the client’s own identifier)
  • He joins the channel and begins to read everything
  • If someone speaks about a specific command, he executes the command and then disconnects.

How can I make it not disconnect? How can I make the script stand by so that it continues to read after the command is executed?

I am using Python 3.4.1 .
I tried to learn Threading, but either I'm dumb or it doesn't work the way I thought. There is another “error” when you expect events, if I do not start anything with the command, it turns off after 60 seconds.

#Librerias import ts3 import threading import datetime from random import choice, sample # Data needed # USER = "thisisafakename" PASS = "something" HOST = "111.111.111.111" PORT = 10011 SID = 1 class BotPrincipal: def __init__(self, manejador=False): self.ts3conn = ts3.query.TS3Connection(HOST, PORT) self.ts3conn.login(client_login_name=USER, client_login_password=PASS) self.ts3conn.use(sid=SID) channelToJoin = Bot.GettingChannelID("TestingBot") try: #Login with a client that is ok self.ts3conn.clientupdate(client_nickname="The Reader Bot") self.MyData = self.GettingMyData() self.MoveUserToChannel(ChannelToJoin, Bot.MyData["client_id"]) self.suscribirEvento("textchannel", ChannelToJoin) self.ts3conn.on_event = self.manejadorDeEventos self.ts3conn.recv_in_thread() except ts3.query.TS3QueryError: #Name already exists, 2nd client connect with this info self.ts3conn.clientupdate(client_nickname="The Writer Bot") self.MyData = self.GettingMyData() self.MoveUserToChannel(ChannelToJoin, Bot.MyData["client_id"]) def __del__(self): self.ts3conn.close() def GettingMyData(self): respuesta = self.ts3conn.whoami() return respuesta.parsed[0] def GettingChannelID(self, nombre): respuesta = self.ts3conn.channelfind(pattern=ts3.escape.TS3Escape.unescape(nombre)) return respuesta.parsed[0]["cid"] def MoveUserToChannel(self, idCanal, idUsuario, passCanal=None): self.ts3conn.clientmove(cid=idCanal, clid=idUsuario, cpw=passCanal) def suscribirEvento(self, tipoEvento, idCanal): self.ts3conn.servernotifyregister(event=tipoEvento, id_=idCanal) def SendTextToChannel(self, idCanal, mensajito="Error"): self.ts3conn.sendtextmessage(targetmode=2, target=idCanal, msg=mensajito) #This works print("test") #PROBLEM HERE This doesn't work. Why? the line above did work def manejadorDeEventos(sender, event): message = event.parsed[0]['msg'] if "test" in message: #This works Bot.SendTextToChannel(ChannelToJoin, "This is a test") #This works if __name__ == "__main__": Bot = BotPrincipal() threadprincipal = threading.Thread(target=Bot.__init__) threadprincipal.start() 

Before using 2 bots, I tested running SendTextToChannel when it connects and it works fine, which allows me to do whatever I want after it sends the text to the channel. The error that causes all python code to stop occurs only if it is called by the manejadorDeEventos function

Edit 1 - experiment with threads.
I confused this with a lot of time with threads, getting the result when 2 clients connect at the same time. Somehow I think that 1 of them reads events, and the other answers. the script no longer closes and that wins, but having a clone connection doesn't look very good.

Edit 2 - Updated code and actual status of the problem.
I managed to make the double connection more or less “perfect”, but it disconnects if nothing happens in the room for 60 seconds. Tried using Threading.timer, but I can't get it to work. All question code has been updated for him.

I need an answer that helps me do reading from the channel and answer it without the need to connect a second bot to it (for example, actually ...) And I would give extra points if the answer also helps me understand a simple way to do a request to the server every 50 seconds so that it does not disconnect.

+2
source share
1 answer

From looking at the source , recv_in_thread does not create a thread that moves around receiving messages before exiting the game, creates a thread that receives one message, and then exits:

 def recv_in_thread(self): """ Calls :meth:`recv` in a thread. This is useful, if you used ``servernotifyregister`` and you expect to receive events. """ thread = threading.Thread(target=self.recv, args=(True,)) thread.start() return None 

This means that you need to re-name recv_in_thread , rather than just calling it once.

I am not sure where exactly to do this by reading the documents, but presumably this is at the end of any called invocation of the invoked event; I think your method is manejadorDeEventos ? (Or maybe this has something to do with the servernotifyregister method? I'm not sure what servernotifyregister for and what on_event for ...)


That manejadorDeEventos calls two side points:

  • You have declared manejadorDeEventos incorrect. Each method should take self as its first parameter. When you pass a bound method, such as self.manejadorDeEventos , the bound self will be passed as the first argument before any arguments that the caller passes. (There are exceptions to this for classmethod and staticmethod s, but they do not apply here.) In addition, in this method you will almost certainly get access to self , and not to the global variable Bot , which will happen for the same object as self .
  • If manejadorDeEventos is actually a callback to recv_in_thread , you have a race condition: if the first message arrives before your main threads complete the on_event , recv_on_thread will not be able to call the event handler. (This is exactly the kind of error that often appears once in a million, which makes it a huge pain for debugging when you discover it a few months after deploying or publishing your code.) So, change these two lines.

Last: A brief overview of this library code is a bit troubling. It is not like he wrote someone who really knows what they are doing. The method that I copied above has only 3 lines of code, but includes a useless return None and a missed Thread , which can never be join ed, not to mention the whole construct allowing you to call this method (and create new thread) after each received event becomes strange, and especially considering that this is not explained. If this is the standard client library for the service that you should use, then you really do not have much choice in this matter, but if it is not, I would think about looking for another library.

+1
source

Source: https://habr.com/ru/post/1204940/


All Articles