mirror of
https://github.com/pyrogram/pyrogram
synced 2025-09-01 14:55:12 +00:00
Various improvements
This commit is contained in:
@@ -1,9 +1,8 @@
|
||||
Advanced Usage
|
||||
==============
|
||||
|
||||
Pyrogram's API, which consists of well documented convenience :doc:`methods <../api/methods/index>` and facade
|
||||
:doc:`types <../api/types/index>`, exists to provide a much easier interface to the undocumented and often confusing
|
||||
Telegram API.
|
||||
Pyrogram's API -- which consists of well documented :doc:`methods <../api/methods/index>` and
|
||||
:doc:`types <../api/types/index>` -- exists to provide an easier interface to the more complex Telegram API.
|
||||
|
||||
In this section, you'll be shown the alternative way of communicating with Telegram using Pyrogram: the main "raw"
|
||||
Telegram API with its functions and types.
|
||||
@@ -21,25 +20,18 @@ Telegram Raw API
|
||||
If you can't find a high-level method for your needs or if you want complete, low-level access to the whole
|
||||
Telegram API, you have to use the raw :mod:`~pyrogram.raw.functions` and :mod:`~pyrogram.raw.types`.
|
||||
|
||||
As already hinted, raw functions and types can be really confusing, mainly because people don't realize soon enough they
|
||||
accept *only* the right types and that all required parameters must be filled in. This section will therefore explain
|
||||
some pitfalls to take into consideration when working with the raw API.
|
||||
As already hinted, raw functions and types can be less convenient. This section will therefore explain some pitfalls to
|
||||
take into consideration when working with the raw API.
|
||||
|
||||
.. hint::
|
||||
.. tip::
|
||||
|
||||
Every available high-level methods in Pyrogram is built on top of these raw functions.
|
||||
|
||||
Nothing stops you from using the raw functions only, but they are rather complex and
|
||||
:doc:`plenty of them <../api/methods/index>` are already re-implemented by providing a much simpler and cleaner
|
||||
interface which is very similar to the Bot API (yet much more powerful).
|
||||
|
||||
If you think a raw function should be wrapped and added as a high-level method, feel free to ask in our Community_!
|
||||
Every available high-level method in Pyrogram is built on top of these raw functions.
|
||||
|
||||
Invoking Functions
|
||||
^^^^^^^^^^^^^^^^^^
|
||||
------------------
|
||||
|
||||
Unlike the :doc:`methods <../api/methods/index>` found in Pyrogram's API, which can be called in the usual simple way,
|
||||
functions to be invoked from the raw Telegram API have a different way of usage and are more complex.
|
||||
functions to be invoked from the raw Telegram API have a different way of usage.
|
||||
|
||||
First of all, both :doc:`raw functions <../telegram/functions/index>` and :doc:`raw types <../telegram/types/index>`
|
||||
live in their respective packages (and sub-packages): ``pyrogram.raw.functions``, ``pyrogram.raw.types``. They all exist
|
||||
@@ -61,12 +53,12 @@ Here's some examples:
|
||||
with Client("my_account") as app:
|
||||
app.send(
|
||||
functions.account.UpdateProfile(
|
||||
first_name="Dan", last_name="Tès",
|
||||
about="Bio written from Pyrogram"
|
||||
first_name="First Name", last_name="Last Name",
|
||||
about="New bio text"
|
||||
)
|
||||
)
|
||||
|
||||
- Disable links to your account when someone forwards your messages:
|
||||
- Set online/offline status:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
@@ -74,14 +66,13 @@ Here's some examples:
|
||||
from pyrogram.raw import functions, types
|
||||
|
||||
with Client("my_account") as app:
|
||||
app.send(
|
||||
functions.account.SetPrivacy(
|
||||
key=types.PrivacyKeyForwards(),
|
||||
rules=[types.InputPrivacyValueDisallowAll()]
|
||||
)
|
||||
)
|
||||
# Set online status
|
||||
app.send(functions.account.UpdateStatus(offline=False))
|
||||
|
||||
- Invite users to your channel/supergroup:
|
||||
# Set offline status
|
||||
app.send(functions.account.UpdateStatus(offline=True))
|
||||
|
||||
- Get chat info:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
@@ -89,21 +80,18 @@ Here's some examples:
|
||||
from pyrogram.raw import functions, types
|
||||
|
||||
with Client("my_account") as app:
|
||||
app.send(
|
||||
functions.channels.InviteToChannel(
|
||||
channel=app.resolve_peer(123456789), # ID or Username
|
||||
users=[ # The users you want to invite
|
||||
app.resolve_peer(23456789), # By ID
|
||||
app.resolve_peer("username"), # By username
|
||||
app.resolve_peer("+393281234567"), # By phone number
|
||||
]
|
||||
r = app.send(
|
||||
functions.channels.GetFullChannel(
|
||||
channel=app.resolve_peer("username")
|
||||
)
|
||||
)
|
||||
|
||||
print(r)
|
||||
|
||||
Chat IDs
|
||||
^^^^^^^^
|
||||
--------
|
||||
|
||||
The way Telegram works makes it impossible to directly send a message to a user or a chat by using their IDs only.
|
||||
The way Telegram works makes it not possible to directly send a message to a user or a chat by using their IDs only.
|
||||
Instead, a pair of ``id`` and ``access_hash`` wrapped in a so called ``InputPeer`` is always needed. Pyrogram allows
|
||||
sending messages with IDs only thanks to cached access hashes.
|
||||
|
||||
@@ -112,18 +100,17 @@ Whenever an InputPeer is needed you must pass one of these:
|
||||
|
||||
- :class:`~pyrogram.raw.types.InputPeerUser` - Users
|
||||
- :class:`~pyrogram.raw.types.InputPeerChat` - Basic Chats
|
||||
- :class:`~pyrogram.raw.types.InputPeerChannel` - Either Channels or Supergroups
|
||||
- :class:`~pyrogram.raw.types.InputPeerChannel` - Channels & Supergroups
|
||||
|
||||
But you don't necessarily have to manually instantiate each object because, luckily for you, Pyrogram already provides
|
||||
But you don't necessarily have to manually instantiate each object because Pyrogram already provides
|
||||
:meth:`~pyrogram.Client.resolve_peer` as a convenience utility method that returns the correct InputPeer
|
||||
by accepting a peer ID only.
|
||||
|
||||
Another thing to take into consideration about chat IDs is the way they are represented: they are all integers and
|
||||
all positive within their respective raw types.
|
||||
|
||||
Things are different when working with Pyrogram's API because having them in the same space can theoretically lead to
|
||||
collisions, and that's why Pyrogram (as well as the official Bot API) uses a slightly different representation for each
|
||||
kind of ID.
|
||||
Things are different when working with Pyrogram's API because having them in the same space could lead to
|
||||
collisions, and that's why Pyrogram uses a slightly different representation for each kind of ID.
|
||||
|
||||
For example, given the ID *123456789*, here's how Pyrogram can tell entities apart:
|
||||
|
||||
|
@@ -1,50 +0,0 @@
|
||||
Bots Interaction
|
||||
================
|
||||
|
||||
Users can interact with other bots via plain text messages as well as inline queries.
|
||||
|
||||
.. contents:: Contents
|
||||
:backlinks: none
|
||||
:depth: 1
|
||||
:local:
|
||||
|
||||
-----
|
||||
|
||||
Inline Bots
|
||||
-----------
|
||||
|
||||
- If a bot accepts inline queries, you can call it by using
|
||||
:meth:`~pyrogram.Client.get_inline_bot_results` to get the list of its inline results for a query:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
# Get bot results for "Fuzz Universe" from the inline bot @vid
|
||||
bot_results = app.get_inline_bot_results("vid", "Fuzz Universe")
|
||||
|
||||
.. figure:: https://i.imgur.com/IAqLs54.png
|
||||
:width: 90%
|
||||
:align: center
|
||||
:figwidth: 60%
|
||||
|
||||
``get_inline_bot_results()`` is the equivalent action of writing ``@vid Fuzz Universe`` and getting the
|
||||
results list.
|
||||
|
||||
- After you retrieved the bot results, you can use
|
||||
:meth:`~pyrogram.Client.send_inline_bot_result` to send a chosen result to any chat:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
# Send the first result to your own chat
|
||||
app.send_inline_bot_result(
|
||||
"me",
|
||||
bot_results.query_id,
|
||||
bot_results.results[0].id
|
||||
)
|
||||
|
||||
.. figure:: https://i.imgur.com/wwxr7B7.png
|
||||
:width: 90%
|
||||
:align: center
|
||||
:figwidth: 60%
|
||||
|
||||
``send_inline_bot_result()`` is the equivalent action of choosing a result from the list and sending it
|
||||
to a chat.
|
@@ -1,24 +1,12 @@
|
||||
Session Settings
|
||||
================
|
||||
Client Settings
|
||||
===============
|
||||
|
||||
As you may probably know, Telegram allows users (and bots) having more than one session (authorizations) registered
|
||||
in the system at the same time.
|
||||
You can control the way your client appears in the Active Sessions menu of an official client by changing some client
|
||||
settings. By default you will see something like the following:
|
||||
|
||||
Briefly explaining, sessions are simply new logins in your account. They can be reviewed in the settings of an official
|
||||
app (or by invoking :class:`~pyrogram.api.functions.account.GetAuthorizations` with Pyrogram). They
|
||||
store some useful information such as the client who's using them and from which country and IP address.
|
||||
|
||||
.. figure:: https://i.imgur.com/YaqtMLO.png
|
||||
:width: 600
|
||||
:align: center
|
||||
|
||||
**A Pyrogram session running on Linux, Python 3.7.**
|
||||
|
||||
That's how a session looks like on the Android app, showing the three main pieces of information.
|
||||
|
||||
- ``app_version``: **Pyrogram 0.13.0**
|
||||
- ``device_model``: **CPython 3.7.2**
|
||||
- ``system_version``: **Linux 4.15.0-23-generic**
|
||||
- Device Model: ``CPython x.y.z``
|
||||
- Application: ``Pyrogram x.y.z``
|
||||
- System Version: ``Linux x.y.z``
|
||||
|
||||
.. contents:: Contents
|
||||
:backlinks: none
|
@@ -15,7 +15,7 @@ Introduction
|
||||
------------
|
||||
|
||||
The idea behind using a configuration file is to help keeping your code free of private settings information such as
|
||||
the API Key and Proxy, without having you to even deal with how to load such settings. The configuration file, usually
|
||||
the API Key and Proxy, without having you to deal with how to load such settings. The configuration file, usually
|
||||
referred as ``config.ini`` file, is automatically loaded from the root of your working directory; all you need to do is
|
||||
fill in the necessary parts.
|
||||
|
||||
@@ -23,7 +23,7 @@ fill in the necessary parts.
|
||||
|
||||
The configuration file is optional, but recommended. If, for any reason, you prefer not to use it, there's always an
|
||||
alternative way to configure Pyrogram via Client's parameters. Doing so, you can have full control on how to store
|
||||
and load your settings (e.g.: from environment variables).
|
||||
and load your settings.
|
||||
|
||||
Settings specified via Client's parameter have higher priority and will override any setting stored in the
|
||||
configuration file.
|
||||
|
@@ -87,7 +87,7 @@ Finally, the filter usage remains the same:
|
||||
Filters with Arguments
|
||||
----------------------
|
||||
|
||||
A much cooler filter would be one that accepts "pyrogram" or any other string as argument at usage time.
|
||||
A more flexible filter would be one that accepts "pyrogram" or any other string as argument at usage time.
|
||||
A dynamic filter like this will make use of named arguments for the :meth:`~pyrogram.filters.create` method and the
|
||||
first argument of the callback function, which is a reference to the filter object itself holding the extra data passed
|
||||
via named arguments.
|
||||
|
@@ -2,7 +2,7 @@ Debugging
|
||||
=========
|
||||
|
||||
When working with the API, chances are you'll stumble upon bugs, get stuck and start wondering how to continue. Nothing
|
||||
to actually worry about -- that's normal -- and luckily for you, Pyrogram provides some commodities to help you in this.
|
||||
to actually worry about since Pyrogram provides some commodities to help you in this.
|
||||
|
||||
.. contents:: Contents
|
||||
:backlinks: none
|
||||
@@ -27,8 +27,8 @@ Consider the following code:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
dan = app.get_users("haskell")
|
||||
print(dan) # User
|
||||
me = app.get_users("me")
|
||||
print(me) # User
|
||||
|
||||
This will show a JSON representation of the object returned by :meth:`~pyrogram.Client.get_users`, which is a
|
||||
:class:`~pyrogram.types.User` instance, in this case. The output on your terminal will be something similar to this:
|
||||
@@ -36,9 +36,9 @@ This will show a JSON representation of the object returned by :meth:`~pyrogram.
|
||||
.. code-block:: json
|
||||
|
||||
{
|
||||
"_": "pyrogram.User",
|
||||
"id": 23122162,
|
||||
"is_self": false,
|
||||
"_": "User",
|
||||
"id": 123456789,
|
||||
"is_self": true,
|
||||
"is_contact": false,
|
||||
"is_mutual_contact": false,
|
||||
"is_deleted": false,
|
||||
@@ -46,19 +46,13 @@ This will show a JSON representation of the object returned by :meth:`~pyrogram.
|
||||
"is_verified": false,
|
||||
"is_restricted": false,
|
||||
"is_support": false,
|
||||
"is_scam": false,
|
||||
"first_name": "Dan",
|
||||
"status": {
|
||||
"_": "pyrogram.UserStatus",
|
||||
"user_id": 23122162,
|
||||
"recently": true
|
||||
},
|
||||
"username": "haskell",
|
||||
"language_code": "en",
|
||||
"first_name": "Pyrogram",
|
||||
"photo": {
|
||||
"_": "pyrogram.ChatPhoto",
|
||||
"small_file_id": "AQADBAAD8tBgAQAEJjCxGgAEo5IBAAIC",
|
||||
"big_file_id": "AQADBAAD8tBgAQAEJjCxGgAEpZIBAAEBAg"
|
||||
"_": "ChatPhoto",
|
||||
"small_file_id": "AbCdE...EdCbA",
|
||||
"small_photo_unique_id": "VwXyZ...ZyXwV",
|
||||
"big_file_id": "AbCdE...EdCbA",
|
||||
"big_photo_unique_id": "VwXyZ...ZyXwV"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,37 +63,23 @@ Accessing Attributes
|
||||
--------------------
|
||||
|
||||
Even though you see a JSON output, it doesn't mean we are dealing with dictionaries; in fact, all Pyrogram types are
|
||||
full-fledged Python objects and the correct way to access any attribute of them is by using the dot notation ``.``:
|
||||
fully-fledged Python objects and the correct way to access any attribute of them is by using the dot notation ``.``:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
dan_photo = dan.photo
|
||||
print(dan_photo) # ChatPhoto
|
||||
photo = me.photo
|
||||
print(photo) # ChatPhoto
|
||||
|
||||
.. code-block:: json
|
||||
|
||||
{
|
||||
"_": "pyrogram.ChatPhoto",
|
||||
"small_file_id": "AQADBAAD8tBgAQAEJjCxGgAEo5IBAAIC",
|
||||
"big_file_id": "AQADBAAD8tBgAQAEJjCxGgAEpZIBAAEBAg"
|
||||
"_": "ChatPhoto",
|
||||
"small_file_id": "AbCdE...EdCbA",
|
||||
"small_photo_unique_id": "VwXyZ...ZyXwV",
|
||||
"big_file_id": "AbCdE...EdCbA",
|
||||
"big_photo_unique_id": "VwXyZ...ZyXwV"
|
||||
}
|
||||
|
||||
However, the bracket notation ``[]`` is also supported, but its usage is discouraged:
|
||||
|
||||
.. warning::
|
||||
|
||||
Bracket notation in Python is not commonly used for getting/setting object attributes. While it works for Pyrogram
|
||||
objects, it might not work for anything else and you should not rely on this.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
dan_photo_big = dan["photo"]["big_file_id"]
|
||||
print(dan_photo_big) # str
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
AQADBAAD8tBgAQAEJjCxGgAEpZIBAAEBAg
|
||||
|
||||
Checking an Object's Type
|
||||
-------------------------
|
||||
|
||||
@@ -111,8 +91,8 @@ error. The correct way to get the object type is by using the built-in function
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
dan_status = dan.status
|
||||
print(type(dan_status))
|
||||
status = me.status
|
||||
print(type(status))
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
@@ -125,8 +105,8 @@ And to check if an object is an instance of a given class, you use the built-in
|
||||
|
||||
from pyrogram.types import UserStatus
|
||||
|
||||
dan_status = dan.status
|
||||
print(isinstance(dan_status, UserStatus))
|
||||
status = me.status
|
||||
print(isinstance(status, UserStatus))
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
|
@@ -24,7 +24,6 @@ group. Dispatching groups hold one or more handlers and are processed sequential
|
||||
For example, take these two handlers:
|
||||
|
||||
.. code-block:: python
|
||||
:emphasize-lines: 1, 6
|
||||
|
||||
@app.on_message(filters.text | filters.sticker)
|
||||
def text_or_sticker(client, message):
|
||||
|
@@ -1,10 +1,10 @@
|
||||
MTProto vs. Bot API
|
||||
===================
|
||||
|
||||
Pyrogram is a framework that acts as a fully-fledged Telegram client based on MTProto, and this very feature makes it
|
||||
already superior to, what is usually called, the official Bot API, in many respects. This page will therefore show you
|
||||
why Pyrogram might be a better choice for your project by comparing the two APIs, but first, let's make it clear what
|
||||
actually is the MTProto and the Bot API.
|
||||
Pyrogram is a framework written from the ground up that acts as a fully-fledged Telegram client based on the MTProto
|
||||
API. This means that Pyrogram is able to execute any official client and bot API action and more. This page will
|
||||
therefore show you why Pyrogram might be a better choice for your project by comparing the two APIs, but first, let's
|
||||
make it clear what actually is the MTProto and the Bot API.
|
||||
|
||||
.. contents:: Contents
|
||||
:backlinks: none
|
||||
@@ -19,10 +19,11 @@ What is the MTProto API?
|
||||
`MTProto`_, took alone, is the name of the custom-made, open and encrypted communication protocol created by Telegram
|
||||
itself --- it's the only protocol used to exchange information between a client and the actual Telegram servers.
|
||||
|
||||
The MTProto **API** on the other hand, is what people, for convenience, call the main Telegram API as a whole. This API
|
||||
is able to authorize both users and bots and is built on top of the MTProto encryption protocol by means of
|
||||
`binary data serialized`_ in a specific way, as described by the `TL language`_, and delivered using UDP, TCP or even
|
||||
HTTP as transport-layer protocol.
|
||||
The MTProto API on the other hand, is what people for convenience call the main Telegram API in order to distinguish it
|
||||
from the Bot API. The main Telegram API is able to authorize both users and bots and is built on top of the MTProto
|
||||
encryption protocol by means of `binary data serialized`_ in a specific way, as described by the `TL language`_, and
|
||||
delivered using UDP, TCP or even HTTP as transport-layer protocol. Clients that make use of Telegram's main API, such as
|
||||
Pyrogram, implement all these details.
|
||||
|
||||
.. _MTProto: https://core.telegram.org/mtproto
|
||||
.. _binary data serialized: https://core.telegram.org/mtproto/serialize
|
||||
@@ -31,12 +32,12 @@ HTTP as transport-layer protocol.
|
||||
What is the Bot API?
|
||||
--------------------
|
||||
|
||||
The `Bot API`_ is an HTTP(S) interface for building normal bots using a sub-set of the main MTProto API. Bots are special
|
||||
accounts that are authorized via tokens instead of phone numbers. The Bot API is built yet again on top of the main
|
||||
Telegram API, but runs on an intermediate server application that in turn communicates with the actual Telegram servers
|
||||
using MTProto.
|
||||
The `Bot API`_ is an HTTP(S) interface for building normal bots using a sub-set of the main Telegram API. Bots are
|
||||
special accounts that are authorized via tokens instead of phone numbers. The Bot API is built yet again on top of the
|
||||
main Telegram API, but runs on an intermediate server application that in turn communicates with the actual Telegram
|
||||
servers using MTProto.
|
||||
|
||||
.. figure:: https://i.imgur.com/WvwBoZo.png
|
||||
.. figure:: //_static/img/mtproto-vs-bot-api.png
|
||||
:align: center
|
||||
|
||||
.. _Bot API: https://core.telegram.org/bots/api
|
||||
@@ -44,8 +45,8 @@ using MTProto.
|
||||
Advantages of the MTProto API
|
||||
-----------------------------
|
||||
|
||||
Here is a list of all the advantages in using MTProto-based libraries -- such as Pyrogram -- instead of the official
|
||||
HTTP Bot API. Using Pyrogram you can:
|
||||
Here is a non-exhaustive list of all the advantages in using MTProto-based libraries -- such as Pyrogram -- instead of
|
||||
the official HTTP Bot API. Using Pyrogram you can:
|
||||
|
||||
.. hlist::
|
||||
:columns: 1
|
||||
@@ -69,7 +70,7 @@ HTTP Bot API. Using Pyrogram you can:
|
||||
.. hlist::
|
||||
:columns: 1
|
||||
|
||||
- :guilabel:`+` **Run multiple sessions at once, up to 10 per account (either bot or user)**
|
||||
- :guilabel:`+` **Run multiple sessions at once (for both user and bot identities)**
|
||||
- :guilabel:`--` The Bot API intermediate server will terminate any other session in case you try to use the same
|
||||
bot again in a parallel connection.
|
||||
|
||||
|
@@ -14,8 +14,8 @@ non-asynchronous contexts. For more detailed information, you can visit and lear
|
||||
|
||||
-----
|
||||
|
||||
Using ``apscheduler``
|
||||
---------------------
|
||||
Using apscheduler
|
||||
-----------------
|
||||
|
||||
- Install with ``pip3 install apscheduler``
|
||||
- Documentation: https://apscheduler.readthedocs.io
|
||||
|
@@ -24,8 +24,7 @@ If you want a nicely formatted, human readable JSON representation of any object
|
||||
...
|
||||
|
||||
with app:
|
||||
r = app.get_chat("haskell")
|
||||
|
||||
r = app.get_chat("me")
|
||||
print(str(r))
|
||||
|
||||
.. tip::
|
||||
@@ -48,7 +47,7 @@ as the process requires the package to be in scope.
|
||||
...
|
||||
|
||||
with app:
|
||||
r = app.get_chat("haskell")
|
||||
r = app.get_chat("me")
|
||||
|
||||
print(repr(r))
|
||||
print(eval(repr(r)) == r) # True
|
||||
|
@@ -1,9 +1,9 @@
|
||||
Smart Plugins
|
||||
=============
|
||||
|
||||
Pyrogram embeds a **smart**, lightweight yet powerful plugin system that is meant to further simplify the organization
|
||||
of large projects and to provide a way for creating pluggable (modular) components that can be **easily shared** across
|
||||
different Pyrogram applications with **minimal boilerplate code**.
|
||||
Pyrogram embeds a smart, lightweight yet powerful plugin system that is meant to further simplify the organization
|
||||
of large projects and to provide a way for creating pluggable (modular) components that can be easily shared across
|
||||
different Pyrogram applications with minimal boilerplate code.
|
||||
|
||||
.. tip::
|
||||
|
||||
@@ -74,8 +74,8 @@ after importing your modules, like this:
|
||||
|
||||
This is already nice and doesn't add *too much* boilerplate code, but things can get boring still; you have to
|
||||
manually ``import``, manually :meth:`~pyrogram.Client.add_handler` and manually instantiate each
|
||||
:class:`~pyrogram.handlers.MessageHandler` object because **you can't use those cool decorators** for your
|
||||
functions. So, what if you could? Smart Plugins solve this issue by taking care of handlers registration automatically.
|
||||
:class:`~pyrogram.handlers.MessageHandler` object because you can't use decorators for your functions.
|
||||
So, what if you could? Smart Plugins solve this issue by taking care of handlers registration automatically.
|
||||
|
||||
Using Smart Plugins
|
||||
-------------------
|
||||
@@ -91,7 +91,6 @@ Setting up your Pyrogram project to accommodate Smart Plugins is pretty straight
|
||||
This is the same example application as shown above, written using the Smart Plugin system.
|
||||
|
||||
.. code-block:: text
|
||||
:emphasize-lines: 2, 3
|
||||
|
||||
myproject/
|
||||
plugins/
|
||||
@@ -102,7 +101,6 @@ Setting up your Pyrogram project to accommodate Smart Plugins is pretty straight
|
||||
- ``plugins/handlers.py``
|
||||
|
||||
.. code-block:: python
|
||||
:emphasize-lines: 4, 9
|
||||
|
||||
from pyrogram import Client, filters
|
||||
|
||||
@@ -164,7 +162,7 @@ found inside each module will be, instead, loaded in the order they are defined,
|
||||
.. note::
|
||||
|
||||
Remember: there can be at most one handler, within a group, dealing with a specific update. Plugins with overlapping
|
||||
filters included a second time will not work. Learn more at :doc:`More on Updates <more-on-updates>`.
|
||||
filters included a second time will not work, by design. Learn more at :doc:`More on Updates <more-on-updates>`.
|
||||
|
||||
This default loading behaviour is usually enough, but sometimes you want to have more control on what to include (or
|
||||
exclude) and in which exact order to load plugins. The way to do this is to make use of ``include`` and ``exclude``
|
||||
@@ -300,32 +298,30 @@ In the previous section we've explained how to specify which plugins to load and
|
||||
starts. Here we'll show, instead, how to unload and load again a previously registered plugin at runtime.
|
||||
|
||||
Each function decorated with the usual ``on_message`` decorator (or any other decorator that deals with Telegram
|
||||
updates) will be modified in such a way that a special ``handler`` attribute pointing to a tuple of
|
||||
updates) will be modified in such a way that a special ``handlers`` attribute pointing to a list of tuples of
|
||||
*(handler: Handler, group: int)* is attached to the function object itself.
|
||||
|
||||
- ``plugins/handlers.py``
|
||||
|
||||
.. code-block:: python
|
||||
:emphasize-lines: 5, 6
|
||||
|
||||
@Client.on_message(filters.text & filters.private)
|
||||
def echo(client, message):
|
||||
message.reply(message.text)
|
||||
|
||||
print(echo)
|
||||
print(echo.handler)
|
||||
print(echo.handlers)
|
||||
|
||||
- Printing ``echo`` will show something like ``<function echo at 0x10e3b6598>``.
|
||||
|
||||
- Printing ``echo.handler`` will reveal the handler, that is, a tuple containing the actual handler and the group it
|
||||
was registered on ``(<MessageHandler object at 0x10e3abc50>, 0)``.
|
||||
- Printing ``echo.handlers`` will reveal the handlers, that is, a list of tuples containing the actual handlers and
|
||||
the groups they were registered on ``[(<MessageHandler object at 0x10e3abc50>, 0)]``.
|
||||
|
||||
Unloading
|
||||
^^^^^^^^^
|
||||
|
||||
In order to unload a plugin, all you need to do is obtain a reference to it by importing the relevant module and call
|
||||
:meth:`~pyrogram.Client.remove_handler` Client's method with your function's *handler* special attribute preceded by the
|
||||
star ``*`` operator as argument. Example:
|
||||
:meth:`~pyrogram.Client.remove_handler` Client's method with your function's *handler* instance:
|
||||
|
||||
- ``main.py``
|
||||
|
||||
@@ -333,16 +329,19 @@ star ``*`` operator as argument. Example:
|
||||
|
||||
from plugins.handlers import echo
|
||||
|
||||
...
|
||||
handlers = echo.handlers
|
||||
|
||||
app.remove_handler(*echo.handler)
|
||||
for h in handlers:
|
||||
app.remove_handler(*h)
|
||||
|
||||
The star ``*`` operator is used to unpack the tuple into positional arguments so that *remove_handler* will receive
|
||||
exactly what is needed. The same could have been achieved with:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
handler, group = echo.handler
|
||||
handlers = echo.handlers
|
||||
handler, group = handlers[0]
|
||||
|
||||
app.remove_handler(handler, group)
|
||||
|
||||
Loading
|
||||
@@ -359,4 +358,7 @@ using :meth:`~pyrogram.Client.add_handler` instead. Example:
|
||||
|
||||
...
|
||||
|
||||
app.add_handler(*echo.handler)
|
||||
handlers = echo.handlers
|
||||
|
||||
for h in handlers:
|
||||
app.add_handler(*h)
|
@@ -18,28 +18,18 @@ Persisting Sessions
|
||||
In order to make a client reconnect successfully between restarts, that is, without having to start a new
|
||||
authorization process from scratch each time, Pyrogram needs to store the generated session data somewhere.
|
||||
|
||||
Other useful data being stored is peers' cache. In short, peers are all those entities you can chat with, such as users
|
||||
or bots, basic groups, but also channels and supergroups. Because of how Telegram works, a unique pair of **id** and
|
||||
**access_hash** is needed to contact a peer. This, plus other useful info such as the peer type, is what is stored
|
||||
inside a session storage.
|
||||
|
||||
So, if you ever wondered how is Pyrogram able to contact peers just by asking for their ids, it's because of this very
|
||||
reason: the peer *id* is looked up in the internal database and the available *access_hash* is retrieved, which is then
|
||||
used to correctly invoke API methods.
|
||||
|
||||
Different Storage Engines
|
||||
-------------------------
|
||||
|
||||
Let's now talk about how Pyrogram actually stores all the relevant data. Pyrogram offers two different types of storage
|
||||
engines: a **File Storage** and a **Memory Storage**. These engines are well integrated in the library and require a
|
||||
minimal effort to set up. Here's how they work:
|
||||
Pyrogram offers two different types of storage engines: a **File Storage** and a **Memory Storage**.
|
||||
These engines are well integrated in the framework and require a minimal effort to set up. Here's how they work:
|
||||
|
||||
File Storage
|
||||
^^^^^^^^^^^^
|
||||
|
||||
This is the most common storage engine. It is implemented by using **SQLite**, which will store the session and peers
|
||||
details. The database will be saved to disk as a single portable file and is designed to efficiently store and retrieve
|
||||
peers whenever they are needed.
|
||||
This is the most common storage engine. It is implemented by using **SQLite**, which will store the session details.
|
||||
The database will be saved to disk as a single portable file and is designed to efficiently store and retrieve
|
||||
data whenever they are needed.
|
||||
|
||||
To use this type of engine, simply pass any name of your choice to the ``session_name`` parameter of the
|
||||
:obj:`~pyrogram.Client` constructor, as usual:
|
||||
@@ -68,8 +58,8 @@ session name "**:memory:**" to the ``session_name`` parameter of the :obj:`~pyro
|
||||
with Client(":memory:") as app:
|
||||
print(app.get_me())
|
||||
|
||||
This storage engine is still backed by SQLite, but the database exists purely in memory. This means that, once you stop a
|
||||
client, the entire database is discarded and the session details used for logging in again will be lost forever.
|
||||
This storage engine is still backed by SQLite, but the database exists purely in memory. This means that, once you stop
|
||||
a client, the entire database is discarded and the session details used for logging in again will be lost forever.
|
||||
|
||||
Session Strings
|
||||
---------------
|
||||
@@ -84,8 +74,8 @@ In case you want to use an in-memory storage, but also want to keep access to th
|
||||
with Client(":memory:") as app:
|
||||
print(app.export_session_string())
|
||||
|
||||
...and save the resulting (quite long) string somewhere. You can use this string as session name the next time you want
|
||||
to login using the same session; the storage used will still be completely in-memory:
|
||||
...and save the resulting string. You can use this string as session name the next time you want to login
|
||||
using the same session; the storage used will still be in-memory:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
@@ -96,11 +86,5 @@ to login using the same session; the storage used will still be completely in-me
|
||||
with Client(session_string) as app:
|
||||
print(app.get_me())
|
||||
|
||||
Session strings are useful when you want to run authorized Pyrogram clients on platforms like
|
||||
`Heroku <https://www.heroku.com/>`_, where their ephemeral filesystems makes it much harder for a file-based storage
|
||||
engine to properly work as intended.
|
||||
|
||||
But, why is the session string so long? Can't it be shorter? No, it can't. The session string already packs the bare
|
||||
minimum data Pyrogram needs to successfully reconnect to an authorized session, and the 2048-bits auth key is the major
|
||||
contributor to the overall length. Needless to say that this string, as well as any other session storage, represent
|
||||
strictly personal data. Keep them safe.
|
||||
Session strings are useful when you want to run authorized Pyrogram clients on platforms where their ephemeral
|
||||
filesystems makes it harder for a file-based storage engine to properly work as intended.
|
||||
|
@@ -15,8 +15,7 @@ Telegram's test servers without hassle. All you need to do is start a new sessio
|
||||
.. note::
|
||||
|
||||
If this is the first time you login into test servers, you will be asked to register your account first.
|
||||
Don't worry about your contacts and chats, they will be kept untouched inside the production environment;
|
||||
accounts authorized on test servers reside in a different, parallel instance of a Telegram database.
|
||||
Accounts registered on test servers reside in a different, parallel instance of a Telegram server.
|
||||
|
||||
.. contents:: Contents
|
||||
:backlinks: none
|
||||
@@ -28,19 +27,15 @@ Telegram's test servers without hassle. All you need to do is start a new sessio
|
||||
Test Mode in Official Apps
|
||||
--------------------------
|
||||
|
||||
You can also login yourself into test servers using official desktop apps, such as Webogram and TDesktop:
|
||||
You can also login yourself into test servers using official desktop apps, such as Telegram Web and Telegram Desktop:
|
||||
|
||||
- **Webogram**: Login here: https://web.telegram.org/?test=1
|
||||
- **TDesktop**: Hold ``Alt+Shift`` and right click on "Add account", then choose "Test server".
|
||||
- **Telegram Web**: Login here: https://web.telegram.org/?test=1
|
||||
- **Telegram Desktop**: Hold ``Alt+Shift`` and right click on "Add account", then choose "Test server".
|
||||
|
||||
Test Numbers
|
||||
------------
|
||||
|
||||
Beside normal numbers, the test environment allows you to login with reserved test numbers.
|
||||
Valid phone numbers follow the pattern ``99966XYYYY``, where ``X`` is the DC number (1 to 3) and ``YYYY`` are random
|
||||
numbers. Users with such numbers always get ``XXXXX`` as the confirmation code (the DC number, repeated five times).
|
||||
|
||||
.. important::
|
||||
|
||||
Do not store any important or private information in such test users' accounts; anyone can make use of the
|
||||
simplified authorization mechanism and login at any time.
|
||||
numbers. Users with such numbers always get ``XXXXX`` or ``XXXXXX`` as the confirmation code (the DC number, repeated
|
||||
five or six times).
|
@@ -14,7 +14,7 @@ Text Formatting
|
||||
:class: strike-italic
|
||||
|
||||
Pyrogram uses a custom Markdown dialect for text formatting which adds some unique features that make writing styled
|
||||
texts easier in both Markdown and HTML. You can send sophisticated text messages and media captions using a great
|
||||
texts easier in both Markdown and HTML. You can send sophisticated text messages and media captions using a
|
||||
variety of decorations that can also be nested in order to combine multiple styles together.
|
||||
|
||||
.. contents:: Contents
|
||||
@@ -36,7 +36,7 @@ list of the basic styles currently supported by Pyrogram.
|
||||
- :underline:`underline`
|
||||
- spoiler
|
||||
- `text URL <https://pyrogram.org>`_
|
||||
- `user text mention <https://t.me/haskell>`_
|
||||
- `user text mention <tg://user?id=123456789>`_
|
||||
- ``inline fixed-width code``
|
||||
- .. code-block:: text
|
||||
|
||||
@@ -66,9 +66,9 @@ To strictly use this mode, pass "markdown" to the *parse_mode* parameter when us
|
||||
|
||||
||spoiler||
|
||||
|
||||
[text URL](https://docs.pyrogram.org/)
|
||||
[text URL](https://pyrogram.org/)
|
||||
|
||||
[text user mention](tg://user?id=23122162)
|
||||
[text user mention](tg://user?id=123456789)
|
||||
|
||||
`inline fixed-width code`
|
||||
|
||||
@@ -83,14 +83,13 @@ To strictly use this mode, pass "markdown" to the *parse_mode* parameter when us
|
||||
.. code-block:: python
|
||||
|
||||
app.send_message(
|
||||
"haskell",
|
||||
"me",
|
||||
(
|
||||
"**bold**, "
|
||||
"__italic__, "
|
||||
"--underline--, "
|
||||
"~~strike~~, "
|
||||
"||spoiler||, "
|
||||
"[mention](tg://user?id=23122162), "
|
||||
"[URL](https://pyrogram.org), "
|
||||
"`code`, "
|
||||
"```"
|
||||
@@ -119,9 +118,9 @@ The following tags are currently supported:
|
||||
|
||||
<spoiler>spoiler</spoiler>
|
||||
|
||||
<a href="http://docs.pyrogram.org/">text URL</a>
|
||||
<a href="https://pyrogram.org/">text URL</a>
|
||||
|
||||
<a href="tg://user?id=23122162">inline mention</a>
|
||||
<a href="tg://user?id=123456789">inline mention</a>
|
||||
|
||||
<code>inline fixed-width code</code>
|
||||
|
||||
@@ -136,14 +135,13 @@ The following tags are currently supported:
|
||||
.. code-block:: python
|
||||
|
||||
app.send_message(
|
||||
"haskell",
|
||||
"me",
|
||||
(
|
||||
"<b>bold</b>, "
|
||||
"<i>italic</i>, "
|
||||
"<u>underline</u>, "
|
||||
"<s>strike</s>, "
|
||||
"<spoiler>spoiler</spoiler>, "
|
||||
"<a href=\"tg://user?id=23122162\">mention</a>, "
|
||||
"<a href=\"https://pyrogram.org/\">URL</a>, "
|
||||
"<code>code</code>\n\n"
|
||||
"<pre>"
|
||||
@@ -181,7 +179,7 @@ This means you can combine together both syntaxes in the same text:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
app.send_message("haskell", "**bold**, <i>italic</i>")
|
||||
app.send_message("me", "**bold**, <i>italic</i>")
|
||||
|
||||
Result:
|
||||
|
||||
@@ -192,8 +190,8 @@ If you don't like this behaviour you can always choose to only enable either Mar
|
||||
|
||||
.. code-block::
|
||||
|
||||
app.send_message("haskell", "**bold**, <i>italic</i>", parse_mode="markdown")
|
||||
app.send_message("haskell", "**bold**, <i>italic</i>", parse_mode="html")
|
||||
app.send_message("me", "**bold**, <i>italic</i>", parse_mode="markdown")
|
||||
app.send_message("me", "**bold**, <i>italic</i>", parse_mode="html")
|
||||
|
||||
Result:
|
||||
|
||||
@@ -206,7 +204,7 @@ as-is.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
app.send_message("haskell", "**bold**, <i>italic</i>", parse_mode=None)
|
||||
app.send_message("me", "**bold**, <i>italic</i>", parse_mode=None)
|
||||
|
||||
Result:
|
||||
|
||||
|
@@ -1,11 +1,11 @@
|
||||
Fast Crypto
|
||||
===========
|
||||
|
||||
Pyrogram's speed can be *dramatically* boosted up by TgCrypto_, a high-performance, easy-to-install Telegram Crypto
|
||||
Library specifically written in C for Pyrogram [1]_ as a Python extension.
|
||||
Pyrogram's speed can be boosted up by TgCrypto_, a high-performance, easy-to-install cryptography library specifically
|
||||
written in C for Pyrogram as a Python extension.
|
||||
|
||||
TgCrypto is a replacement for the much slower PyAES and implements the crypto algorithms Telegram requires, namely
|
||||
**AES-IGE 256 bit** (used in MTProto v2.0) and **AES-CTR 256 bit** (used for CDN encrypted files).
|
||||
TgCrypto is a replacement for a slower Python-only alternative and implements the cryptographic algorithms Telegram
|
||||
requires, namely: AES-256-IGE, AES-256-CTR and AES-256-CBC.
|
||||
|
||||
Installation
|
||||
------------
|
||||
@@ -14,10 +14,10 @@ Installation
|
||||
|
||||
$ pip3 install -U tgcrypto
|
||||
|
||||
.. note:: Being a C extension for Python, TgCrypto is an optional but *highly recommended* dependency; when TgCrypto is
|
||||
not detected in your system, Pyrogram will automatically fall back to PyAES and will show you a warning.
|
||||
.. note:: When TgCrypto is not detected in your system, Pyrogram will automatically fall back to a slower Python-only
|
||||
implementation and will show you a warning.
|
||||
|
||||
The reason about being an optional package is that TgCrypto requires some extra system tools in order to be compiled.
|
||||
The reason about being an optional package is that TgCrypto requires extra system tools in order to be compiled.
|
||||
The errors you receive when trying to install TgCrypto are system dependent, but also descriptive enough to understand
|
||||
what you should do next:
|
||||
|
||||
@@ -26,7 +26,4 @@ what you should do next:
|
||||
- **Linux**: Install a proper C compiler (``gcc``, ``clang``) and the Python header files (``python3-dev``).
|
||||
- **Termux**: Install ``clang`` package.
|
||||
|
||||
.. _TgCrypto: https://github.com/pyrogram/tgcrypto
|
||||
|
||||
.. [1] Although TgCrypto is intended for Pyrogram, it is shipped as a standalone package and can thus be used for
|
||||
other Python projects too.
|
||||
.. _TgCrypto: https://github.com/pyrogram/tgcrypto
|
@@ -19,16 +19,15 @@ Single Filters
|
||||
|
||||
Let's start right away with a simple example:
|
||||
|
||||
- This example will show you how to **only** handle messages containing an :class:`~pyrogram.Audio` object and
|
||||
- This example will show you how to **only** handle messages containing a :class:`~pyrogram.types.Sticker` object and
|
||||
ignore any other message. Filters are passed as the first argument of the decorator:
|
||||
|
||||
.. code-block:: python
|
||||
:emphasize-lines: 4
|
||||
|
||||
from pyrogram import filters
|
||||
|
||||
|
||||
@app.on_message(filters.audio)
|
||||
@app.on_message(filters.sticker)
|
||||
def my_handler(client, message):
|
||||
print(message)
|
||||
|
||||
@@ -36,7 +35,6 @@ Let's start right away with a simple example:
|
||||
callback function itself:
|
||||
|
||||
.. code-block:: python
|
||||
:emphasize-lines: 9
|
||||
|
||||
from pyrogram import filters
|
||||
from pyrogram.handlers import MessageHandler
|
||||
@@ -46,12 +44,12 @@ Let's start right away with a simple example:
|
||||
print(message)
|
||||
|
||||
|
||||
app.add_handler(MessageHandler(my_handler, filters.audio))
|
||||
app.add_handler(MessageHandler(my_handler, filters.sticker))
|
||||
|
||||
Combining Filters
|
||||
-----------------
|
||||
|
||||
Filters can also be used in a more advanced way by inverting and combining more filters together using bitwise
|
||||
Filters can be used in a more advanced way by inverting and combining more filters together using bitwise
|
||||
operators ``~``, ``&`` and ``|``:
|
||||
|
||||
- Use ``~`` to invert a filter (behaves like the ``not`` operator).
|
||||
|
@@ -1,8 +1,8 @@
|
||||
Voice Calls
|
||||
===========
|
||||
|
||||
Both private voice calls and group voice calls are currently supported by third-party libraries that integrate with
|
||||
Pyrogram.
|
||||
Both private voice calls and group voice calls are currently supported by third-party, external libraries that integrate
|
||||
with Pyrogram.
|
||||
|
||||
Libraries
|
||||
---------
|
||||
|
Reference in New Issue
Block a user