-
Notifications
You must be signed in to change notification settings - Fork 0
Transition guide to Version 12.0
- Context based callbacks
- Handler changes
- Filters in handlers
- Persistence
- Return UTC from from_timestamp()
The biggest change in this release is context based callbacks. When running your bot you will probably see a warning like the following:
echobot2.py:62: TelegramDeprecationWarning: Old Handler API is deprecated - see https://git.io/fxJuV for details
This means you're using the old style callbacks and should upgrade to context based callbacks.
The first thing you should do is find where you create your Updater
.
updater = Updater('TOKEN')
And add use_context=True
so it looks like
updater = Updater('TOKEN', use_context=True)
Note that this is only necessary in version 12 of python-telegram-bot
. Version 13 will have use_context=True
set as default.
If you do not use Updater
but only Dispatcher
you should instead set use_context=True
when you create the Dispatcher
.
CallbackContext
is an object that contains all the extra context information regarding an Update
, error or Job
. It replaces the old behaviour with having a ton of pass_something=True
in your handlers. Instead, all this data is available directly on the CallbackContext
- always!
So what information is stored on a CallbackContext
? The parameters marked with a star will only be set on specific updates.
- bot
- job_queue
- update_queue
- chat_data*
- user_data*
- job*
- error*
- args*
- matches/match*
Now on to the bulk of the change. You wanna change all your callback functions from the following:
def start(bot, update, args, job_queue):
# Stuff here
to the new style using CallbackContext
def start(update: Update, context: CallbackContext):
# Stuff here
# args will be available as context.args
# jobqueue will be available as context.jobqueue
On python 2 which doesn't support annotations replace update: Update, context: CallbackContext
with simply update, context
.
Error handler callbacks are the ones added using Dispatcher.add_error_handler
. These have also been changed from the old form:
def error_callback(bot, update, error):
logger.warning('Update "%s" caused error "%s"', update, error)
into
def error_callback(update, context):
logger.warning('Update "%s" caused error "%s"', update, context.error)
Note that the error is now part of the CallbackContext
object.
Job callbacks (the ones that are passed to JobQueue.run_once
and similar) have also changed. Old form:
def job_callback(bot, job):
bot.send_message(SOMEONE, job.context)
New form:
def job_callback(context):
job = context.job
context.bot.send_message(SOMEONE, job.context)
Note that both bot, and job have been merged into the CallbackContext
object.
Before version 12, you could both pass_groups and pass_groupdict. Inside CallbackContext
this has been combined into a single Match
object. Therefore if your handler looked like this before:
def like_callback(bot, update, groups, groupdict): # Registered with a RegexHandler with pattern (?i)i (like|dislike) (?P<thing>.*)
update.reply_text('You {} {}'.format(groups[1], groupdict['thing'])
It would instead now look something like this:
def like_callback(update, context): # Registered with a RegexHandler with pattern (?i)i (like|dislike) (?P<thing>.*)
update.reply_text('You {} {}'.format(context.match[1], context.match.groupdict()['thing'])
Also see Special note about regex filters.
In version 13 of python-telegram-bot
, use_context
will default to True
. This means that your old handlers using pass_ will stop working. It also means that after upgrading to version 13, you can remove use_context=True
from your Updater
if you so desire.
This part is only relevant if you've developed custom handlers, that subclass telegram.ext.Handler
. To support the new context based callbacks, add a method called collect_additional_context
to your handler. The method receives a CallbackContext
object and whatever is return by check_update()
, and should add whatever extra context is needed (at least everything that could be added via pass_
arguments before). Note that job_queue, update_queue, chat_data, user_data
is automatically added by the base Handler
.
We made some changes to the behaviour of some handlers. Listed below are the changes notable to you and maybe requires some action in your code.
From now on CommandHandler
will only respond to valid bot commands. It will raise ValueError
when an invalid command is given as the command
argument. If you previously used commands not considered valid by @botfather, you can use the new PrefixHandler instead.
In addition allow_edited
is deprecated until V13, when it will be removed. The new default behavior is to accept both message
and edited_message
with a valid command. If you would like to exclude edited message from your CommandHandler pass filters=~Filters.update.edited_message
to the constructor.
Newly added is the PrefixHandler
. read the docs for more details on its use and implementation.
MessageHandler
received some upgrades to switch to the filter system. We've removed allow_edited
which has been deprecated for a while. Also we now deprecated message_updates
, channel_post_updates
and edited_updates
in the constructor. The defaults have also changed to accepting all updates by default. This includes (edited_)channel_posts and (edited_)messages. To tweak the message you receive with MessageHandler, please use the update filters.
RegexHandler
is being deprecated. It's basically a MessageHandler with a Filters.regex
, now the CallbackContext contains all match information. For now, we keep it in, but you should switch the use of RegexHandler
to using MessageHandler(Filters.regex('pattern'), callback)
.
See Special note about regex filters and Note about group and groupdict for more details.
The arguments run_async_timeout
and timed_out_behavior
have been removed.
The timeout for waiting for a @run_async handler is now always 0. If an update would have waited before, ConversationHandler will now try to use a handler in the new special state ConversationHandler.WAITING
. This allows you to either manually wait in the handler if you want the old functionality, or send a message back to the user like "I am still processing your last request, please wait".
Error handler got a major improvement. Instead of only handling TelegramErrors, every error from every handler will be passed to its callback.
You can use it for example to send yourself notifications if an error happened while your bot is running.
Note: If an error handler callback is successfully executed, the error itself won't be caught by the logger module. If you still want this, reraise the error at the end of your function.
Using a list of filters in a handler like below has been deprecated for a while now. Version 12 removes the ability completely.
MessageHandler([Filters.audio, Filters.video], your_callback)
Instead, you can now combine filters using bitwise operators like below. (The pipe ( |
) character means OR, so the below is equivalent to the above example using a list).
# Handle messages that contain EITHER audio or video
MessageHandler(Filters.audio | Filters.video, your_callback)
AND:
# Handle messages that are text AND contain a mention
Filters.text & Filters.entity(MesageEntity.MENTION)
NOT:
# Handle messages that are NOT commands (same as Filters.text in most cases)
~ Filters.command
More advanced combinations:
# Handle messages that are text and contain a link of some kind
Filters.text & (Filters.entity(URL) | Filters.entity(TEXT_LINK))
# Handle messages that are text but are not forwarded
Filters.text & (~ Filters.forwarded)
Regex filters can also be used in advanced combinations like so:
((Filters.regex('(test)') | Filters.command) & (Filters.regex('(it)') | Filters.forwarded))
This would make context.matches
equal a list of regex matches, but only if the regex filter actually executed. This means that:
- it will be a list with a single match for
test
if it's a command but not forwarded. - it will be a list with a single match for
it
if it's forwarded but not a command. - it will be a list of two matches. The first one will be
test
and the second oneit
. Note that in the last case, the order is the order that the filters were executed in, and not necessarily left to right.
Also note that context.match
is a shortcut for context.matches[0]
. Very useful when you are only interested in the first match.
As of version 12.4, Filters.command
checks for MessageEntity.BOT_COMMAND
instead of a leading slash and accordingld, Filters.text
accepts text with a leading slash. Use Filters.text & (~Filters.command)
to filter for text messages that have no commands. For more details, please see the changelog and the documentation on filters.
In version 12 we introduce persistence to the bot's mechanics. If you want to use this please read the wiki page dedicated to persistence.
from_timestamp() now returns UTC timestamps. The recommended way to work is to run your bot on a machine configured to UTC. This means that from now on. telegram.Message.date
will always be in UTC format.
- Wiki of
python-telegram-bot
© Copyright 2015-2025 – Licensed by Creative Commons
- Architecture Overview
- Builder Pattern for
Application
- Types of Handlers
- Working with Files and Media
- Exceptions, Warnings and Logging
- Concurrency in PTB
- Advanced Filters
- Storing data
- Making your bot persistent
- Adding Defaults
- Job Queue
- Arbitrary
callback_data
- Avoiding flood limits
- Webhooks
- Bot API Forward Compatiblity
- Frequently requested design patterns
- Code snippets
- Performance Optimizations
- Telegram Passport
- Bots built with PTB
- Automated Bot Tests