ConversationHandler: Fix wrong signature call for timeout handlers

Fixes #1652

Co-authored-by: Eldinnie <Eldinnie@users.noreply.github.com>
This commit is contained in:
tobiaswicker 2020-01-11 19:51:31 +01:00 committed by Noam Meltzer
parent a582515766
commit 940b42e048
2 changed files with 75 additions and 8 deletions

View file

@ -393,8 +393,10 @@ class ConversationHandler(Handler):
self.logger.debug('conversation timeout was triggered!') self.logger.debug('conversation timeout was triggered!')
# Backward compatibility with bots that do not use CallbackContext # Backward compatibility with bots that do not use CallbackContext
callback_context = None
if isinstance(context, CallbackContext): if isinstance(context, CallbackContext):
job = context.job job = context.job
callback_context = context
context = job.context context = job.context
@ -409,5 +411,5 @@ class ConversationHandler(Handler):
for handler in handlers: for handler in handlers:
check = handler.check_update(context.update) check = handler.check_update(context.update)
if check is not None and check is not False: if check is not None and check is not False:
handler.handle_update(context.update, context.dispatcher, check) handler.handle_update(context.update, context.dispatcher, check, callback_context)
self.update_state(self.END, context.conversation_key) self.update_state(self.END, context.conversation_key)

View file

@ -24,7 +24,7 @@ import pytest
from telegram import (CallbackQuery, Chat, ChosenInlineResult, InlineQuery, Message, from telegram import (CallbackQuery, Chat, ChosenInlineResult, InlineQuery, Message,
PreCheckoutQuery, ShippingQuery, Update, User, MessageEntity) PreCheckoutQuery, ShippingQuery, Update, User, MessageEntity)
from telegram.ext import (ConversationHandler, CommandHandler, CallbackQueryHandler, from telegram.ext import (ConversationHandler, CommandHandler, CallbackQueryHandler,
MessageHandler, Filters, InlineQueryHandler) MessageHandler, Filters, InlineQueryHandler, CallbackContext)
@pytest.fixture(scope='class') @pytest.fixture(scope='class')
@ -117,7 +117,10 @@ class TestConversationHandler(object):
# Actions # Actions
def start(self, bot, update): def start(self, bot, update):
if isinstance(update, Update):
return self._set_state(update, self.THIRSTY) return self._set_state(update, self.THIRSTY)
else:
return self._set_state(bot, self.THIRSTY)
def end(self, bot, update): def end(self, bot, update):
return self._set_state(update, self.END) return self._set_state(update, self.END)
@ -129,7 +132,10 @@ class TestConversationHandler(object):
return self._set_state(update, None) return self._set_state(update, None)
def brew(self, bot, update): def brew(self, bot, update):
if isinstance(update, Update):
return self._set_state(update, self.BREWING) return self._set_state(update, self.BREWING)
else:
return self._set_state(bot, self.BREWING)
def drink(self, bot, update): def drink(self, bot, update):
return self._set_state(update, self.DRINKING) return self._set_state(update, self.DRINKING)
@ -139,9 +145,20 @@ class TestConversationHandler(object):
def passout(self, bot, update): def passout(self, bot, update):
assert update.message.text == '/brew' assert update.message.text == '/brew'
assert isinstance(update, Update)
self.is_timeout = True self.is_timeout = True
def passout2(self, bot, update): def passout2(self, bot, update):
assert isinstance(update, Update)
self.is_timeout = True
def passout_context(self, update, context):
assert update.message.text == '/brew'
assert isinstance(context, CallbackContext)
self.is_timeout = True
def passout2_context(self, update, context):
assert isinstance(context, CallbackContext)
self.is_timeout = True self.is_timeout = True
# Drinking actions (nested) # Drinking actions (nested)
@ -613,6 +630,54 @@ class TestConversationHandler(object):
assert handler.conversations.get((self.group.id, user1.id)) is None assert handler.conversations.get((self.group.id, user1.id)) is None
assert not self.is_timeout assert not self.is_timeout
def test_conversation_handler_timeout_state_context(self, cdp, bot, user1):
states = self.states
states.update({ConversationHandler.TIMEOUT: [
CommandHandler('brew', self.passout_context),
MessageHandler(~Filters.regex('oding'), self.passout2_context)
]})
handler = ConversationHandler(entry_points=self.entry_points, states=states,
fallbacks=self.fallbacks, conversation_timeout=0.5)
cdp.add_handler(handler)
# CommandHandler timeout
message = Message(0, user1, None, self.group, text='/start',
entities=[MessageEntity(type=MessageEntity.BOT_COMMAND, offset=0,
length=len('/start'))],
bot=bot)
cdp.process_update(Update(update_id=0, message=message))
message.text = '/brew'
message.entities[0].length = len('/brew')
cdp.process_update(Update(update_id=0, message=message))
sleep(0.5)
cdp.job_queue.tick()
assert handler.conversations.get((self.group.id, user1.id)) is None
assert self.is_timeout
# MessageHandler timeout
self.is_timeout = False
message.text = '/start'
message.entities[0].length = len('/start')
cdp.process_update(Update(update_id=1, message=message))
sleep(0.5)
cdp.job_queue.tick()
assert handler.conversations.get((self.group.id, user1.id)) is None
assert self.is_timeout
# Timeout but no valid handler
self.is_timeout = False
cdp.process_update(Update(update_id=0, message=message))
message.text = '/brew'
message.entities[0].length = len('/brew')
cdp.process_update(Update(update_id=0, message=message))
message.text = '/startCoding'
message.entities[0].length = len('/startCoding')
cdp.process_update(Update(update_id=0, message=message))
sleep(0.5)
cdp.job_queue.tick()
assert handler.conversations.get((self.group.id, user1.id)) is None
assert not self.is_timeout
def test_conversation_timeout_cancel_conflict(self, dp, bot, user1): def test_conversation_timeout_cancel_conflict(self, dp, bot, user1):
# Start state machine, wait half the timeout, # Start state machine, wait half the timeout,
# then call a callback that takes more than the timeout # then call a callback that takes more than the timeout