Pyrogram v2.0#

Performance improvements, In-Memory Downloads, Media Streaming, Enumerations, Datetime objects and more#

This is a major release which brings lots of additions and changes. Read the following release notes to learn about what has changed. Down below the page you’ll also find a transition guide that helps you understand changes with code examples.

Notable changes & additions#

  • Message cache: Pyrogram’s performance has been greatly improved thanks to in-memory cached messages. Messages coming from live updates (new messages, edited messages, callback queries) are now being cached, thus improving the reactivity of the framework and speeding up message-related methods. This will be especially useful for high-traffic bots, in particular for those that are in lots of groups with a high amount of messages handled and for bots that deal with keyboards.

  • In-memory downloads: Support for in-memory media downloads has been added through the new in_memory parameter of download_media() and Message’s bound method download(). See methods documentation for examples on how to use them.

  • Media streaming: Pyrogram is now able to stream media messages (i.e.: download chunk by chunk) with the new method stream_media(). Pass a limit and an offset argument to control how many chunks to obtain one by one and from which chunk to start.

  • Introduction of enumerations: Enumerations are types that hold a group of related values to be used whenever a constant value is required. As opposed to writing hard-coded values which are prone to errors, enumerations will help you deal with those values in a type-safe way and also enable code completion so that you can be sure to apply only a valid value among the expected ones. All enumerations can be found in the package pyrogram.enums and are documented in the dedicated page for Enumerations.

  • Datetime objects for timestamps: Timestamp values found in the framework will now be represented by the datetime class so you can read and pass timestamps around in a more convenient way instead of dealing with bare integer additions.

  • Iter_* methods have been removed: This means there is now only one way of iterating through items by using the respective get_* methods which are all turned into generators. Some of the methods have been renamed as well:

  • Client.send becomes Client.invoke: For better intent clarity of the method, Client.send has been renamed to Client.invoke. The action of “sending” a function was less clear than the action of invoking it.

  • Message.message_id becomes Message.id: For consistency reasons, Message.message_id has been renamed to Message.id. This makes it a less redundant name and will reflect with all other types that have the .id attribute.

  • on_edited_message for edited messages: The on_message() decorator will not handle edited messages anymore. Edited messages are now being handled by the new dedicated decorator on_edited_message() and the respective handler class. This mainly to make it easier handling new messages only by avoiding using ~filters.edited; such filter has been removed since it is not being relevant anymore.

  • Support for the config.ini file has been removed: Pyrogram will not manage an automatic config.ini file anymore. This means that all settings (API key, bot token, proxy settings, plugins settings, etc…), must be passed to the Client instance using its parameters, when relevant.

  • The API key is not required anymore for existing sessions: When starting existing sessions, Pyrogram will not require anymore the API key (api_id and api_hash); it will, instead, ask once for the api_id alone to be stored inside the existing session file so that further restarts will work without having to pass it. For new sessions, you still need to provide the API key (api_id and api_hash) in order to complete the authorization process. At the end you will be able to run clients by only passing the authorized session.

  • Examples throughout the documentations are async by default: Examples found in the documentation are now using the asynchronous interface by default, except for when explicitly explaining how to use them in a non-asynchronous way. See Synchronous Usage for more information about the topic.

  • Improved support for inline query results: All available results are now the following: InlineQueryResultCachedAudio, InlineQueryResultCachedDocument, InlineQueryResultCachedAnimation, InlineQueryResultCachedPhoto, InlineQueryResultCachedSticker, InlineQueryResultCachedVideo, InlineQueryResultCachedVoice, InlineQueryResultArticle, InlineQueryResultAudio, InlineQueryResultContact, InlineQueryResultDocument, InlineQueryResultAnimation, InlineQueryResultLocation, InlineQueryResultPhoto, InlineQueryResultVenue, InlineQueryResultVideo and InlineQueryResultVoice.

