Skip to content

Transition guide to Version 12.0

Eldinnie edited this page Oct 8, 2018 · 19 revisions

Table of contents

Context based callbacks

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/vp113 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.

Handler callbacks

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

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

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.

What exactly is CallbackContext

CallbackContext is an object that contains all the extra context information regarding an update. It replaces the old behaviour with having a ton of pass_something=True in your handlers. Instead, all this data is availible directly on the CallbackContext - always!

Note about groups and groupdict

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'])

Note about version 12

In version 12 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 12, you can remove use_context=True from your Updater if you so desire.

Custom handlers

This part is only relavant 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.


Handler changes

We made some changes to the behavior of some handlers. Listed below are the changes notable to you and maybe requires some action in your code.

CommandHandler

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 V12, 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.

PrefixHandler

Newly added is the PrefixHandler. read the docs for more details on it's use and implementation.

MessageHandler

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 remain the same (not edited messages and channel_posts). To tweak the message you receive with MessageHandler, please use the update filters.

RegexHandler

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)


Filters in handlers

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)

Combine filters using bitwise operators

Instead you can now combine filters using bitwise operators like below. (The pipe ( | ) character means OR, so the below is equalivant to the above example using a list).

# Handle messages that contain EITHER audio or video
MessageHandler(Filters.audio | Filters.video, your_callback)

Also supports AND, NOT and more than 3 filters

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)
Clone this wiki locally