Clean up documentation pages
This commit is contained in:
parent
3ac62ba941
commit
05aed5e0e1
@ -25,6 +25,10 @@ sys.path.insert(0, os.path.abspath('../..'))
|
||||
# Import after sys.path.insert() to avoid issues
|
||||
from pyrogram import __version__
|
||||
|
||||
from pygments.styles.friendly import FriendlyStyle
|
||||
|
||||
FriendlyStyle.background_color = "#f3f2f1"
|
||||
|
||||
# -- General configuration ------------------------------------------------
|
||||
|
||||
# If your documentation needs a minimal Sphinx version, state it here.
|
||||
@ -60,7 +64,7 @@ master_doc = 'index'
|
||||
|
||||
# General information about the project.
|
||||
project = 'Pyrogram'
|
||||
copyright = '2017-2018, Dan Tès'
|
||||
copyright = '2017-2019, Dan Tès'
|
||||
author = 'Dan Tès'
|
||||
|
||||
# The version info for the project you're documenting, acts as replacement for
|
||||
@ -85,7 +89,7 @@ language = None
|
||||
exclude_patterns = []
|
||||
|
||||
# The name of the Pygments (syntax highlighting) style to use.
|
||||
pygments_style = 'tango'
|
||||
pygments_style = 'friendly'
|
||||
|
||||
# If true, `todo` and `todoList` produce output, else they produce nothing.
|
||||
todo_include_todos = False
|
||||
|
@ -9,6 +9,7 @@ Handlers
|
||||
MessageHandler
|
||||
DeletedMessagesHandler
|
||||
CallbackQueryHandler
|
||||
InlineQueryHandler
|
||||
UserStatusHandler
|
||||
DisconnectHandler
|
||||
RawUpdateHandler
|
||||
@ -22,6 +23,9 @@ Handlers
|
||||
.. autoclass:: CallbackQueryHandler
|
||||
:members:
|
||||
|
||||
.. autoclass:: InlineQueryHandler
|
||||
:members:
|
||||
|
||||
.. autoclass:: UserStatusHandler
|
||||
:members:
|
||||
|
||||
|
@ -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).
|
||||
@ -219,3 +217,6 @@ The output of both (equivalent) examples will be:
|
||||
0
|
||||
1
|
||||
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!")
|
@ -1,11 +1,11 @@
|
||||
Installation
|
||||
============
|
||||
|
||||
Being a Python library, Pyrogram requires Python to be installed in your system.
|
||||
Being a Python library, **Pyrogram** requires Python to be installed in your system.
|
||||
We recommend using the latest version of Python 3 and pip.
|
||||
|
||||
Get Python 3 from https://www.python.org/downloads/ (or with your package manager) and pip
|
||||
by following the instructions at https://pip.pypa.io/en/latest/installing/.
|
||||
- Get **Python 3** from https://www.python.org/downloads/ (or with your package manager)
|
||||
- Get **pip** by following the instructions at https://pip.pypa.io/en/latest/installing/.
|
||||
|
||||
.. important::
|
||||
|
||||
@ -29,8 +29,12 @@ Install Pyrogram
|
||||
Bleeding Edge
|
||||
-------------
|
||||
|
||||
If you want the latest development version of Pyrogram, you can install it straight from the develop_
|
||||
branch using this command (note "develop.zip" in the link):
|
||||
Things are constantly evolving in Pyrogram, although new releases are published only when enough changes are added,
|
||||
but this doesn't mean you can't try new features right now!
|
||||
|
||||
In case you would like to try out the latest Pyrogram features and additions, the `GitHub repo`_ is always kept updated
|
||||
with new changes; you can install the development version straight from the ``develop`` branch using this command
|
||||
(note "develop.zip" in the link):
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
@ -39,10 +43,10 @@ branch using this command (note "develop.zip" in the link):
|
||||
Asynchronous
|
||||
------------
|
||||
|
||||
Pyrogram heavily depends on IO-bound network code (it's a cloud-based messaging client library after all), and here's
|
||||
Pyrogram heavily depends on IO-bound network code (it's a cloud-based messaging framework after all), and here's
|
||||
where asyncio shines the most by providing extra performance while running on a single OS-level thread only.
|
||||
|
||||
**A fully asynchronous variant of Pyrogram is therefore available** (Python 3.5+ required).
|
||||
**A fully asynchronous variant of Pyrogram is therefore available** (Python 3.5.3+ required).
|
||||
Use this command to install (note "asyncio.zip" in the link):
|
||||
|
||||
.. code-block:: text
|
||||
@ -85,4 +89,4 @@ If no error shows up you are good to go.
|
||||
'0.12.0'
|
||||
|
||||
.. _TgCrypto: https://docs.pyrogram.ml/resources/TgCrypto
|
||||
.. _develop: http://github.com/pyrogram/pyrogram
|
||||
.. _`Github repo`: http://github.com/pyrogram/pyrogram
|
||||
|
@ -15,23 +15,22 @@ If you already have one you can skip this step, otherwise:
|
||||
#. Fill out the form to register a new Telegram application.
|
||||
#. Done. The API key consists of two parts: **App api_id** and **App api_hash**.
|
||||
|
||||
|
||||
.. important::
|
||||
|
||||
This API key is personal and should be kept secret.
|
||||
This API key is personal and must be kept secret.
|
||||
|
||||
Configuration
|
||||
-------------
|
||||
|
||||
The API key obtained in the `previous step <#api-keys>`_ defines a token for your application allowing you to access
|
||||
the Telegram database using the MTProto API — **it is therefore required for all authorizations of both Users and Bots**.
|
||||
the Telegram database using the MTProto API — **it is therefore required for all authorizations of both users and bots**.
|
||||
|
||||
Having it handy, it's time to configure your Pyrogram project. There are two ways to do so, and you can choose what
|
||||
fits better for you:
|
||||
|
||||
- Create a new ``config.ini`` file at the root of your working directory, copy-paste the following and replace the
|
||||
**api_id** and **api_hash** values with your own. This is the preferred method because allows you
|
||||
to keep your credentials out of your code without having to deal with how to load them:
|
||||
**api_id** and **api_hash** values with your own. This is the preferred method because allows you to keep your
|
||||
credentials out of your code without having to deal with how to load them:
|
||||
|
||||
.. code-block:: ini
|
||||
|
||||
@ -39,8 +38,8 @@ fits better for you:
|
||||
api_id = 12345
|
||||
api_hash = 0123456789abcdef0123456789abcdef
|
||||
|
||||
- Alternatively, you can pass your API key to Pyrogram by simply using the *api_id* and *api_hash*
|
||||
parameters of the Client class. This way you can have full control on how to store and load your credentials:
|
||||
- Alternatively, you can pass your API key to Pyrogram by simply using the *api_id* and *api_hash* parameters of the
|
||||
Client class. This way you can have full control on how to store and load your credentials:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
@ -54,16 +53,16 @@ fits better for you:
|
||||
|
||||
.. note::
|
||||
|
||||
The examples below assume you have created a ``config.ini`` file, thus they won't show the *api_id*
|
||||
and *api_hash* parameters usage.
|
||||
From now on, the code snippets assume you are using the ``config.ini`` file, thus they won't show the *api_id* and
|
||||
*api_hash* parameters usage to keep them as clean as possible.
|
||||
|
||||
User Authorization
|
||||
------------------
|
||||
|
||||
In order to use the API, Telegram requires that Users be authorized via their phone numbers.
|
||||
Pyrogram automatically manages this access, all you need to do is create an instance of
|
||||
the :class:`Client <pyrogram.Client>` class by passing to it a ``session_name`` of your choice
|
||||
(e.g.: "my_account") and call the :meth:`run() <pyrogram.Client.run>` method:
|
||||
In order to use the API, Telegram requires that users be authorized via their phone numbers.
|
||||
Pyrogram automatically manages this access, all you need to do is create an instance of the
|
||||
:class:`Client <pyrogram.Client>` class by passing to it a ``session_name`` of your choice (e.g.: "my_account") and call
|
||||
the :meth:`run() <pyrogram.Client.run>` method:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
@ -80,31 +79,40 @@ and the **phone code** you will receive:
|
||||
Enter phone number: +39**********
|
||||
Is "+39**********" correct? (y/n): y
|
||||
Enter phone code: 32768
|
||||
Logged in successfully as Dan
|
||||
|
||||
After successfully authorizing yourself, a new file called ``my_account.session`` will be created allowing
|
||||
Pyrogram executing API calls with your identity. This file will be loaded again when you restart your app,
|
||||
and as long as you keep the session alive, Pyrogram won't ask you again to enter your phone number.
|
||||
After successfully authorizing yourself, a new file called ``my_account.session`` will be created allowing Pyrogram
|
||||
executing API calls with your identity. This file will be loaded again when you restart your app, and as long as you
|
||||
keep the session alive, Pyrogram won't ask you again to enter your phone number.
|
||||
|
||||
.. important::
|
||||
|
||||
Your ``*.session`` files are personal and must be kept secret.
|
||||
|
||||
.. note::
|
||||
|
||||
The code above does nothing except asking for credentials and keeping the client online, hit ``CTRL+C`` now to stop
|
||||
your application and keep reading.
|
||||
|
||||
Bot Authorization
|
||||
-----------------
|
||||
|
||||
Bots are a special kind of users that are authorized via their tokens (instead of phone numbers), which are created by
|
||||
BotFather_. Bot tokens replace the Users' phone numbers only — you still need to
|
||||
`configure a Telegram API key <#configuration>`_ with Pyrogram, even when using Bots.
|
||||
BotFather_. Bot tokens replace the users' phone numbers only — you still need to
|
||||
`configure a Telegram API key <#configuration>`_ with Pyrogram, even when using bots.
|
||||
|
||||
The authorization process is automatically managed. All you need to do is choose a ``session_name`` (can be anything,
|
||||
usually your bot username) and pass your bot token using the ``bot_token`` parameter.
|
||||
The session file will be named after the session name, which will be ``pyrogrambot.session`` for the example below.
|
||||
usually your bot username) and pass your bot token using the ``bot_token`` parameter. The session file will be named
|
||||
after the session name, which will be ``pyrogrambot.session`` for the example below.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from pyrogram import Client
|
||||
|
||||
app = Client("pyrogrambot", bot_token="123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11")
|
||||
app = Client(
|
||||
"pyrogrambot",
|
||||
bot_token="123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11"
|
||||
)
|
||||
app.run()
|
||||
|
||||
.. _installed Pyrogram: Installation.html
|
||||
|
@ -1,7 +1,7 @@
|
||||
Usage
|
||||
=====
|
||||
|
||||
Having your `project set up`_ and your account authorized_, it's time to play with the API. Let's start!
|
||||
Having your `project set up`_ and your account authorized_, it's time to start playing with the API. Let's start!
|
||||
|
||||
High-level API
|
||||
--------------
|
||||
@ -22,6 +22,7 @@ Here's a simple example:
|
||||
print(app.get_me())
|
||||
app.send_message("me", "Hi there! I'm using **Pyrogram**")
|
||||
app.send_location("me", 51.500729, -0.124583)
|
||||
app.send_sticker("me", "CAADBAADyg4AAvLQYAEYD4F7vcZ43AI")
|
||||
|
||||
app.stop()
|
||||
|
||||
@ -39,6 +40,7 @@ exceptions in your code:
|
||||
print(app.get_me())
|
||||
app.send_message("me", "Hi there! I'm using **Pyrogram**")
|
||||
app.send_location("me", 51.500729, -0.124583)
|
||||
app.send_sticker("me", "CAADBAADyg4AAvLQYAEYD4F7vcZ43AI")
|
||||
|
||||
More examples on `GitHub <https://github.com/pyrogram/pyrogram/tree/develop/examples>`_.
|
||||
|
||||
|
@ -33,13 +33,6 @@ class OnCallbackQuery(BaseClient):
|
||||
"""Use this decorator to automatically register a function for handling callback queries.
|
||||
This does the same thing as :meth:`add_handler` using the :class:`CallbackQueryHandler`.
|
||||
|
||||
.. note::
|
||||
This decorator will wrap your defined function in a tuple consisting of *(Handler, group)*.
|
||||
|
||||
To reference your own function after it has been decorated, you need to access
|
||||
*my_function[0].callback*, that is, the *callback* field of Handler object which is the the
|
||||
first element in the tuple.
|
||||
|
||||
Args:
|
||||
filters (:obj:`Filters <pyrogram.Filters>`):
|
||||
Pass one or more filters to allow only a subset of callback queries to be passed
|
||||
|
@ -33,13 +33,6 @@ class OnDeletedMessages(BaseClient):
|
||||
"""Use this decorator to automatically register a function for handling deleted messages.
|
||||
This does the same thing as :meth:`add_handler` using the :class:`DeletedMessagesHandler`.
|
||||
|
||||
.. note::
|
||||
This decorator will wrap your defined function in a tuple consisting of *(Handler, group)*.
|
||||
|
||||
To reference your own function after it has been decorated, you need to access
|
||||
*my_function[0].callback*, that is, the *callback* field of Handler object which is the the
|
||||
first element in the tuple.
|
||||
|
||||
Args:
|
||||
filters (:obj:`Filters <pyrogram.Filters>`):
|
||||
Pass one or more filters to allow only a subset of messages to be passed
|
||||
|
@ -33,13 +33,6 @@ class OnMessage(BaseClient):
|
||||
"""Use this decorator to automatically register a function for handling messages.
|
||||
This does the same thing as :meth:`add_handler` using the :class:`MessageHandler`.
|
||||
|
||||
.. note::
|
||||
This decorator will wrap your defined function in a tuple consisting of *(Handler, group)*.
|
||||
|
||||
To reference your own function after it has been decorated, you need to access
|
||||
*my_function[0].callback*, that is, the *callback* field of Handler object which is the the
|
||||
first element in the tuple.
|
||||
|
||||
Args:
|
||||
filters (:obj:`Filters <pyrogram.Filters>`):
|
||||
Pass one or more filters to allow only a subset of messages to be passed
|
||||
|
@ -31,13 +31,6 @@ class OnRawUpdate(BaseClient):
|
||||
"""Use this decorator to automatically register a function for handling raw updates.
|
||||
This does the same thing as :meth:`add_handler` using the :class:`RawUpdateHandler`.
|
||||
|
||||
.. note::
|
||||
This decorator will wrap your defined function in a tuple consisting of *(Handler, group)*.
|
||||
|
||||
To reference your own function after it has been decorated, you need to access
|
||||
*my_function[0].callback*, that is, the *callback* field of Handler object which is the the
|
||||
first element in the tuple.
|
||||
|
||||
Args:
|
||||
group (``int``, *optional*):
|
||||
The group identifier, defaults to 0.
|
||||
|
@ -33,13 +33,6 @@ class OnUserStatus(BaseClient):
|
||||
"""Use this decorator to automatically register a function for handling user status updates.
|
||||
This does the same thing as :meth:`add_handler` using the :class:`UserStatusHandler`.
|
||||
|
||||
.. note::
|
||||
This decorator will wrap your defined function in a tuple consisting of *(Handler, group)*.
|
||||
|
||||
To reference your own function after it has been decorated, you need to access
|
||||
*my_function[0].callback*, that is, the *callback* field of Handler object which is the the
|
||||
first element in the tuple.
|
||||
|
||||
Args:
|
||||
filters (:obj:`Filters <pyrogram.Filters>`):
|
||||
Pass one or more filters to allow only a subset of UserStatus updated to be passed in your function.
|
||||
|
Loading…
Reference in New Issue
Block a user