How current state is managed in ConversationHandler in python-telegram-api

Viewed 5188

I want to use a ConversationHandler in my bot. At least, it would need three parameters:

class telegram.ext.ConversationHandler(entry_points, states, fallbacks)

AFAIK, entry points are triggers for the conversation handler, then each state may execute its own handlers, and based on fallbacks definition, if all handlers from a state return false, then fallback is triggered.

Ok, therefore, handlers return something. But a handler is an object, an instance of a class.

Based on this example, looking for example to the new_alarm_handler.

So my doubts

  1. How is it, that handlers return a value? (They appear to return their callback function result).

  2. Where is the current state of the conversation? It appears to not be accessible, but to be the last result of the last handler executed. Is it it? If not, then what do I have to do to change the current state in the conversation?

  3. Therefore, when a state is reached, their list of handlers (value in the dictionary states passed as arg) is executed. But being a list, it could be more than one, so there could be more than one returned state. How is it managed?

1 Answers

ConversationHandler stores the current state of the conversation in a dict, called conversations, and the key is an entity called conversation_key. It is a tuple, that consists of Chat's ID, User's ID and Message's ID (Some of which may be missing, this is defined by per_chat, per_user and per_message bool attributes).

Here conversations is accessed to get state in check_update method (explained further):
https://github.com/python-telegram-bot/python-telegram-bot/blob/2cde878d1e5e0bb552aaf41d5ab5df695ec4addb/telegram/ext/conversationhandler.py#L248
The state of the conversation is not intended to be accessible manually.

When user sends a message to the bot, Updater receives Update objects from Telegram and delivers them to its Dispatcher. Dispatcher has a list of registered Handler objects, their check_update methods are called in order in which they were added. check_update either returns False or None if the update should not be handled, or it returns some object that is then passed to handle_update method.

ConversationHandler inherits from Handler itself and it has other Handler objects as values in its states dict. It also has check_update and handle_update overwritten. Its check_update gets its current conversation state (see link above) and calls the check_update methods of all the handlers for that state. If all of them return False it does the same for handlers in fallbacks list. If all their check also return False it does nothing.

If one of the handlers should handle the event, the object its check_update returns is passed to ConversationHadler's handle_update method. It calls the fired Handler's handle_update method, which in turn calls the callback function, defined on its creation. Its result is set to be the new state of this conversation in the conversations dict.

According to the ConversationHandler docstring:

To change the state of conversation, the callback function of a handler must return the new state after responding to the user. If it does not return anything (returning ``None`` by default), the state will not change.

Related