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
|
# Import after sys.path.insert() to avoid issues
|
||||||
from pyrogram import __version__
|
from pyrogram import __version__
|
||||||
|
|
||||||
|
from pygments.styles.friendly import FriendlyStyle
|
||||||
|
|
||||||
|
FriendlyStyle.background_color = "#f3f2f1"
|
||||||
|
|
||||||
# -- General configuration ------------------------------------------------
|
# -- General configuration ------------------------------------------------
|
||||||
|
|
||||||
# If your documentation needs a minimal Sphinx version, state it here.
|
# If your documentation needs a minimal Sphinx version, state it here.
|
||||||
@ -60,7 +64,7 @@ master_doc = 'index'
|
|||||||
|
|
||||||
# General information about the project.
|
# General information about the project.
|
||||||
project = 'Pyrogram'
|
project = 'Pyrogram'
|
||||||
copyright = '2017-2018, Dan Tès'
|
copyright = '2017-2019, Dan Tès'
|
||||||
author = 'Dan Tès'
|
author = 'Dan Tès'
|
||||||
|
|
||||||
# The version info for the project you're documenting, acts as replacement for
|
# The version info for the project you're documenting, acts as replacement for
|
||||||
@ -85,7 +89,7 @@ language = None
|
|||||||
exclude_patterns = []
|
exclude_patterns = []
|
||||||
|
|
||||||
# The name of the Pygments (syntax highlighting) style to use.
|
# 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.
|
# If true, `todo` and `todoList` produce output, else they produce nothing.
|
||||||
todo_include_todos = False
|
todo_include_todos = False
|
||||||
|
@ -9,6 +9,7 @@ Handlers
|
|||||||
MessageHandler
|
MessageHandler
|
||||||
DeletedMessagesHandler
|
DeletedMessagesHandler
|
||||||
CallbackQueryHandler
|
CallbackQueryHandler
|
||||||
|
InlineQueryHandler
|
||||||
UserStatusHandler
|
UserStatusHandler
|
||||||
DisconnectHandler
|
DisconnectHandler
|
||||||
RawUpdateHandler
|
RawUpdateHandler
|
||||||
@ -22,6 +23,9 @@ Handlers
|
|||||||
.. autoclass:: CallbackQueryHandler
|
.. autoclass:: CallbackQueryHandler
|
||||||
:members:
|
:members:
|
||||||
|
|
||||||
|
.. autoclass:: InlineQueryHandler
|
||||||
|
:members:
|
||||||
|
|
||||||
.. autoclass:: UserStatusHandler
|
.. autoclass:: UserStatusHandler
|
||||||
:members:
|
:members:
|
||||||
|
|
||||||
|
@ -1,40 +1,102 @@
|
|||||||
Advanced Usage
|
Advanced Usage
|
||||||
==============
|
==============
|
||||||
|
|
||||||
In this section, you'll be shown the alternative way of communicating with Telegram using Pyrogram: the main Telegram
|
Pyrogram's API, which consists of well documented convenience methods_ and facade types_, exists to provide a much
|
||||||
API with its raw functions and types.
|
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
|
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
|
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>`
|
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.
|
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::
|
.. 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
|
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_!
|
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
|
Unlike the methods_ found in Pyrogram's API, which can be called in the usual simple way, functions to be invoked from
|
||||||
*exactly* the right values, but also because most of them don't have enough Python experience to fully grasp how things
|
the raw Telegram API have a different way of usage and are more complex.
|
||||||
work.
|
|
||||||
|
|
||||||
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
|
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 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.
|
There are three different InputPeer types, one for each kind of Telegram entity.
|
||||||
Whenever an InputPeer is needed you must pass one of these:
|
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:
|
For example, given the ID *123456789*, here's how Pyrogram can tell entities apart:
|
||||||
|
|
||||||
- ``+ID`` - User: *123456789*
|
- ``+ID`` User: *123456789*
|
||||||
- ``-ID`` - Chat: *-123456789*
|
- ``-ID`` Chat: *-123456789*
|
||||||
- ``-100ID`` - Channel (and Supergroup): *-100123456789*
|
- ``-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
|
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.
|
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
|
.. _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
|
.. _Community: https://t.me/PyrogramChat
|
@ -1,13 +1,13 @@
|
|||||||
Configuration File
|
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.
|
This page explains how this file is structured in Pyrogram, how to use it and why.
|
||||||
|
|
||||||
Introduction
|
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
|
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
|
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.
|
fill in the necessary parts.
|
||||||
@ -46,7 +46,7 @@ These are all the sections Pyrogram uses in its configuration file:
|
|||||||
Pyrogram
|
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
|
.. code-block:: ini
|
||||||
|
|
||||||
|
@ -1,19 +1,19 @@
|
|||||||
Customize Sessions
|
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.
|
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
|
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
|
app (or by invoking `GetAuthorizations <../functions/account/GetAuthorizations.html>`_ with Pyrogram). They store some
|
||||||
information about the client who generated them.
|
useful information such as the client who's using them and from which country and IP address.
|
||||||
|
|
||||||
|
|
||||||
.. figure:: https://i.imgur.com/lzGPCdZ.png
|
.. figure:: https://i.imgur.com/lzGPCdZ.png
|
||||||
:width: 70%
|
:width: 70%
|
||||||
:align: center
|
: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.
|
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.
|
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
|
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:`303 - See Other <pyrogram.errors.SeeOther>`
|
||||||
- :obj:`400 - Bad Request <pyrogram.errors.BadRequest>`
|
- :obj:`400 - Bad Request <pyrogram.errors.BadRequest>`
|
||||||
|
@ -1,24 +1,22 @@
|
|||||||
More on Updates
|
More on Updates
|
||||||
===============
|
===============
|
||||||
|
|
||||||
Here we'll show some advanced usages when working with updates.
|
Here we'll show some advanced usages when working with `update handlers`_ and `filters`_.
|
||||||
|
|
||||||
.. 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>`_.
|
|
||||||
|
|
||||||
Handler Groups
|
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.
|
In order to handle the very same update more than once, you have to register your handler in a different dispatching
|
||||||
Groups are identified by a number (number 0 being the default) and are sorted, that is, a lower group number has a
|
group. Dispatching groups hold one or more handlers and are processed sequentially, they are identified by a number
|
||||||
higher priority.
|
(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
|
.. code-block:: python
|
||||||
|
:emphasize-lines: 1, 6
|
||||||
|
|
||||||
@app.on_message(Filters.text | Filters.sticker)
|
@app.on_message(Filters.text | Filters.sticker)
|
||||||
def text_or_sticker(client, message):
|
def text_or_sticker(client, message):
|
||||||
@ -29,8 +27,8 @@ For example, in:
|
|||||||
def just_text(client, message):
|
def just_text(client, message):
|
||||||
print("Just Text")
|
print("Just Text")
|
||||||
|
|
||||||
``just_text`` is never executed because ``text_or_sticker`` already handles texts. To enable it, simply register the
|
Here, ``just_text`` is never executed because ``text_or_sticker``, which has been registered first, already handles
|
||||||
function using a different group:
|
texts (``Filters.text`` is shared and conflicting). To enable it, register the function using a different group:
|
||||||
|
|
||||||
.. code-block:: python
|
.. 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)
|
@app.on_message(Filters.private, group=1)
|
||||||
def _(client, message):
|
def _(client, message):
|
||||||
print(1 / 0) # Unhandled exception: ZeroDivisionError
|
raise Exception("Unhandled exception!") # Simulate an unhandled exception
|
||||||
|
|
||||||
|
|
||||||
@app.on_message(Filters.private, group=2)
|
@app.on_message(Filters.private, group=2)
|
||||||
@ -82,7 +80,7 @@ The output for each incoming update will therefore be:
|
|||||||
.. code-block:: text
|
.. code-block:: text
|
||||||
|
|
||||||
0
|
0
|
||||||
ZeroDivisionError: division by zero
|
Exception: Unhandled exception!
|
||||||
2
|
2
|
||||||
|
|
||||||
Stop Propagation
|
Stop Propagation
|
||||||
@ -153,9 +151,9 @@ Continue Propagation
|
|||||||
|
|
||||||
As opposed to `stopping the update propagation <#stop-propagation>`_ and also as an alternative to the
|
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
|
`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
|
**the same group** regardless of the next handler's filters. This allows you to register multiple handlers with
|
||||||
filters in the same group; to let the dispatcher process the next handler you can do *one* of the following in each
|
overlapping filters in the same group; to let the dispatcher process the next handler you can do *one* of the following
|
||||||
handler you want to grant permission to continue:
|
in each handler you want to grant permission to continue:
|
||||||
|
|
||||||
- Call the update's bound-method ``.continue_propagation()`` (preferred way).
|
- Call the update's bound-method ``.continue_propagation()`` (preferred way).
|
||||||
- Manually ``raise ContinuePropagation`` exception (more suitable for raw updates only).
|
- Manually ``raise ContinuePropagation`` exception (more suitable for raw updates only).
|
||||||
@ -218,4 +216,7 @@ The output of both (equivalent) examples will be:
|
|||||||
|
|
||||||
0
|
0
|
||||||
1
|
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
|
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,
|
your applications, you had to put your function definitions in separate files and register them inside your main script
|
||||||
like this:
|
after importing your modules, like this:
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
|
|
||||||
@ -72,7 +72,7 @@ functions. So, what if you could? Smart Plugins solve this issue by taking care
|
|||||||
Using Smart Plugins
|
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", ...).
|
#. 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.
|
#. 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
|
from pyrogram import Client
|
||||||
|
|
||||||
plugins = dict(
|
plugins = dict(root="plugins")
|
||||||
root="plugins"
|
|
||||||
)
|
|
||||||
|
|
||||||
Client("my_account", plugins=plugins).run()
|
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
|
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
|
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.
|
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 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.
|
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
|
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
|
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``
|
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 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.
|
- 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
|
.. code-block:: python
|
||||||
|
|
||||||
plugins = dict(
|
plugins = dict(root="plugins")
|
||||||
root="plugins"
|
|
||||||
)
|
|
||||||
|
|
||||||
Client("my_account", plugins=plugins).run()
|
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
|
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
|
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
|
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
|
) 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`` 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>``.
|
Handler, will reveal the actual callback ``<function echo at 0x10e3b6598>``.
|
||||||
|
|
||||||
Unloading
|
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
|
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
|
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:
|
name preceded by the star ``*`` operator as argument. Example:
|
||||||
|
|
||||||
- ``main.py``
|
- ``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
|
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``
|
- ``main.py``
|
||||||
|
|
||||||
|
@ -1,11 +1,13 @@
|
|||||||
Update Handling
|
Update Handling
|
||||||
===============
|
===============
|
||||||
|
|
||||||
Updates are events that happen in your Telegram account (incoming messages, new channel posts, new members join, ...)
|
Let's now dive right into the core of the framework.
|
||||||
and can be handled by registering one or more callback functions in your app by using `Handlers <../pyrogram/Handlers.html>`_.
|
|
||||||
|
|
||||||
To put it simply, whenever an update is received from Telegram it will be dispatched and your previously defined callback
|
Updates are events that happen in your Telegram account (incoming messages, new channel posts, new members join, ...)
|
||||||
function(s) matching it will be called back with the update itself as argument.
|
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
|
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
|
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.
|
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
|
Using Decorators
|
||||||
----------------
|
----------------
|
||||||
|
|
||||||
The easiest and nicest way to register a MessageHandler is by decorating your function with the
|
A much nicer way to register a MessageHandler is by decorating your callback function with the
|
||||||
:meth:`on_message() <pyrogram.Client.on_message>` decorator. Here's a full example that prints out the content
|
:meth:`on_message() <pyrogram.Client.on_message>` decorator, which will still make use of add_handler() under the hood.
|
||||||
of a message as soon as it arrives.
|
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
@ -37,23 +60,13 @@ of a message as soon as it arrives.
|
|||||||
|
|
||||||
app.run()
|
app.run()
|
||||||
|
|
||||||
Using add_handler()
|
|
||||||
-------------------
|
|
||||||
|
|
||||||
If you prefer not to use decorators for any reason, there is an alternative way for registering Handlers.
|
.. note::
|
||||||
This is useful, for example, when you want to keep your callback functions in separate files.
|
|
||||||
|
|
||||||
.. 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
|
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.
|
||||||
def my_handler(client, message):
|
|
||||||
print(message)
|
|
||||||
|
|
||||||
|
|
||||||
app = Client("my_account")
|
|
||||||
|
|
||||||
app.add_handler(MessageHandler(my_handler))
|
|
||||||
|
|
||||||
app.run()
|
|
@ -1,17 +1,19 @@
|
|||||||
Using Filters
|
Using Filters
|
||||||
=============
|
=============
|
||||||
|
|
||||||
For a finer grained control over what kind of messages will be allowed or not in your callback functions, you can use
|
So far we've seen how to register a callback function that executes every time a specific update comes from the server,
|
||||||
:class:`Filters <pyrogram.Filters>`.
|
but there's much more than that to come.
|
||||||
|
|
||||||
.. note::
|
Here we'll discuss about :class:`Filters <pyrogram.Filters>`. Filters enable a fine-grain control over what kind of
|
||||||
This page makes use of Handlers to show you how to handle updates.
|
updates are allowed or not to be passed in your callback functions, based on their inner details.
|
||||||
Learn more at `Update Handling <UpdateHandling.html>`_.
|
|
||||||
|
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
|
- 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
|
.. code-block:: python
|
||||||
|
:emphasize-lines: 4
|
||||||
|
|
||||||
from pyrogram import Filters
|
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):
|
def my_handler(client, message):
|
||||||
print(message)
|
print(message)
|
||||||
|
|
||||||
- or, without decorators:
|
- or, without decorators. Here filters are passed as the second argument of the handler constructor:
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
:emphasize-lines: 8
|
||||||
|
|
||||||
from pyrogram import Filters, MessageHandler
|
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
|
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 ``~`` to invert a filter (behaves like the ``not`` operator).
|
||||||
- Use ``&`` and ``|`` to merge two filters (behave like ``and``, ``or`` operators respectively).
|
- 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):
|
def my_handler(client, message):
|
||||||
print(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
|
.. 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
|
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
|
a specific one for your needs or want to build a custom filter by yourself (to be used in a different kind of handler,
|
||||||
example) you can use :meth:`Filters.create() <pyrogram.Filters.create>`.
|
for example) you can use :meth:`Filters.create() <pyrogram.Filters.create>`.
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
At the moment, the built-in filters are intended to be used with the :obj:`MessageHandler <pyrogram.MessageHandler>`
|
At the moment, the built-in filters are intended to be used with the :obj:`MessageHandler <pyrogram.MessageHandler>`
|
||||||
only.
|
only.
|
||||||
|
|
||||||
An example to demonstrate how custom filters work is to show how to create and use one for the
|
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;
|
:obj:`CallbackQueryHandler <pyrogram.CallbackQueryHandler>`. Note that callback queries updates are only received by
|
||||||
create and `authorize your bot <../start/Setup.html#bot-authorization>`_, then send a message with an inline keyboard to
|
bots; create and `authorize your bot <../start/Setup.html#bot-authorization>`_, then send a message with an inline
|
||||||
yourself. This allows you to test your filter by pressing the inline button:
|
keyboard to yourself. This allows you to test your filter by pressing the inline button:
|
||||||
|
|
||||||
.. code-block:: python
|
.. 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>`.
|
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
|
The code below creates a simple filter for hardcoded, static callback data. This filter will only allow callback queries
|
||||||
containing "pyrogram" as data:
|
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
|
.. code-block:: python
|
||||||
|
|
||||||
hardcoded_data = Filters.create(
|
static_data = Filters.create(
|
||||||
name="HardcodedData",
|
name="StaticdData",
|
||||||
func=lambda filter, callback_query: callback_query.data == b"pyrogram"
|
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
|
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
|
.. code-block:: python
|
||||||
|
|
||||||
def func(filter, callback_query):
|
def func(flt, callback_query):
|
||||||
return callback_query.data == b"pyrogram"
|
return callback_query.data == b"Pyrogram"
|
||||||
|
|
||||||
hardcoded_data = Filters.create(
|
static_data = Filters.create(
|
||||||
name="HardcodedData",
|
name="StaticData",
|
||||||
func=func
|
func=func
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -160,14 +164,14 @@ The filter usage remains the same:
|
|||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
@app.on_callback_query(hardcoded_data)
|
@app.on_callback_query(static_data)
|
||||||
def pyrogram_data(client, callback_query):
|
def pyrogram_data(client, callback_query):
|
||||||
client.answer_callback_query(callback_query.id, "it works!")
|
client.answer_callback_query(callback_query.id, "it works!")
|
||||||
|
|
||||||
Filters with Arguments
|
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>`.
|
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:
|
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):
|
def dynamic_data(data):
|
||||||
return Filters.create(
|
return Filters.create(
|
||||||
name="DynamicData",
|
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"
|
data=data # "data" kwarg is accessed with "filter.data"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -185,6 +189,6 @@ And its usage:
|
|||||||
|
|
||||||
.. code-block:: python
|
.. 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):
|
def pyrogram_data(client, callback_query):
|
||||||
client.answer_callback_query(callback_query.id, "it works!")
|
client.answer_callback_query(callback_query.id, "it works!")
|
@ -1,11 +1,11 @@
|
|||||||
Installation
|
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.
|
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
|
- Get **Python 3** from https://www.python.org/downloads/ (or with your package manager)
|
||||||
by following the instructions at https://pip.pypa.io/en/latest/installing/.
|
- Get **pip** by following the instructions at https://pip.pypa.io/en/latest/installing/.
|
||||||
|
|
||||||
.. important::
|
.. important::
|
||||||
|
|
||||||
@ -29,8 +29,12 @@ Install Pyrogram
|
|||||||
Bleeding Edge
|
Bleeding Edge
|
||||||
-------------
|
-------------
|
||||||
|
|
||||||
If you want the latest development version of Pyrogram, you can install it straight from the develop_
|
Things are constantly evolving in Pyrogram, although new releases are published only when enough changes are added,
|
||||||
branch using this command (note "develop.zip" in the link):
|
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
|
.. code-block:: text
|
||||||
|
|
||||||
@ -39,10 +43,10 @@ branch using this command (note "develop.zip" in the link):
|
|||||||
Asynchronous
|
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.
|
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):
|
Use this command to install (note "asyncio.zip" in the link):
|
||||||
|
|
||||||
.. code-block:: text
|
.. code-block:: text
|
||||||
@ -85,4 +89,4 @@ If no error shows up you are good to go.
|
|||||||
'0.12.0'
|
'0.12.0'
|
||||||
|
|
||||||
.. _TgCrypto: https://docs.pyrogram.ml/resources/TgCrypto
|
.. _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.
|
#. 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**.
|
#. Done. The API key consists of two parts: **App api_id** and **App api_hash**.
|
||||||
|
|
||||||
|
|
||||||
.. important::
|
.. important::
|
||||||
|
|
||||||
This API key is personal and should be kept secret.
|
This API key is personal and must be kept secret.
|
||||||
|
|
||||||
Configuration
|
Configuration
|
||||||
-------------
|
-------------
|
||||||
|
|
||||||
The API key obtained in the `previous step <#api-keys>`_ defines a token for your application allowing you to access
|
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
|
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:
|
fits better for you:
|
||||||
|
|
||||||
- Create a new ``config.ini`` file at the root of your working directory, copy-paste the following and replace the
|
- 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
|
**api_id** and **api_hash** values with your own. This is the preferred method because allows you to keep your
|
||||||
to keep your credentials out of your code without having to deal with how to load them:
|
credentials out of your code without having to deal with how to load them:
|
||||||
|
|
||||||
.. code-block:: ini
|
.. code-block:: ini
|
||||||
|
|
||||||
@ -39,8 +38,8 @@ fits better for you:
|
|||||||
api_id = 12345
|
api_id = 12345
|
||||||
api_hash = 0123456789abcdef0123456789abcdef
|
api_hash = 0123456789abcdef0123456789abcdef
|
||||||
|
|
||||||
- Alternatively, you can pass your API key to Pyrogram by simply using the *api_id* and *api_hash*
|
- Alternatively, you can pass your API key to Pyrogram by simply using the *api_id* and *api_hash* parameters of the
|
||||||
parameters of the Client class. This way you can have full control on how to store and load your credentials:
|
Client class. This way you can have full control on how to store and load your credentials:
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
@ -54,16 +53,16 @@ fits better for you:
|
|||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
|
|
||||||
The examples below assume you have created a ``config.ini`` file, thus they won't show the *api_id*
|
From now on, the code snippets assume you are using the ``config.ini`` file, thus they won't show the *api_id* and
|
||||||
and *api_hash* parameters usage.
|
*api_hash* parameters usage to keep them as clean as possible.
|
||||||
|
|
||||||
User Authorization
|
User Authorization
|
||||||
------------------
|
------------------
|
||||||
|
|
||||||
In order to use the API, Telegram requires that Users be authorized via their phone numbers.
|
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
|
Pyrogram automatically manages this access, all you need to do is create an instance of the
|
||||||
the :class:`Client <pyrogram.Client>` class by passing to it a ``session_name`` of your choice
|
:class:`Client <pyrogram.Client>` class by passing to it a ``session_name`` of your choice (e.g.: "my_account") and call
|
||||||
(e.g.: "my_account") and call the :meth:`run() <pyrogram.Client.run>` method:
|
the :meth:`run() <pyrogram.Client.run>` method:
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
@ -80,31 +79,40 @@ and the **phone code** you will receive:
|
|||||||
Enter phone number: +39**********
|
Enter phone number: +39**********
|
||||||
Is "+39**********" correct? (y/n): y
|
Is "+39**********" correct? (y/n): y
|
||||||
Enter phone code: 32768
|
Enter phone code: 32768
|
||||||
|
Logged in successfully as Dan
|
||||||
|
|
||||||
After successfully authorizing yourself, a new file called ``my_account.session`` will be created allowing
|
After successfully authorizing yourself, a new file called ``my_account.session`` will be created allowing Pyrogram
|
||||||
Pyrogram executing API calls with your identity. This file will be loaded again when you restart your app,
|
executing API calls with your identity. This file will be loaded again when you restart your app, and as long as you
|
||||||
and as long as you keep the session alive, Pyrogram won't ask you again to enter your phone number.
|
keep the session alive, Pyrogram won't ask you again to enter your phone number.
|
||||||
|
|
||||||
.. important::
|
.. important::
|
||||||
|
|
||||||
Your ``*.session`` files are personal and must be kept secret.
|
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
|
Bot Authorization
|
||||||
-----------------
|
-----------------
|
||||||
|
|
||||||
Bots are a special kind of users that are authorized via their tokens (instead of phone numbers), which are created by
|
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
|
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.
|
`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,
|
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.
|
usually your bot username) and pass your bot token using the ``bot_token`` parameter. The session file will be named
|
||||||
The session file will be named after the session name, which will be ``pyrogrambot.session`` for the example below.
|
after the session name, which will be ``pyrogrambot.session`` for the example below.
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
from pyrogram import Client
|
from pyrogram import Client
|
||||||
|
|
||||||
app = Client("pyrogrambot", bot_token="123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11")
|
app = Client(
|
||||||
|
"pyrogrambot",
|
||||||
|
bot_token="123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11"
|
||||||
|
)
|
||||||
app.run()
|
app.run()
|
||||||
|
|
||||||
.. _installed Pyrogram: Installation.html
|
.. _installed Pyrogram: Installation.html
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
Usage
|
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
|
High-level API
|
||||||
--------------
|
--------------
|
||||||
@ -11,34 +11,36 @@ named after the `Telegram Bot API`_.
|
|||||||
|
|
||||||
Here's a simple example:
|
Here's a simple example:
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
from pyrogram import Client
|
from pyrogram import Client
|
||||||
|
|
||||||
app = Client("my_account")
|
app = Client("my_account")
|
||||||
|
|
||||||
app.start()
|
app.start()
|
||||||
|
|
||||||
print(app.get_me())
|
print(app.get_me())
|
||||||
app.send_message("me", "Hi there! I'm using **Pyrogram**")
|
app.send_message("me", "Hi there! I'm using **Pyrogram**")
|
||||||
app.send_location("me", 51.500729, -0.124583)
|
app.send_location("me", 51.500729, -0.124583)
|
||||||
|
app.send_sticker("me", "CAADBAADyg4AAvLQYAEYD4F7vcZ43AI")
|
||||||
|
|
||||||
app.stop()
|
app.stop()
|
||||||
|
|
||||||
You can also use Pyrogram in a context manager with the ``with`` statement. The Client will automatically
|
You can also use Pyrogram in a context manager with the ``with`` statement. The Client will automatically
|
||||||
:meth:`start <pyrogram.Client.start>` and :meth:`stop <pyrogram.Client.stop>` gracefully, even in case of unhandled
|
:meth:`start <pyrogram.Client.start>` and :meth:`stop <pyrogram.Client.stop>` gracefully, even in case of unhandled
|
||||||
exceptions in your code:
|
exceptions in your code:
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
from pyrogram import Client
|
from pyrogram import Client
|
||||||
|
|
||||||
app = Client("my_account")
|
app = Client("my_account")
|
||||||
|
|
||||||
with app:
|
with app:
|
||||||
print(app.get_me())
|
print(app.get_me())
|
||||||
app.send_message("me", "Hi there! I'm using **Pyrogram**")
|
app.send_message("me", "Hi there! I'm using **Pyrogram**")
|
||||||
app.send_location("me", 51.500729, -0.124583)
|
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>`_.
|
More examples on `GitHub <https://github.com/pyrogram/pyrogram/tree/develop/examples>`_.
|
||||||
|
|
||||||
@ -46,4 +48,4 @@ More examples on `GitHub <https://github.com/pyrogram/pyrogram/tree/develop/exam
|
|||||||
.. _authorized: Setup.html#user-authorization
|
.. _authorized: Setup.html#user-authorization
|
||||||
.. _Telegram Bot API: https://core.telegram.org/bots/api
|
.. _Telegram Bot API: https://core.telegram.org/bots/api
|
||||||
.. _methods: ../pyrogram/Client.html#messages
|
.. _methods: ../pyrogram/Client.html#messages
|
||||||
.. _types: ../pyrogram/Types.html
|
.. _types: ../pyrogram/Types.html
|
||||||
|
@ -33,13 +33,6 @@ class OnCallbackQuery(BaseClient):
|
|||||||
"""Use this decorator to automatically register a function for handling callback queries.
|
"""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`.
|
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:
|
Args:
|
||||||
filters (:obj:`Filters <pyrogram.Filters>`):
|
filters (:obj:`Filters <pyrogram.Filters>`):
|
||||||
Pass one or more filters to allow only a subset of callback queries to be passed
|
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.
|
"""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`.
|
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:
|
Args:
|
||||||
filters (:obj:`Filters <pyrogram.Filters>`):
|
filters (:obj:`Filters <pyrogram.Filters>`):
|
||||||
Pass one or more filters to allow only a subset of messages to be passed
|
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.
|
"""Use this decorator to automatically register a function for handling messages.
|
||||||
This does the same thing as :meth:`add_handler` using the :class:`MessageHandler`.
|
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:
|
Args:
|
||||||
filters (:obj:`Filters <pyrogram.Filters>`):
|
filters (:obj:`Filters <pyrogram.Filters>`):
|
||||||
Pass one or more filters to allow only a subset of messages to be passed
|
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.
|
"""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`.
|
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:
|
Args:
|
||||||
group (``int``, *optional*):
|
group (``int``, *optional*):
|
||||||
The group identifier, defaults to 0.
|
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.
|
"""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`.
|
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:
|
Args:
|
||||||
filters (:obj:`Filters <pyrogram.Filters>`):
|
filters (:obj:`Filters <pyrogram.Filters>`):
|
||||||
Pass one or more filters to allow only a subset of UserStatus updated to be passed in your function.
|
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