mirror of
https://github.com/pyrogram/pyrogram
synced 2025-08-31 14:25:55 +00:00
Clean up documentation pages
This commit is contained in:
@@ -1,40 +1,102 @@
|
||||
Advanced Usage
|
||||
==============
|
||||
|
||||
In this section, you'll be shown the alternative way of communicating with Telegram using Pyrogram: the main Telegram
|
||||
API with its raw functions and types.
|
||||
Pyrogram's API, which consists of well documented convenience methods_ and facade types_, exists to provide a much
|
||||
easier interface to the undocumented and often confusing 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.
|
||||
|
||||
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:`functions <pyrogram.api.functions>` and :mod:`types <pyrogram.api.types>`
|
||||
exposed by the ``pyrogram.api`` package and call any Telegram API method you wish using the
|
||||
:meth:`send() <pyrogram.Client.send>` method provided by the Client class.
|
||||
Telegram API, you have to use the raw :mod:`functions <pyrogram.api.functions>` and :mod:`types <pyrogram.api.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.
|
||||
|
||||
.. hint::
|
||||
|
||||
Every available high-level method mentioned in the previous page is built on top of these raw functions.
|
||||
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 `plenty of them`_ are already
|
||||
re-implemented by providing a much simpler and cleaner interface which is very similar to the Bot API.
|
||||
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_!
|
||||
|
||||
Caveats
|
||||
-------
|
||||
Invoking Functions
|
||||
^^^^^^^^^^^^^^^^^^
|
||||
|
||||
As hinted before, raw functions and types can be confusing, mainly because people don't realize they must accept
|
||||
*exactly* the right values, but also because most of them don't have enough Python experience to fully grasp how things
|
||||
work.
|
||||
Unlike the methods_ 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.
|
||||
|
||||
This section will therefore explain some pitfalls to take into consideration when working with the raw API.
|
||||
First of all, both `raw functions`_ and `raw types`_ live in their respective packages (and sub-packages):
|
||||
``pyrogram.api.functions``, ``pyrogram.api.types``. They all exist as Python classes, meaning you need to create an
|
||||
instance of each every time you need them and fill them in with the correct values using named arguments.
|
||||
|
||||
Next, to actually invoke the raw function you have to use the :meth:`send() <pyrogram.Client.send>` method provided by
|
||||
the Client class and pass the function object you created.
|
||||
|
||||
Here's some examples:
|
||||
|
||||
- Update first name, last name and bio:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from pyrogram import Client
|
||||
from pyrogram.api import functions
|
||||
|
||||
with Client("my_account") as app:
|
||||
app.send(
|
||||
functions.account.UpdateProfile(
|
||||
first_name="Dan", last_name="Tès",
|
||||
about="Bio written from Pyrogram"
|
||||
)
|
||||
)
|
||||
|
||||
- Disable links to your account when someone forwards your messages:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from pyrogram import Client
|
||||
from pyrogram.api import functions, types
|
||||
|
||||
with Client("my_account") as app:
|
||||
app.send(
|
||||
functions.account.SetPrivacy(
|
||||
key=types.PrivacyKeyForwards(),
|
||||
rules=[types.InputPrivacyValueDisallowAll()]
|
||||
)
|
||||
)
|
||||
|
||||
- Invite users to your channel/supergroup:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from pyrogram import Client
|
||||
from pyrogram.api 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
|
||||
]
|
||||
)
|
||||
)
|
||||
|
||||
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.
|
||||
Instead, a pair of ``id`` and ``access_hash`` wrapped in a so called ``InputPeer`` is always needed.
|
||||
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.
|
||||
|
||||
There are three different InputPeer types, one for each kind of Telegram entity.
|
||||
Whenever an InputPeer is needed you must pass one of these:
|
||||
@@ -56,66 +118,19 @@ kind of ID.
|
||||
|
||||
For example, given the ID *123456789*, here's how Pyrogram can tell entities apart:
|
||||
|
||||
- ``+ID`` - User: *123456789*
|
||||
- ``-ID`` - Chat: *-123456789*
|
||||
- ``-100ID`` - Channel (and Supergroup): *-100123456789*
|
||||
- ``+ID`` User: *123456789*
|
||||
- ``-ID`` Chat: *-123456789*
|
||||
- ``-100ID`` Channel (and Supergroup): *-100123456789*
|
||||
|
||||
So, every time you take a raw ID, make sure to translate it into the correct ID when you want to use it with an
|
||||
high-level method.
|
||||
|
||||
Examples
|
||||
--------
|
||||
|
||||
- Update first name, last name and bio:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from pyrogram import Client
|
||||
from pyrogram.api import functions
|
||||
|
||||
with Client("my_account") as app:
|
||||
app.send(
|
||||
functions.account.UpdateProfile(
|
||||
first_name="Dan", last_name="Tès",
|
||||
about="Bio written from Pyrogram"
|
||||
)
|
||||
)
|
||||
|
||||
- Share your Last Seen time only with your contacts:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from pyrogram import Client
|
||||
from pyrogram.api import functions, types
|
||||
|
||||
with Client("my_account") as app:
|
||||
app.send(
|
||||
functions.account.SetPrivacy(
|
||||
key=types.InputPrivacyKeyStatusTimestamp(),
|
||||
rules=[types.InputPrivacyValueAllowContacts()]
|
||||
)
|
||||
)
|
||||
|
||||
- Invite users to your channel/supergroup:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from pyrogram import Client
|
||||
from pyrogram.api 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
|
||||
]
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
|
||||
.. _methods: ../pyrogram/Client.html#messages
|
||||
.. _types: ../pyrogram/Types.html
|
||||
.. _plenty of them: ../pyrogram/Client.html#messages
|
||||
.. _Raw Functions: Usage.html#using-raw-functions
|
||||
.. _raw functions: ../pyrogram/functions
|
||||
.. _raw types: ../pyrogram/types
|
||||
.. _Community: https://t.me/PyrogramChat
|
@@ -1,13 +1,13 @@
|
||||
Configuration File
|
||||
==================
|
||||
|
||||
As already mentioned in previous sections, Pyrogram can also be configured by the use of an INI file.
|
||||
As already mentioned in previous sections, Pyrogram can be configured by the use of an INI file.
|
||||
This page explains how this file is structured in Pyrogram, how to use it and why.
|
||||
|
||||
Introduction
|
||||
------------
|
||||
|
||||
The idea behind using a configuration file is to help keeping your code free of settings (private) information such as
|
||||
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
|
||||
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.
|
||||
@@ -46,7 +46,7 @@ These are all the sections Pyrogram uses in its configuration file:
|
||||
Pyrogram
|
||||
^^^^^^^^
|
||||
|
||||
The ``[pyrogram]`` section contains your Telegram API credentials *api_id* and *api_hash*.
|
||||
The ``[pyrogram]`` section contains your Telegram API credentials: *api_id* and *api_hash*.
|
||||
|
||||
.. code-block:: ini
|
||||
|
||||
|
@@ -1,19 +1,19 @@
|
||||
Customize Sessions
|
||||
==================
|
||||
|
||||
As you may probably know, Telegram allows Users (and Bots) having more than one session (authorizations) registered
|
||||
As you may probably know, Telegram allows users (and bots) having more than one session (authorizations) registered
|
||||
in the system at the same time.
|
||||
|
||||
Briefly explaining, sessions are simply new logins in your account. They can be reviewed in the settings of an official
|
||||
app (or by invoking `GetAuthorizations <../functions/account/GetAuthorizations.html>`_ with Pyrogram) and store some useful
|
||||
information about the client who generated them.
|
||||
app (or by invoking `GetAuthorizations <../functions/account/GetAuthorizations.html>`_ 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/lzGPCdZ.png
|
||||
:width: 70%
|
||||
:align: center
|
||||
|
||||
A Pyrogram session running on Linux, Python 3.6.
|
||||
**A Pyrogram session running on Linux, Python 3.6.**
|
||||
|
||||
That's how a session looks like on the Android app, showing the three main pieces of information.
|
||||
|
||||
|
@@ -4,7 +4,7 @@ Error Handling
|
||||
Errors are inevitable when working with the API, and they must be correctly handled with ``try..except`` blocks.
|
||||
|
||||
There are many errors that Telegram could return, but they all fall in one of these categories
|
||||
(which are in turn children of the :obj:`RPCError <pyrogram.RPCError>` superclass)
|
||||
(which are in turn children of the :obj:`RPCError <pyrogram.RPCError>` superclass):
|
||||
|
||||
- :obj:`303 - See Other <pyrogram.errors.SeeOther>`
|
||||
- :obj:`400 - Bad Request <pyrogram.errors.BadRequest>`
|
||||
|
@@ -1,24 +1,22 @@
|
||||
More on Updates
|
||||
===============
|
||||
|
||||
Here we'll show some advanced usages when working with updates.
|
||||
|
||||
.. note::
|
||||
This page makes use of Handlers and Filters to show you how to handle updates.
|
||||
Learn more at `Update Handling <UpdateHandling.html>`_ and `Using Filters <UsingFilters.html>`_.
|
||||
Here we'll show some advanced usages when working with `update handlers`_ and `filters`_.
|
||||
|
||||
Handler Groups
|
||||
--------------
|
||||
|
||||
If you register handlers with overlapping filters, only the first one is executed and any other handler will be ignored.
|
||||
If you register handlers with overlapping (conflicting) filters, only the first one is executed and any other handler
|
||||
will be ignored. This is intended by design.
|
||||
|
||||
In order to process the same update more than once, you can register your handler in a different group.
|
||||
Groups are identified by a number (number 0 being the default) and are sorted, that is, a lower group number has a
|
||||
higher priority.
|
||||
In order to handle the very same update more than once, you have to register your handler in a different dispatching
|
||||
group. Dispatching groups hold one or more handlers and are processed sequentially, they are identified by a number
|
||||
(number 0 being the default) and sorted, that is, a lower group number has a higher priority:
|
||||
|
||||
For example, in:
|
||||
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):
|
||||
@@ -29,8 +27,8 @@ For example, in:
|
||||
def just_text(client, message):
|
||||
print("Just Text")
|
||||
|
||||
``just_text`` is never executed because ``text_or_sticker`` already handles texts. To enable it, simply register the
|
||||
function using a different group:
|
||||
Here, ``just_text`` is never executed because ``text_or_sticker``, which has been registered first, already handles
|
||||
texts (``Filters.text`` is shared and conflicting). To enable it, register the function using a different group:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
@@ -69,7 +67,7 @@ continue to propagate the same update to the next groups until all the handlers
|
||||
|
||||
@app.on_message(Filters.private, group=1)
|
||||
def _(client, message):
|
||||
print(1 / 0) # Unhandled exception: ZeroDivisionError
|
||||
raise Exception("Unhandled exception!") # Simulate an unhandled exception
|
||||
|
||||
|
||||
@app.on_message(Filters.private, group=2)
|
||||
@@ -82,7 +80,7 @@ The output for each incoming update will therefore be:
|
||||
.. code-block:: text
|
||||
|
||||
0
|
||||
ZeroDivisionError: division by zero
|
||||
Exception: Unhandled exception!
|
||||
2
|
||||
|
||||
Stop Propagation
|
||||
@@ -153,9 +151,9 @@ Continue Propagation
|
||||
|
||||
As opposed to `stopping the update propagation <#stop-propagation>`_ and also as an alternative to the
|
||||
`handler groups <#handler-groups>`_, you can signal the internal dispatcher to continue the update propagation within
|
||||
the group regardless of the next handler's filters. This allows you to register multiple handlers with overlapping
|
||||
filters in the same group; to let the dispatcher process the next handler you can do *one* of the following in each
|
||||
handler you want to grant permission to continue:
|
||||
**the same group** regardless of the next handler's filters. This allows you to register multiple handlers with
|
||||
overlapping filters in the same group; to let the dispatcher process the next handler you can do *one* of the following
|
||||
in each handler you want to grant permission to continue:
|
||||
|
||||
- Call the update's bound-method ``.continue_propagation()`` (preferred way).
|
||||
- Manually ``raise ContinuePropagation`` exception (more suitable for raw updates only).
|
||||
@@ -218,4 +216,7 @@ The output of both (equivalent) examples will be:
|
||||
|
||||
0
|
||||
1
|
||||
2
|
||||
2
|
||||
|
||||
.. _`update handlers`: UpdateHandling.html
|
||||
.. _`filters`: UsingFilters.html
|
@@ -13,8 +13,8 @@ Introduction
|
||||
------------
|
||||
|
||||
Prior to the Smart Plugin system, pluggable handlers were already possible. For example, if you wanted to modularize
|
||||
your applications, you had to put your function definitions in separate files and register them inside your main script,
|
||||
like this:
|
||||
your applications, you had to put your function definitions in separate files and register them inside your main script
|
||||
after importing your modules, like this:
|
||||
|
||||
.. note::
|
||||
|
||||
@@ -72,7 +72,7 @@ functions. So, what if you could? Smart Plugins solve this issue by taking care
|
||||
Using Smart Plugins
|
||||
-------------------
|
||||
|
||||
Setting up your Pyrogram project to accommodate Smart Plugins is straightforward:
|
||||
Setting up your Pyrogram project to accommodate Smart Plugins is pretty straightforward:
|
||||
|
||||
#. Create a new folder to store all the plugins (e.g.: "plugins", "handlers", ...).
|
||||
#. Put your python files full of plugins inside. Organize them as you wish.
|
||||
@@ -129,18 +129,17 @@ Setting up your Pyrogram project to accommodate Smart Plugins is straightforward
|
||||
|
||||
from pyrogram import Client
|
||||
|
||||
plugins = dict(
|
||||
root="plugins"
|
||||
)
|
||||
plugins = dict(root="plugins")
|
||||
|
||||
Client("my_account", plugins=plugins).run()
|
||||
|
||||
|
||||
The first important thing to note is the new ``plugins`` folder. You can put *any python file* in *any subfolder* and
|
||||
each file can contain *any decorated function* (handlers) with one limitation: within a single module (file) you must
|
||||
use different names for each decorated function.
|
||||
|
||||
The second thing is telling Pyrogram where to look for your plugins: you can either use the *config.ini* file or
|
||||
the Client parameter "plugins"; the *root* value must match the name of your plugins folder. Your Pyrogram Client
|
||||
the Client parameter "plugins"; the *root* value must match the name of your plugins root folder. Your Pyrogram Client
|
||||
instance will **automatically** scan the folder upon starting to search for valid handlers and register them for you.
|
||||
|
||||
Then you'll notice you can now use decorators. That's right, you can apply the usual decorators to your callback
|
||||
@@ -161,7 +160,7 @@ found inside each module will be, instead, loaded in the order they are defined,
|
||||
|
||||
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``
|
||||
keys, either in the *config.ini* file or in the dictionary passed as Client argument. Here's how they work:
|
||||
directives, either in the *config.ini* file or in the dictionary passed as Client argument. Here's how they work:
|
||||
|
||||
- If both ``include`` and ``exclude`` are omitted, all plugins are loaded as described above.
|
||||
- If ``include`` is given, only the specified plugins will be loaded, in the order they are passed.
|
||||
@@ -214,9 +213,7 @@ also organized in subfolders:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
plugins = dict(
|
||||
root="plugins"
|
||||
)
|
||||
plugins = dict(root="plugins")
|
||||
|
||||
Client("my_account", plugins=plugins).run()
|
||||
|
||||
@@ -293,7 +290,7 @@ Load/Unload Plugins at Runtime
|
||||
|
||||
In the `previous section <#specifying-the-plugins-to-include>`_ we've explained how to specify which plugins to load and
|
||||
which to ignore before your Client starts. Here we'll show, instead, how to unload and load again a previously
|
||||
registered plugins at runtime.
|
||||
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, when you reference them later on, they will be actually pointing to a tuple of
|
||||
@@ -314,14 +311,14 @@ attribute. Here's an example:
|
||||
|
||||
- Printing ``echo`` will show something like ``(<MessageHandler object at 0x10e3abc50>, 0)``.
|
||||
|
||||
- Printing ``echo[0].callback``, that is, the *callback* attribute of the first eleent of the tuple, which is an
|
||||
- Printing ``echo[0].callback``, that is, the *callback* attribute of the first element of the tuple, which is an
|
||||
Handler, will reveal the actual callback ``<function echo at 0x10e3b6598>``.
|
||||
|
||||
Unloading
|
||||
^^^^^^^^^
|
||||
|
||||
In order to unload a plugin, or any other handler, all you need to do is obtain a reference to it (by importing the
|
||||
relevant module) and call :meth:`remove_handler <pyrogram.Client.remove_handler>` Client's method with your function
|
||||
In order to unload a plugin, or any other handler, all you need to do is obtain a reference to it by importing the
|
||||
relevant module and call :meth:`remove_handler() <pyrogram.Client.remove_handler>` Client's method with your function
|
||||
name preceded by the star ``*`` operator as argument. Example:
|
||||
|
||||
- ``main.py``
|
||||
@@ -346,7 +343,7 @@ Loading
|
||||
^^^^^^^
|
||||
|
||||
Similarly to the unloading process, in order to load again a previously unloaded plugin you do the same, but this time
|
||||
using :meth:`add_handler <pyrogram.Client.add_handler>` instead. Example:
|
||||
using :meth:`add_handler() <pyrogram.Client.add_handler>` instead. Example:
|
||||
|
||||
- ``main.py``
|
||||
|
||||
|
@@ -1,11 +1,13 @@
|
||||
Update Handling
|
||||
===============
|
||||
|
||||
Updates are events that happen in your Telegram account (incoming messages, new channel posts, new members join, ...)
|
||||
and can be handled by registering one or more callback functions in your app by using `Handlers <../pyrogram/Handlers.html>`_.
|
||||
Let's now dive right into the core of the framework.
|
||||
|
||||
To put it simply, whenever an update is received from Telegram it will be dispatched and your previously defined callback
|
||||
function(s) matching it will be called back with the update itself as argument.
|
||||
Updates are events that happen in your Telegram account (incoming messages, new channel posts, new members join, ...)
|
||||
and are handled by registering one or more callback functions in your app using `Handlers <../pyrogram/Handlers.html>`_.
|
||||
|
||||
Each handler deals with a specific event and once a matching update arrives from Telegram, your registered callback
|
||||
function will be called.
|
||||
|
||||
Registering an Handler
|
||||
----------------------
|
||||
@@ -15,13 +17,34 @@ To explain how handlers work let's have a look at the most used one, the
|
||||
updates coming from all around your chats. Every other handler shares the same setup logic; you should not have troubles
|
||||
settings them up once you learn from this section.
|
||||
|
||||
Using add_handler()
|
||||
-------------------
|
||||
|
||||
The :meth:`add_handler() <pyrogram.Client.add_handler>` method takes any handler instance that wraps around your defined
|
||||
callback function and registers it in your Client. Here's a full example that prints out the content of a message as
|
||||
soon as it arrives:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from pyrogram import Client, MessageHandler
|
||||
|
||||
|
||||
def my_function(client, message):
|
||||
print(message)
|
||||
|
||||
|
||||
app = Client("my_account")
|
||||
|
||||
my_handler = MessageHandler(my_function)
|
||||
app.add_handler(my_handler)
|
||||
|
||||
app.run()
|
||||
|
||||
Using Decorators
|
||||
----------------
|
||||
|
||||
The easiest and nicest way to register a MessageHandler is by decorating your function with the
|
||||
:meth:`on_message() <pyrogram.Client.on_message>` decorator. Here's a full example that prints out the content
|
||||
of a message as soon as it arrives.
|
||||
A much nicer way to register a MessageHandler is by decorating your callback function with the
|
||||
:meth:`on_message() <pyrogram.Client.on_message>` decorator, which will still make use of add_handler() under the hood.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
@@ -37,23 +60,13 @@ of a message as soon as it arrives.
|
||||
|
||||
app.run()
|
||||
|
||||
Using add_handler()
|
||||
-------------------
|
||||
|
||||
If you prefer not to use decorators for any reason, there is an alternative way for registering Handlers.
|
||||
This is useful, for example, when you want to keep your callback functions in separate files.
|
||||
.. note::
|
||||
|
||||
.. code-block:: python
|
||||
Due to how these decorators work in Pyrogram, they will wrap your defined callback function in a tuple consisting of
|
||||
``(handler, group)``; this will be the value held by your function identifier (e.g.: *my_function* from the example
|
||||
above).
|
||||
|
||||
from pyrogram import Client, MessageHandler
|
||||
|
||||
|
||||
def my_handler(client, message):
|
||||
print(message)
|
||||
|
||||
|
||||
app = Client("my_account")
|
||||
|
||||
app.add_handler(MessageHandler(my_handler))
|
||||
|
||||
app.run()
|
||||
In case, for some reason, you want to get your own function back after it has been decorated, you need to access
|
||||
``my_function[0].callback``, that is, the *callback* field of the *handler* object which is the first element in the
|
||||
tuple.
|
@@ -1,17 +1,19 @@
|
||||
Using Filters
|
||||
=============
|
||||
|
||||
For a finer grained control over what kind of messages will be allowed or not in your callback functions, you can use
|
||||
:class:`Filters <pyrogram.Filters>`.
|
||||
So far we've seen how to register a callback function that executes every time a specific update comes from the server,
|
||||
but there's much more than that to come.
|
||||
|
||||
.. note::
|
||||
This page makes use of Handlers to show you how to handle updates.
|
||||
Learn more at `Update Handling <UpdateHandling.html>`_.
|
||||
Here we'll discuss about :class:`Filters <pyrogram.Filters>`. Filters enable a fine-grain control over what kind of
|
||||
updates are allowed or not to be passed in your callback functions, based on their inner details.
|
||||
|
||||
Let's start right away with a simple example:
|
||||
|
||||
- This example will show you how to **only** handle messages containing an :obj:`Audio <pyrogram.Audio>` object and
|
||||
ignore any other message:
|
||||
ignore any other message. Filters are passed as the first argument of the decorator:
|
||||
|
||||
.. code-block:: python
|
||||
:emphasize-lines: 4
|
||||
|
||||
from pyrogram import Filters
|
||||
|
||||
@@ -20,9 +22,10 @@ For a finer grained control over what kind of messages will be allowed or not in
|
||||
def my_handler(client, message):
|
||||
print(message)
|
||||
|
||||
- or, without decorators:
|
||||
- or, without decorators. Here filters are passed as the second argument of the handler constructor:
|
||||
|
||||
.. code-block:: python
|
||||
:emphasize-lines: 8
|
||||
|
||||
from pyrogram import Filters, MessageHandler
|
||||
|
||||
@@ -37,7 +40,7 @@ Combining Filters
|
||||
-----------------
|
||||
|
||||
Filters can also be used in a more advanced way by inverting and combining more filters together using bitwise
|
||||
operators:
|
||||
operators ``~``, ``&`` and ``|``:
|
||||
|
||||
- Use ``~`` to invert a filter (behaves like the ``not`` operator).
|
||||
- Use ``&`` and ``|`` to merge two filters (behave like ``and``, ``or`` operators respectively).
|
||||
@@ -74,7 +77,7 @@ can also accept arguments:
|
||||
def my_handler(client, message):
|
||||
print(message)
|
||||
|
||||
- Message is a **text** message matching the given **regex** pattern.
|
||||
- Message is a **text** message or a media **caption** matching the given **regex** pattern.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
@@ -104,17 +107,17 @@ Custom Filters
|
||||
--------------
|
||||
|
||||
Pyrogram already provides lots of built-in :class:`Filters <pyrogram.Filters>` to work with, but in case you can't find
|
||||
a specific one for your needs or want to build a custom filter by yourself (to be used in a different handler, for
|
||||
example) you can use :meth:`Filters.create() <pyrogram.Filters.create>`.
|
||||
a specific one for your needs or want to build a custom filter by yourself (to be used in a different kind of handler,
|
||||
for example) you can use :meth:`Filters.create() <pyrogram.Filters.create>`.
|
||||
|
||||
.. note::
|
||||
At the moment, the built-in filters are intended to be used with the :obj:`MessageHandler <pyrogram.MessageHandler>`
|
||||
only.
|
||||
|
||||
An example to demonstrate how custom filters work is to show how to create and use one for the
|
||||
:obj:`CallbackQueryHandler <pyrogram.CallbackQueryHandler>`. Note that callback queries updates are only received by Bots;
|
||||
create and `authorize your bot <../start/Setup.html#bot-authorization>`_, then send a message with an inline keyboard to
|
||||
yourself. This allows you to test your filter by pressing the inline button:
|
||||
:obj:`CallbackQueryHandler <pyrogram.CallbackQueryHandler>`. Note that callback queries updates are only received by
|
||||
bots; create and `authorize your bot <../start/Setup.html#bot-authorization>`_, then send a message with an inline
|
||||
keyboard to yourself. This allows you to test your filter by pressing the inline button:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
@@ -133,26 +136,27 @@ Basic Filters
|
||||
|
||||
For this basic filter we will be using only the first two parameters of :meth:`Filters.create() <pyrogram.Filters.create>`.
|
||||
|
||||
The code below creates a simple filter for hardcoded callback data. This filter will only allow callback queries
|
||||
containing "pyrogram" as data:
|
||||
The code below creates a simple filter for hardcoded, static callback data. This filter will only allow callback queries
|
||||
containing "Pyrogram" as data, that is, the function *func* you pass returns True in case the callback query data
|
||||
equals to ``b"Pyrogram"``.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
hardcoded_data = Filters.create(
|
||||
name="HardcodedData",
|
||||
func=lambda filter, callback_query: callback_query.data == b"pyrogram"
|
||||
static_data = Filters.create(
|
||||
name="StaticdData",
|
||||
func=lambda flt, callback_query: callback_query.data == b"Pyrogram"
|
||||
)
|
||||
|
||||
The ``lambda`` operator in python is used to create small anonymous functions and is perfect for this example, the same
|
||||
could be achieved with a normal function, but we don't really need it as it makes sense only inside the filter itself:
|
||||
could be achieved with a normal function, but we don't really need it as it makes sense only inside the filter's scope:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
def func(filter, callback_query):
|
||||
return callback_query.data == b"pyrogram"
|
||||
def func(flt, callback_query):
|
||||
return callback_query.data == b"Pyrogram"
|
||||
|
||||
hardcoded_data = Filters.create(
|
||||
name="HardcodedData",
|
||||
static_data = Filters.create(
|
||||
name="StaticData",
|
||||
func=func
|
||||
)
|
||||
|
||||
@@ -160,14 +164,14 @@ The filter usage remains the same:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
@app.on_callback_query(hardcoded_data)
|
||||
@app.on_callback_query(static_data)
|
||||
def pyrogram_data(client, callback_query):
|
||||
client.answer_callback_query(callback_query.id, "it works!")
|
||||
|
||||
Filters with Arguments
|
||||
^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
A much cooler filter would be one that accepts "pyrogram" or any other data as argument at usage time.
|
||||
A much cooler filter would be one that accepts "Pyrogram" or any other data as argument at usage time.
|
||||
A dynamic filter like this will make use of the third parameter of :meth:`Filters.create() <pyrogram.Filters.create>`.
|
||||
|
||||
This is how a dynamic custom filter looks like:
|
||||
@@ -177,7 +181,7 @@ This is how a dynamic custom filter looks like:
|
||||
def dynamic_data(data):
|
||||
return Filters.create(
|
||||
name="DynamicData",
|
||||
func=lambda filter, callback_query: filter.data == callback_query.data,
|
||||
func=lambda flt, callback_query: flt.data == callback_query.data,
|
||||
data=data # "data" kwarg is accessed with "filter.data"
|
||||
)
|
||||
|
||||
@@ -185,6 +189,6 @@ And its usage:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
@app.on_callback_query(dynamic_data(b"pyrogram"))
|
||||
@app.on_callback_query(dynamic_data(b"Pyrogram"))
|
||||
def pyrogram_data(client, callback_query):
|
||||
client.answer_callback_query(callback_query.id, "it works!")
|
Reference in New Issue
Block a user