我正在尝试连接到一个TeamSpeak服务器,使用QueryServer来创建一个bot。我已经听取了this thread的建议,但是我仍然需要帮助。在
这是我正在使用的The TeamSpeak API。在
在编辑之前,这是我的脚本中实际发生的事情的摘要(1个连接):
我怎么才能让它不断开呢?如何使脚本保持在“等待”状态,以便在执行命令后继续读取?在
我使用的是python3.4.1
我试着学习线程,但要么我很笨,要么它没有我想象的那样工作。还有一个“bug”,一旦等待事件发生,如果我没有用命令触发任何东西,它会在60秒后断开。在
#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()
在使用2个bot之前,我测试了在SendTextToChannel连接并且工作正常时启动它,允许我在它将文本发送到频道后执行任何我想做的事情。使整个python代码停止的bug只有在由manejadorDeEventos触发时才会发生
编辑1-试验线程。
我在线程方面把它搞砸了,结果是两个客户机同时连接。不知怎么的,我觉得他们中的一个在读事件,另一个在回答。脚本不再自动关闭,这是一个胜利,但是有一个克隆连接看起来不太好。在
编辑2-更新的代码和问题的实际状态。
我设法使双重连接工作或多或少“好”,但它断开,如果在房间里什么事都没有发生60秒。尝试使用线程.计时器但我无法让它发挥作用。整个问题代码已经更新。在
我想要一个答案,帮助我既从频道阅读,又回答它,而不需要为它连接第二个机器人(就像它实际上在做…),我会给额外的分数,如果答案也帮助我理解一个简单的方法,每50秒向服务器查询一次,这样它就不会断开连接。在
从the source来看,
recv_in_thread
直到退出时才创建一个围绕接收消息循环的线程,它创建了一个接收单个消息然后退出的线程:这意味着您必须反复调用
recv_in_thread
,而不仅仅是调用一次。在我不确定从读取文档到的确切位置,但大概是在接收到的事件触发的任何回调的末尾;我想这就是您的
manejadorDeEventos
方法?(或者可能与servernotifyregister
方法有关?我不确定servernotifyregister
是干什么的,on_event
是干什么的…)这
manejadorDeEventos
带来了两个侧面:manejadorDeEventos
错误。每个方法都必须将self
作为第一个参数。当您传递一个绑定方法时,如self.manejadorDeEventos
,该绑定self
对象将作为第一个参数传递,在调用方传递的任何参数之前。(对于classmethod
s和staticmethod
s也有例外,但这些在这里不适用。)此外,在该方法中,您几乎可以肯定地访问self
,而不是一个全局变量Bot
,它恰好与self
是同一个对象。在manejadorDeEventos
实际上是recv_in_thread
的回调,那么这里有一个竞争条件:如果第一条消息在主线程完成on_event
分配之前到达,则recv_on_thread
将无法调用事件处理程序。(这正是一种百里挑一的bug,当您在部署或发布代码数月后发现它时,调试会非常痛苦。)因此,请颠倒这两行代码。在最后一件事:简单地看一下这个库的代码有点令人担忧。它看起来不像是一个真正知道自己在做什么的人写的。我在上面复制的方法只有3行代码,但它包含了一个无用的},更不用说,在接收到每个事件后让您调用此方法(并生成一个新线程)的整个设计都很奇怪,而且考虑到它没有得到真正的解释。如果这是您必须使用的服务的标准客户机库,那么您在这方面确实没有太多选择,但如果不是,我会考虑寻找另一个库。在
return None
和一个永远不会join
的泄漏{相关问题 更多 >
编程相关推荐