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
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
offsetargument 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.enumsand are documented in the dedicated page for Enumerations.
Datetime objects for timestamps: Timestamp values found in the framework will now be represented by the
datetimeclass 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.sendhas 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_idhas been renamed to
Message.id. This makes it a less redundant name and will reflect with all other types that have the
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:
Other changes & additions#
The minimum Python version required is now Python 3.7.
ChatMembertype has been revamped to allow a more convenient representation of administrator privileges, which are now kept in a dedicated attribute with the type
Added the attributes
reply_to_top_message_idto Message. These attributes will enable the recognition of messages that are replies to other messages (in case the
reply_to_messageis not set) and the original messages of a thread.
Added the methods
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.
update_chat_usernamehave been renamed to
pin()are now returning the service message about the pinned message instead of a boolean.
Added the bound method
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.xhas been renamed to a more natural name,
The session string format has been updated, use
export_session_string()to update. The Client parameter
session_namehas been renamed to
nameand doesn’t accept the session string anymore, use the
session_stringparameter instead. It also doesn’t accept
:memory:anymore, use the new parameter
Added new type
ChatJoinerand the related method
get_chat_invite_link_members_counthave been renamed to
Added support for Web Apps bots (Bot API 6.0).
Added the class
WebAppInfoand the field web_app to the classes
Added the class
SentWebAppMessageand 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
WebAppDataand the field web_app_data to the class Message.
Added the class
MenuButtonand the methods
get_chat_menu_button()for managing the behavior of the bot’s menu button in private chats.
Added the methods
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
Renamed the parameter can_manage_voice_chats to can_manage_video_chats in the method
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
Renamed the parameter voice_chats to video_chats in
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
Chattype will not be
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
... 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")