- Saved searches
- Use saved searches to filter your results more quickly
- bot.send_message() raises TimedOut exception for some messages over quota, but still delivers them #1045
- bot.send_message() raises TimedOut exception for some messages over quota, but still delivers them #1045
- Comments
- Steps to reproduce
- Expected behaviour
- Actual behaviour
- Configuration
- ConversationHandler¶
- ApplicationBuilder¶
Saved searches
Use saved searches to filter your results more quickly
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session. You switched accounts on another tab or window. Reload to refresh your session.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
bot.send_message() raises TimedOut exception for some messages over quota, but still delivers them #1045
bot.send_message() raises TimedOut exception for some messages over quota, but still delivers them #1045
Comments
Steps to reproduce
import time from telegram import Bot from telegram.error import RetryAfter, TimedOut def telegram_send(message): tries = 0 max_tries = 10 retry_delay = 10 while tries max_tries: try: _telegram_send( 'Test message <>, Retries <>'.format( message, tries ) ) except (RetryAfter, TimedOut) as e: print("Message <> got exception <>".format(message, e)) time.sleep(retry_delay) tries += 1 else: break def _telegram_send(message): chat_id = "put your chat id here" bot = Bot(token="put your token here") bot.send_message(chat_id=chat_id, text=message) for n in range(30): telegram_send(str(n))
Expected behaviour
Each message delivered exactly once, or not delivered (if the exceptions listed are not enough to handle all cases)
Actual behaviour
All messages delivered. Message 20 is delivered 3 times:
Bot [15.03.18 00:18] Test message 20, Retries 0 Bot [15.03.18 00:18] Test message 20, Retries 1 Bot [15.03.18 00:19] Test message 20, Retries 2
In [2]: for n in range(30): . telegram_send(str(n)) . Message 20 got exception Timed out Message 20 got exception Timed out
So what we have is first 2 deliveries are «timedout» duplicates and the third delivery is the normal one.
Configuration
Operating System:
Some old Ubuntu («trusty»)
Version of Python, python-telegram-bot & dependencies:
$ python -m telegram python-telegram-bot 10.0.1 certifi 2018.01.18 future 0.16.0 Python 3.6.0 (default, Oct 19 2017, 13:41:42) [GCC 4.8.4]
The text was updated successfully, but these errors were encountered:
ConversationHandler¶
class telegram.ext. ConversationHandler ( entry_points , states , fallbacks , allow_reentry = False , per_chat = True , per_user = True , per_message = False , conversation_timeout = None , name = None , persistent = False , map_to_parent = None , block = True ) [source] ¶ Bases: telegram.ext.BaseHandler A handler to hold a conversation with a single or multiple users through Telegram updates by managing three collections of other handlers.
Warning ConversationHandler heavily relies on incoming updates being processed one by one. When using this handler, telegram.ext.ApplicationBuilder.concurrent_updates should be set to False .
Note ConversationHandler will only accept updates that are (subclass-)instances of telegram.Update . This is, because depending on the per_user and per_chat , ConversationHandler relies on telegram.Update.effective_user and/or telegram.Update.effective_chat in order to determine which conversation an update should belong to. For per_message=True , ConversationHandler uses update.callback_query.message.message_id when per_chat=True and update.callback_query.inline_message_id when per_chat=False . For a more detailed explanation, please see our FAQ. Finally, ConversationHandler , does not handle (edited) channel posts.
The first collection, a list named entry_points , is used to initiate the conversation, for example with a telegram.ext.CommandHandler or telegram.ext.MessageHandler . The second collection, a dict named states , contains the different conversation steps and one or more associated handlers that should be used if the user sends a message when the conversation with them is currently in that state. Here you can also define a state for TIMEOUT to define the behavior when conversation_timeout is exceeded, and a state for WAITING to define behavior when a new update is received while the previous block=False handler is not finished. The third collection, a list named fallbacks , is used if the user is currently in a conversation but the state has either no associated handler or the handler that is associated to the state is inappropriate for the update, for example if the update contains a command, but a regular text message is expected. You could use this for a /cancel command or to let the user know their message was not recognized. 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. If an entry point callback function returns None , the conversation ends immediately after the execution of this callback function. To end the conversation, the callback function must return END or -1 . To handle the conversation timeout, use handler TIMEOUT or -2 . Finally, telegram.ext.ApplicationHandlerStop can be used in conversations as described in its documentation.
Note In each of the described collections of handlers, a handler may in turn be a ConversationHandler . In that case, the child ConversationHandler should have the attribute map_to_parent which allows returning to the parent conversation at specified states within the child conversation. Note that the keys in map_to_parent must not appear as keys in states attribute or else the latter will be ignored. You may map END to one of the parents states to continue the parent conversation after the child conversation has ended or even map a state to END to end the parent conversation from within the child conversation. For an example on nested ConversationHandler s, see nestedconversationbot.py .
- entry_points (List[ telegram.ext.BaseHandler ]) – A list of BaseHandler objects that can trigger the start of the conversation. The first handler whose check_update() method returns True will be used. If all return False , the update is not handled.
- states (Dict[ object , List[ telegram.ext.BaseHandler ]]) – A dict that defines the different states of conversation a user can be in and one or more associated BaseHandler objects that should be used in that state. The first handler whose check_update() method returns True will be used.
- fallbacks (List[ telegram.ext.BaseHandler ]) – A list of handlers that might be used if the user is in a conversation, but every handler for their current state returned False on check_update() . The first handler which check_update() method returns True will be used. If all return False , the update is not handled.
- allow_reentry ( bool , optional) – If set to True , a user that is currently in a conversation can restart the conversation by triggering one of the entry points. Default is False .
- per_chat ( bool , optional) – If the conversation key should contain the Chat’s ID. Default is True .
- per_user ( bool , optional) – If the conversation key should contain the User’s ID. Default is True .
- per_message ( bool , optional) – If the conversation key should contain the Message’s ID. Default is False .
- conversation_timeout ( float | datetime.timedelta , optional) – When this handler is inactive more than this timeout (in seconds), it will be automatically ended. If this value is 0 or None (default), there will be no timeout. The last received update and the corresponding context will be handled by ALL the handler’s whose check_update() method returns True that are in the state ConversationHandler.TIMEOUT .
- This feature relies on the telegram.ext.Application.job_queue being set and hence requires that the dependencies that telegram.ext.JobQueue relies on are installed.
- Using conversation_timeout with nested conversations is currently not supported. You can still try to use it, but it will likely behave differently from what you expect.
Changed in version 20.0: No longer overrides the handlers settings. Resolution order was changed.
ApplicationBuilder¶
class telegram.ext. ApplicationBuilder [source] ¶ This class serves as initializer for telegram.ext.Application via the so called builder pattern. To build a telegram.ext.Application , one first initializes an instance of this class. Arguments for the telegram.ext.Application to build are then added by subsequently calling the methods of the builder. Finally, the telegram.ext.Application is built by calling build() . In the simplest case this can look like the following example.
application = ApplicationBuilder().token("TOKEN").build()
Please see the description of the individual methods for information on which arguments can be set and what the defaults are when not called. When no default is mentioned, the argument will not be used by default.
- Some arguments are mutually exclusive. E.g. after calling token() , you can’t set a custom bot with bot() and vice versa.
- Unless a custom telegram.Bot instance is set via bot() , build() will use telegram.ext.ExtBot for the bot.
Sets a custom subclass instead of telegram.ext.Application . The subclass’s __init__ should look like this
def __init__(self, custom_arg_1, custom_arg_2, . , **kwargs): super().__init__(**kwargs) self.custom_arg_1 = custom_arg_1 self.custom_arg_2 = custom_arg_2
- application_class ( type ) – A subclass of telegram.ext.Application
- kwargs (Dict[ str , object ], optional) – Keyword arguments for the initialization. Defaults to an empty dict.
The same builder with the updated argument.
Specifies whether telegram.ext.Application.bot should allow arbitrary objects as callback data for telegram.InlineKeyboardButton and how many keyboards should be cached in memory. If not called, only strings can be used as callback data and no data will be stored in memory.
If you want to use this feature, you must install PTB with the optional requirement callback-data , i.e.
pip install python-telegram-bot[callback-data]
arbitrary_callback_data ( bool | int ) – If True is passed, the default cache size of 1024 will be used. Pass an integer to specify a different cache size.
The same builder with the updated argument.
Sets the base file URL for telegram.ext.Application.bot . If not called, will default to ‘https://api.telegram.org/file/bot’ .
The same builder with the updated argument.
Sets the base URL for telegram.ext.Application.bot . If not called, will default to ‘https://api.telegram.org/bot’ .
The same builder with the updated argument.
Sets a telegram.Bot instance for telegram.ext.Application.bot . Instances of subclasses like telegram.ext.ExtBot are also valid.
The same builder with the updated argument.
Builds a telegram.ext.Application with the provided arguments.
Specifies if and how many updates may be processed concurrently instead of one by one. If not called, updates will be processed one by one.
Processing updates concurrently is not recommended when stateful handlers like telegram.ext.ConversationHandler are used. Only use this if you are sure that your bot does not (explicitly or implicitly) rely on updates being processed sequentially.
When making requests to the Bot API in an asynchronous fashion (e.g. via block=False , Application.create_task , concurrent_updates() or the JobQueue ), it can happen that more requests are being made in parallel than there are connections in the pool. If the number of requests is much higher than the number of connections, even setting pool_timeout() to a larger value may not always be enough to prevent pool timeouts. You should therefore set concurrent_updates() , connection_pool_size() and pool_timeout() to values that make sense for your setup.
concurrent_updates ( bool | int ) – Passing True will allow for 256 updates to be processed concurrently. Pass an integer to specify a different number of updates that may be processed concurrently.
The same builder with the updated argument.
Sets the connection attempt timeout for the connect_timeout parameter of telegram.Bot.request . Defaults to 5.0 .
The same builder with the updated argument.
Sets the size of the connection pool for the connection_pool_size parameter of telegram.Bot.request . Defaults to 256 .
When making requests to the Bot API in an asynchronous fashion (e.g. via block=False , Application.create_task , concurrent_updates() or the JobQueue ), it can happen that more requests are being made in parallel than there are connections in the pool. If the number of requests is much higher than the number of connections, even setting pool_timeout() to a larger value may not always be enough to prevent pool timeouts. You should therefore set concurrent_updates() , connection_pool_size() and pool_timeout() to values that make sense for your setup.
The same builder with the updated argument.