Other changes & additions#

  • The minimum Python version required is now Python 3.7.

  • The ChatMember type has been revamped to allow a more convenient representation of administrator privileges, which are now kept in a dedicated attribute with the type ChatPrivileges.

  • Added the attributes reply_to_message_id and reply_to_top_message_id to Message. These attributes will enable the recognition of messages that are replies to other messages (in case the reply_to_message is not set) and the original messages of a thread.

  • Added the methods get_discussion_replies() and get_discussion_replies_count() for obtaining the messages belonging to a discussion thread (including channel comments).

  • Added the method pyrogram.compose() to run multiple clients at once.

  • The methods update_username and update_chat_username have been renamed to set_username() and set_chat_username().

  • The methods pin_chat_message() and pin() are now returning the service message about the pinned message instead of a boolean.

  • Added the bound method react() and unpin_all_messages().

  • The ability to access Pyrogram’s objects attributes via bracket notation has been removed, you can access them via the usual dot notation instead.

  • The attribute storing the error value previously accessed with e.x has been renamed to a more natural name, e.value.

  • The session string format has been updated, use export_session_string() to update. The Client parameter session_name has been renamed to name and doesn’t accept the session string anymore, use the session_string parameter instead. It also doesn’t accept :memory: anymore, use the new parameter in_memory=True instead.

  • Added new type ChatJoiner and the related method get_chat_join_requests().

  • get_chat_invite_link_members and get_chat_invite_link_members_count have been renamed to get_chat_invite_link_joiners() and get_chat_invite_link_joiners_count().

  • Added support for Web Apps bots (Bot API 6.0).

  • Added the class WebAppInfo and the field web_app to the classes KeyboardButton and InlineKeyboardButton.

  • Added the class SentWebAppMessage and the method answer_web_app_query() for sending an answer to a Web App query, which originated from an inline button of the “web_app” type.

  • Added the class WebAppData and the field web_app_data to the class Message.

  • Added the class MenuButton and the methods set_chat_menu_button() and get_chat_menu_button() for managing the behavior of the bot’s menu button in private chats.

  • Added the methods set_bot_default_privileges() and get_bot_default_privileges() for managing the bot’s default privileges.

  • Renamed the field can_manage_voice_chats to can_manage_video_chats in the class ChatPrivileges.

  • Renamed the parameter can_manage_voice_chats to can_manage_video_chats in the method promote_chat_member().

  • Renamed the fields voice_chat_scheduled, voice_chat_started, voice_chat_ended, and voice_chat_members_invited to video_chat_scheduled, video_chat_started, video_chat_ended, and video_chat_members_invited in the class Message.

  • Renamed the parameter voice_chats to video_chats in ChatEventFilter.

Transition guide#

  • Enumerations: Instead of string constants, object attributes will now hold an enumeration values and methods are expected an enumeration value as well. For example, a Chat type will not be "channel" anymore but CHANNEL; when searching for messages with a filter, you can’t pass a string constant anymore (for example "photo"), but you need to pass a valid enumeration value, for example PHOTO. The documentation of each method and type has been updated to reflect these changes.

    from pyrogram import enums
    
    ...
    c = app.get_chat(chat_id)
    
    # Check whether a chat is a channel.
    print(c.type == enums.ChatType.CHANNEL)
    
    from pyrogram import enums
    
    ...
    for m in app.search_messages(chat_id, filter=enums.MessagesFilter.PHOTO):
        print(m)
    
  • Datetime: Instead of integers, timestamps are now datetime objects.

    ...
    m = app.get_messages(chat_id, 12345)
    print(m.date.year, m.date.month, m.date.day)
    

    To pass timestamps around, you have to construct a datetime object. For example, banning a chat member for a day can be done this way:

    from datetime import datetime, timedelta
    
    ...
    app.ban_chat_member(
        chat_id,
        user_id,
        until_date=datetime.now() + timedelta(days=1))
    

    You can also ban a chat member until a specific date by using this convenient way:

    from datetime import datetime, timedelta
    
    ...
    app.ban_chat_member(
        chat_id,
        user_id,
        until_date=datetime(year=y, month=m, day=d))
    
  • on_edited_messages: New and edited messages now have separate decorators:

    ...
    @app.on_message()
    async def new(c, m):
        print("new")
    
    @app.on_edited_message()
    async def edited(c, m):
        print("edited")
    

    To have both new and edited messages handled using a single function, stack the decorators one on top of the other:

    ...
    f = filters.command("start")
    
    @app.on_message(f)
    @app.on_edited_message(f)
    async def new_and_edited(c, m):
        print("new and edited")