2014-10-21 2 views
2

Я пытаюсь подключиться к серверу TeamSpeak, используя QueryServer, чтобы сделать бота. Я принял совет от this thread, однако мне все еще нужна помощь.скрипт Python 3 (Bot) перестает работать

Это The TeamSpeak API, которые я использую.

Перед правок, это было резюме того, что произошло на самом деле в моем сценарии (1 соединение):

  1. Он соединяет.
  2. Он проверяет идентификатор канала (и собственный идентификатор клиента)
  3. Она соединяет канал и начинает читать все
  4. Если кто-то говорит один специальная команда, она выполняет команду, а затем он отключается.

Как я могу это сделать, чтобы он не отключился? Как заставить скрипт оставаться в состоянии ожидания, чтобы он продолжал читать после выполнения команды?

Я пользуюсь Python 3.4.1.
Я пробовал изучать Threading, но либо я немой, либо не работает так, как я думал. Есть еще одна «ошибка», после ожидания событий, если я ничего не запускаю с помощью команды, она отключается через 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 бот, я проверил, чтобы запустить SendTextToChannel, когда он подключается и работает отлично, что позволяет мне делать то, что я хочу после того, как он отправляет текст в канал. Ошибка, из-за которой весь код python останавливается, происходит только в том случае, если она запускается с помощью manejadorDeEventos

Редактирование 1 - Экспериментирование с нарезкой.
Я перепутал это с большим количеством времени с потоками, получая результат, когда 2 клиента соединяются в одно и то же время. Как-то я думаю, что 1 из них читает события, а другой отвечает. Скрипт больше не закрывается, и это победа, но наличие клон-соединения выглядит не очень хорошо.

Редактировать 2 - Обновлен код и фактическое состояние проблемы.
Мне удалось сделать двойное соединение более или менее «прекрасным», но оно отключается, если в комнате не происходит ничего в течение 60 секунд. Пробовал использовать Threading.timer, но я не могу заставить его работать. Для него был обновлен весь код вопроса.

Я хотел бы получить ответ, который поможет мне как читать по каналу, так и отвечать на него без необходимости подключения к нему второго бота (например, на самом деле это делает ...) И я бы дал дополнительные баллы, если ответ также помогает мне понять простой способ сделать запрос на сервер каждые 50 секунд, чтобы он не отключился.

+0

@Parker: Это обновленный код с новой проблемой, а не дубликат. Тем не менее, OP: стоит попытаться выяснить, как сделать это более ясным, потому что у многих людей будет такая немедленная реакция. Я точно не знаю, как это сделать, особенно когда английский не является вашим первым языком ... возможно, в FAQ есть некоторые рекомендации? – abarnert

+0

Для дальнейшего использования OP это действительно стоит закодировать такие вещи в локальном репозитории git или, по крайней мере, просто делать резервные копии исходных файлов, прежде чем вы внесете большие изменения в исходный код. Я сделал очень похожие ошибки, такие как этот, с проектами, и все они уходят с резервным копированием/управлением источниками. – phantom

ответ

1

Глядя на the source, recv_in_thread не создает поток, который петли вокруг не принимает сообщения до выхода времени, он создает поток, который принимает одно сообщение, а затем выходит:

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 

Это означает, что у вас есть многократно вызывать recv_in_thread, а не просто называть его один раз.

Я не уверен точно , где, чтобы сделать это, прочитав документы, но, по-видимому, это в конце любого обратного вызова, вызванного полученным событием; Я думаю, что это ваш метод manejadorDeEventos? (? Или, может быть, это то, что связано с методом servernotifyregister я не уверен, что servernotifyregister для и что on_event для ...)


Это manejadorDeEventos воспитывает двух боковых точек:

  • You» объявлено manejadorDeEventos неправильно. В качестве первого параметра каждый метод должен принимать self. Когда вы передаете связанный метод, например self.manejadorDeEventos, связанный объект self будет передан в качестве первого аргумента перед любыми аргументами, которые передает вызывающий. (Есть исключения из этого для classmethod и staticmethod s, но они здесь не применяются.) Кроме того, в рамках этого метода вы почти наверняка получите доступ к self, а не глобальную переменную Bot, которая оказывается тем же объектом, что и self ,
  • Если manejadorDeEventos на самом деле является обратным вызовом для recv_in_thread, у вас есть условие гонки: если первое сообщение приходит до того, как ваши основные потоки завершат назначение on_event, recv_on_thread не сможет вызвать ваш обработчик событий. (Это точно такая ошибка, которая часто появляется один раз в миллионе, что делает ее огромной болью для отладки, когда вы обнаруживаете ее через несколько месяцев после развертывания или публикации вашего кода.) Итак, измените эти две строки.

Одна последняя вещь: краткий проблеск на код этой библиотеки немного тревожно. Не похоже, что это написано кем-то, кто действительно знает, что они делают. Метод, который я скопировал выше, имеет только 3 строки кода, но включает в себя бесполезный return None и просочившийся Thread, который никогда не может быть join ed, не говоря уже о том, что вся конструкция, позволяющая вам вызвать этот метод (и создать новый поток) после каждое полученное событие является странным и тем более учитывая, что это не объяснено. Если это стандартная клиентская библиотека для службы, которую вы должны использовать, то у вас действительно нет большого выбора в этом вопросе, но если это не так, я бы подумал о поиске другой библиотеки.

+0

Я не могу снова вызвать recv_in_thread, потому что это код python, который останавливается, а не данные, отправляемые на мой компьютер. Я как-то заставил его снова называть его, и ошибка «уже получает сообщения», как и ожидалось. Я не понимаю, почему весь код python останавливается в разделе SendTextToChannel, что даже функция печати перестает работать, например, если она не является частью скрипта. – Saelyth

+0

@Saelyth: Хорошо, это похоже на другую проблему. Все методы 'send *' блокируются, пока не получат ответ. Если нет проблем с тем, что ваш код начинает обрабатывать одно сообщение, прежде чем заканчивать предыдущий, есть простое исправление: просто вызовите 'recv_in_thread' перед вызовом' sendtextmessage' (или, лучше, перед отправкой на 'sendtextmessage'). Это вызовет новый поток, ожидающий следующего ответа.(В качестве альтернативы вы можете запустить свой собственный поток и повторно называть 'recv' несколько раз в цикле, поэтому вам не нужно продолжать пинать после каждого получения.) – abarnert

+0

Это не сработает, это произойдет, если я попробую : http://prntscr.com/4ypm0x Я также попытался запустить основной поток сам, и он вроде как работает, так как я мог запросить разные команды в чате Bot, и код python не закрылся сам. Тем не менее, я заметил, что он фактически регистрировал все, что я говорил, но не отправлял текст в чат. Так что это была другая проблема с моей реальной проблемой, она выполняла печать, но не линию над ней. Разочарование ... – Saelyth

Смежные вопросы