telepot icon indicating copy to clipboard operation
telepot copied to clipboard

Pressing button does not trigger callback query: on_close() called due to IdleTerminate

Open tesserata opened this issue 8 years ago • 5 comments

Hello!

I've tried to write a bot that should react to button pressing with some further actions. Part of the code is omitted below, but the problem is that on_callback_query method of DocumentsHandler is never called. I also tried to put all this just in one ChatHandler - UserHandler, but the problem persists.

class DocumentHandler(CallbackQueryOriginHandler):
    def __init__(self, *args, **kwargs):
        super(DocumentHandler, self).__init__(*args, **kwargs)
        self._store = None

    def on_callback_query(self, msg):
        print('in on_callback_query')
        query_id, from_id, query_data = glance(msg, flavor='callback_query')
        print('Callback Query:', query_id, from_id, query_data)
        query_call = getattr(self, '_%s' % query_data)
        query_call()
        self.sender.answerCallbackQuery(query_id, text=query_data, alert=True)

class UserHandler(ChatHandler):
    def __init__(self, seed_tuple, **kwargs):
        super(UserHandler, self).__init__(seed_tuple, **kwargs)

    def on_chat_message(self, msg):
        content_type, chat_type, chat_id = glance(msg)

        if content_type != 'text':
            return

        command = msg['text']
        print('Command received: %s' % command)

        if command == '/start':
            content_type, chat_type, chat_id = glance(msg)
            self._store = Storage(chat_id)
            self.sender.sendMessage('Hi! Type a command to begin')
        elif command == '/docs':
            keyboard = InlineKeyboardMarkup(inline_keyboard=[
                       [InlineKeyboardButton(text='New document', callback_data='doc_new'),
                       InlineKeyboardButton(text='Add to document', callback_data='doc_add')],
                       [
                        InlineKeyboardButton(text='Delete document', callback_data='doc_del'),
                        InlineKeyboardButton(text='List documents', callback_data='doc_list')
                       ],
                   ])
            self.sender.sendMessage('Choose a command', reply_markup=keyboard)

bot = DelegatorBot(token,[
                    pave_event_space()(
                        per_chat_id(), create_open, UserHandler, timeout=10),
                     pave_event_space()(
                         per_callback_query_origin(), create_open, DocumentHandler, timeout=10)
                    ])

MessageLoop(bot).run_as_thread()
print('Listening ...')

This way I got only 'Listening...' in the output

Another way I tried was

class UserHandler(ChatHandler):
    def __init__(self, seed_tuple, **kwargs):
        super(UserHandler, self).__init__(seed_tuple, **kwargs)

    def on_chat_message(self, msg):
        content_type, chat_type, chat_id = glance(msg)
        if content_type != 'text':
            return

        command = msg['text']
        print('Command received: %s' % command)

        if command == '/start':
            content_type, chat_type, chat_id = glance(msg)
            self._store = Storage(chat_id)
            self.sender.sendMessage('Hi! Type a command to begin')
        elif command == '/docs':
            keyboard = InlineKeyboardMarkup(inline_keyboard=[
                       [InlineKeyboardButton(text='New document', callback_data='doc_new'),
                       InlineKeyboardButton(text='Add to document', callback_data='doc_add')],
                       [
                        InlineKeyboardButton(text='Delete document', callback_data='doc_del'),
                        InlineKeyboardButton(text='List documents', callback_data='doc_list')
                       ],
                   ])
            self.sender.sendMessage('Choose a command', reply_markup=keyboard)

    def on_callback_query(self, msg):
        print('in on_callback_query')
        query_id, from_id, query_data = glance(msg, flavor='callback_query')
        print('Callback Query:', query_id, from_id, query_data)
        query_call = getattr(self, '_%s' % query_data)
        query_call()
        self.sender.answerCallbackQuery(query_id, text=query_data, alert=True)

bot = DelegatorBot(token,[
                    pave_event_space()(
                        per_chat_id(), create_open, UserHandler, timeout=10)
                    ])

MessageLoop(bot).run_as_thread()
print('Listening ...')

The output was the following:

Listening ...
Command received: /docs
ERROR:root:on_close() called due to IdleTerminate: 10

Any help would be appreciated! Thanks.

tesserata avatar Oct 12 '17 14:10 tesserata

increase your timeout = 10 to something bigger.

TanShengRong avatar Oct 12 '17 16:10 TanShengRong

Well, then it just takes longer before IdleTerminate appears. The problem is that no callback is returned after push or the callback handler doesn't react to it (the input would contain the log otherwise)

tesserata avatar Oct 12 '17 18:10 tesserata

I think you forgot to put these lines at the end:

while 1:
    time.sleep(10)

Without them, the program's main thread will end right away, and the MessageLoop, which is run as a second thread, will evaporate. You need to keep the program alive for MessageLoop to keep working.

nickoala avatar Oct 14 '17 03:10 nickoala

Oh, I did not specify this in the question; I'm running my code in the IPython notebook for now, so the kernel doesn't die after executing the code and continues to listen. I've tried to add the cycle you mentioned, but it changes nothing.

The thing is that bot reacts to commands with a slash (like, /docs), but doesn't react to pressing a button in InlineKeyboardMarkup. So I suppose it has something to do with callback response.

tesserata avatar Oct 18 '17 10:10 tesserata

You will need to mention the 'callback_query' parameter in the MessageLoop. I think this should work:

MessageLoop(bot, {'chat': on_chat_message, 'callback_query': on_callback_query}).run_as_thread()

AditiChoksi avatar Mar 25 '18 16:03 AditiChoksi