mirror of
https://github.com/pyrogram/pyrogram
synced 2025-09-02 15:25:41 +00:00
Merge branch 'develop' into inline-mode
# Conflicts: # compiler/api/compiler.py # compiler/error/source/400_BAD_REQUEST.tsv # pyrogram/__init__.py # pyrogram/client/dispatcher/dispatcher.py # pyrogram/client/ext/utils.py # pyrogram/client/methods/bots/__init__.py # pyrogram/client/types/__init__.py
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
Bad Request
|
||||
===========
|
||||
400 - Bad Request
|
||||
=================
|
||||
|
||||
.. module:: pyrogram.api.errors.BadRequest
|
||||
|
||||
|
@@ -1,5 +1,5 @@
|
||||
Flood
|
||||
=====
|
||||
420 - Flood
|
||||
===========
|
||||
|
||||
.. module:: pyrogram.api.errors.Flood
|
||||
|
||||
|
8
docs/source/errors/Forbidden.rst
Normal file
8
docs/source/errors/Forbidden.rst
Normal file
@@ -0,0 +1,8 @@
|
||||
403 - Forbidden
|
||||
===============
|
||||
|
||||
.. module:: pyrogram.api.errors.Forbidden
|
||||
|
||||
.. automodule:: pyrogram.api.errors.exceptions.forbidden_403
|
||||
:members:
|
||||
:show-inheritance:
|
@@ -1,5 +1,5 @@
|
||||
Internal Server Error
|
||||
=====================
|
||||
500 - Internal Server Error
|
||||
===========================
|
||||
|
||||
.. module:: pyrogram.api.errors.InternalServerError
|
||||
|
||||
|
8
docs/source/errors/NotAcceptable.rst
Normal file
8
docs/source/errors/NotAcceptable.rst
Normal file
@@ -0,0 +1,8 @@
|
||||
406 - Not Acceptable
|
||||
====================
|
||||
|
||||
.. module:: pyrogram.api.errors.NotAcceptable
|
||||
|
||||
.. automodule:: pyrogram.api.errors.exceptions.not_acceptable_406
|
||||
:members:
|
||||
:show-inheritance:
|
@@ -1,5 +1,5 @@
|
||||
See Other
|
||||
=========
|
||||
303 - See Other
|
||||
===============
|
||||
|
||||
.. module:: pyrogram.api.errors.SeeOther
|
||||
|
||||
|
@@ -1,5 +1,5 @@
|
||||
Unauthorized
|
||||
============
|
||||
401 - Unauthorized
|
||||
==================
|
||||
|
||||
.. module:: pyrogram.api.errors.Unauthorized
|
||||
|
||||
|
@@ -1,5 +1,5 @@
|
||||
Unknown Error
|
||||
=============
|
||||
520 - Unknown Error
|
||||
===================
|
||||
|
||||
.. module:: pyrogram.api.errors.UnknownError
|
||||
|
||||
|
@@ -10,27 +10,28 @@ Welcome to Pyrogram
|
||||
</div>
|
||||
|
||||
<p align="center">
|
||||
<b>Telegram MTProto API Client Library for Python</b>
|
||||
<b>Telegram MTProto API Framework for Python</b>
|
||||
|
||||
<br>
|
||||
<a href="https://github.com/pyrogram/pyrogram/releases/latest">
|
||||
Download
|
||||
<a href="https://docs.pyrogram.ml">
|
||||
Documentation
|
||||
</a>
|
||||
•
|
||||
<a href="https://github.com/pyrogram/pyrogram">
|
||||
Source code
|
||||
<a href="https://github.com/pyrogram/pyrogram/releases">
|
||||
Changelog
|
||||
</a>
|
||||
•
|
||||
<a href="https://t.me/PyrogramChat">
|
||||
Community
|
||||
</a>
|
||||
<br>
|
||||
<a href="https://github.com/pyrogram/pyrogram/blob/master/compiler/api/source/main_api.tl">
|
||||
<img src="https://img.shields.io/badge/schema-layer%2082-eda738.svg?longCache=true&colorA=262b30"
|
||||
alt="Scheme Layer">
|
||||
<a href="compiler/api/source/main_api.tl">
|
||||
<img src="https://img.shields.io/badge/schema-layer%2095-eda738.svg?longCache=true&colorA=262b30"
|
||||
alt="Schema Layer">
|
||||
</a>
|
||||
<a href="https://github.com/pyrogram/tgcrypto">
|
||||
<img src="https://img.shields.io/badge/tgcrypto-v1.1.1-eda738.svg?longCache=true&colorA=262b30"
|
||||
alt="TgCrypto">
|
||||
alt="TgCrypto Version">
|
||||
</a>
|
||||
</p>
|
||||
|
||||
@@ -48,25 +49,27 @@ Welcome to Pyrogram
|
||||
|
||||
app.run()
|
||||
|
||||
Welcome to Pyrogram's Documentation! Here you can find resources for learning how to use the library.
|
||||
Welcome to Pyrogram's Documentation! Here you can find resources for learning how to use the framework.
|
||||
Contents are organized into self-contained topics and can be accessed from the sidebar, or by following them in order
|
||||
using the Next button at the end of each page. But first, here's a brief overview of what is this all about.
|
||||
|
||||
About
|
||||
-----
|
||||
|
||||
**Pyrogram** is a brand new Telegram_ Client Library written from the ground up in Python and C. It can be used for
|
||||
building custom Telegram applications that interact with the MTProto API as both User and Bot.
|
||||
**Pyrogram** is an elegant, easy-to-use Telegram_ client library and framework written from the ground up in Python and C.
|
||||
It enables you to easily create custom apps using both user and bot identities (bot API alternative) via the `MTProto API`_.
|
||||
|
||||
Features
|
||||
--------
|
||||
|
||||
- **Easy to use**: You can easily install Pyrogram using pip and start building your app right away.
|
||||
- **High-level**: The low-level details of MTProto are abstracted and automatically handled.
|
||||
- **Easy**: You can install Pyrogram with pip and start building your applications right away.
|
||||
- **Elegant**: Low-level details are abstracted and re-presented in a much nicer and easier way.
|
||||
- **Fast**: Crypto parts are boosted up by TgCrypto_, a high-performance library written in pure C.
|
||||
- **Updated** to the latest Telegram API version, currently Layer 82 on top of MTProto 2.0.
|
||||
- **Documented**: The Pyrogram API is well documented and resembles the Telegram Bot API.
|
||||
- **Full API**, allowing to execute any advanced action an official client is able to do, and more.
|
||||
- **Documented**: Pyrogram API methods, types and public interfaces are well documented.
|
||||
- **Type-hinted**: Exposed Pyrogram types and method parameters are all type-hinted.
|
||||
- **Updated**, to the latest Telegram API version, currently Layer 95 on top of `MTProto 2.0`_.
|
||||
- **Pluggable**: The Smart Plugin system allows to write components with minimal boilerplate code.
|
||||
- **Comprehensive**: Execute any advanced action an official client is able to do, and even more.
|
||||
|
||||
To get started, press the Next button.
|
||||
|
||||
@@ -84,6 +87,8 @@ To get started, press the Next button.
|
||||
|
||||
resources/UpdateHandling
|
||||
resources/UsingFilters
|
||||
resources/MoreOnUpdates
|
||||
resources/ConfigurationFile
|
||||
resources/SmartPlugins
|
||||
resources/AutoAuthorization
|
||||
resources/CustomizeSessions
|
||||
@@ -92,6 +97,10 @@ To get started, press the Next button.
|
||||
resources/SOCKS5Proxy
|
||||
resources/BotsInteraction
|
||||
resources/ErrorHandling
|
||||
resources/TestServers
|
||||
resources/AdvancedUsage
|
||||
resources/VoiceCalls
|
||||
resources/Changelog
|
||||
|
||||
.. toctree::
|
||||
:hidden:
|
||||
@@ -107,4 +116,6 @@ To get started, press the Next button.
|
||||
types/index
|
||||
|
||||
.. _`Telegram`: https://telegram.org/
|
||||
.. _TgCrypto: https://docs.pyrogram.ml/resources/TgCrypto/
|
||||
.. _TgCrypto: https://docs.pyrogram.ml/resources/TgCrypto/
|
||||
.. _`MTProto API`: https://core.telegram.org/api#telegram-api
|
||||
.. _`MTProto 2.0`: https://core.telegram.org/mtproto
|
@@ -13,13 +13,15 @@ Utilities
|
||||
|
||||
start
|
||||
stop
|
||||
restart
|
||||
idle
|
||||
run
|
||||
add_handler
|
||||
remove_handler
|
||||
send
|
||||
resolve_peer
|
||||
download_media
|
||||
save_file
|
||||
stop_transmission
|
||||
|
||||
Decorators
|
||||
----------
|
||||
@@ -62,6 +64,11 @@ Messages
|
||||
delete_messages
|
||||
get_messages
|
||||
get_history
|
||||
iter_history
|
||||
send_poll
|
||||
vote_poll
|
||||
retract_vote
|
||||
download_media
|
||||
|
||||
Chats
|
||||
-----
|
||||
@@ -83,10 +90,13 @@ Chats
|
||||
pin_chat_message
|
||||
unpin_chat_message
|
||||
get_chat
|
||||
get_chat_preview
|
||||
get_chat_member
|
||||
get_chat_members
|
||||
get_chat_members_count
|
||||
iter_chat_members
|
||||
get_dialogs
|
||||
iter_dialogs
|
||||
|
||||
Users
|
||||
-----
|
||||
@@ -130,6 +140,9 @@ Bots
|
||||
send_inline_bot_result
|
||||
answer_callback_query
|
||||
request_callback_answer
|
||||
send_game
|
||||
set_game_score
|
||||
get_game_high_scores
|
||||
|
||||
|
||||
.. autoclass:: pyrogram.Client
|
||||
|
@@ -9,6 +9,8 @@ Error
|
||||
../errors/SeeOther
|
||||
../errors/BadRequest
|
||||
../errors/Unauthorized
|
||||
../errors/Forbidden
|
||||
../errors/NotAcceptable
|
||||
../errors/Flood
|
||||
../errors/InternalServerError
|
||||
../errors/UnknownError
|
||||
|
@@ -12,9 +12,11 @@ Users & Chats
|
||||
User
|
||||
UserStatus
|
||||
Chat
|
||||
ChatPreview
|
||||
ChatPhoto
|
||||
ChatMember
|
||||
ChatMembers
|
||||
ChatPermissions
|
||||
Dialog
|
||||
Dialogs
|
||||
|
||||
@@ -40,6 +42,8 @@ Messages & Media
|
||||
Location
|
||||
Venue
|
||||
Sticker
|
||||
Poll
|
||||
PollOption
|
||||
|
||||
Bots
|
||||
----
|
||||
@@ -54,6 +58,7 @@ Bots
|
||||
InlineKeyboardButton
|
||||
ForceReply
|
||||
CallbackQuery
|
||||
Game
|
||||
|
||||
Input Media
|
||||
-----------
|
||||
@@ -91,6 +96,9 @@ Inline Mode
|
||||
.. autoclass:: Chat
|
||||
:members:
|
||||
|
||||
.. autoclass:: ChatPreview
|
||||
:members:
|
||||
|
||||
.. autoclass:: ChatPhoto
|
||||
:members:
|
||||
|
||||
@@ -157,6 +165,12 @@ Inline Mode
|
||||
.. autoclass:: Sticker
|
||||
:members:
|
||||
|
||||
.. autoclass:: Poll
|
||||
:members:
|
||||
|
||||
.. autoclass:: PollOption
|
||||
:members:
|
||||
|
||||
.. Bots
|
||||
----
|
||||
|
||||
@@ -181,6 +195,15 @@ Inline Mode
|
||||
.. autoclass:: CallbackQuery
|
||||
:members:
|
||||
|
||||
.. autoclass:: Game
|
||||
:members:
|
||||
|
||||
.. autoclass:: GameHighScore
|
||||
:members:
|
||||
|
||||
.. autoclass:: GameHighScores
|
||||
:members:
|
||||
|
||||
.. Input Media
|
||||
-----------
|
||||
|
||||
|
121
docs/source/resources/AdvancedUsage.rst
Normal file
121
docs/source/resources/AdvancedUsage.rst
Normal file
@@ -0,0 +1,121 @@
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
.. hint::
|
||||
|
||||
Every available high-level method mentioned in the previous page 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.
|
||||
|
||||
If you think a raw function should be wrapped and added as a high-level method, feel free to ask in our Community_!
|
||||
|
||||
Caveats
|
||||
-------
|
||||
|
||||
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.
|
||||
|
||||
This section will therefore explain some pitfalls to take into consideration when working with the raw API.
|
||||
|
||||
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.
|
||||
|
||||
There are three different InputPeer types, one for each kind of Telegram entity.
|
||||
Whenever an InputPeer is needed you must pass one of these:
|
||||
|
||||
- `InputPeerUser <https://docs.pyrogram.ml/types/InputPeerUser>`_ - Users
|
||||
- `InputPeerChat <https://docs.pyrogram.ml/types/InputPeerChat>`_ - Basic Chats
|
||||
- `InputPeerChannel <https://docs.pyrogram.ml/types/InputPeerChannel>`_ - Either Channels or Supergroups
|
||||
|
||||
But you don't necessarily have to manually instantiate each object because, luckily for you, Pyrogram already provides
|
||||
:meth:`resolve_peer() <pyrogram.Client.resolve_peer>` as a convenience utility method that returns the correct InputPeer
|
||||
by accepting a peer ID only.
|
||||
|
||||
Another thing to take into consideration about chat IDs is the way they are represented: they are all integers and
|
||||
all positive within their respective raw types.
|
||||
|
||||
Things are different when working with Pyrogram's API because having them in the same space can theoretically lead to
|
||||
collisions, and that's why Pyrogram (as well as the official Bot API) uses a slightly different representation for each
|
||||
kind of ID.
|
||||
|
||||
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*
|
||||
|
||||
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
|
||||
]
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
.. _plenty of them: ../pyrogram/Client.html#messages
|
||||
.. _Raw Functions: Usage.html#using-raw-functions
|
||||
.. _Community: https://t.me/PyrogramChat
|
11
docs/source/resources/Changelog.rst
Normal file
11
docs/source/resources/Changelog.rst
Normal file
@@ -0,0 +1,11 @@
|
||||
Changelog
|
||||
=========
|
||||
|
||||
Currently, all Pyrogram release notes live inside the GitHub repository web page:
|
||||
https://github.com/pyrogram/pyrogram/releases
|
||||
|
||||
(You will be automatically redirected in 10 seconds.)
|
||||
|
||||
.. raw:: html
|
||||
|
||||
<meta http-equiv="refresh" content="10; URL=https://github.com/pyrogram/pyrogram/releases"/>
|
90
docs/source/resources/ConfigurationFile.rst
Normal file
90
docs/source/resources/ConfigurationFile.rst
Normal file
@@ -0,0 +1,90 @@
|
||||
Configuration File
|
||||
==================
|
||||
|
||||
As already mentioned in previous sections, Pyrogram can also 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 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.
|
||||
|
||||
.. note::
|
||||
|
||||
The configuration file is optional, but recommended. If, for any reason, you prefer not to use it, there's always an
|
||||
alternative way to configure Pyrogram via Client's parameters. Doing so, you can have full control on how to store
|
||||
and load your settings (e.g.: from environment variables).
|
||||
|
||||
Settings specified via Client's parameter have higher priority and will override any setting stored in the
|
||||
configuration file.
|
||||
|
||||
|
||||
The config.ini File
|
||||
-------------------
|
||||
|
||||
By default, Pyrogram will look for a file named ``config.ini`` placed at the root of your working directory, that is,
|
||||
the same folder of your running script. You can change the name or location of your configuration file by specifying it
|
||||
in your Client's parameter *config_file*.
|
||||
|
||||
- Replace the default *config.ini* file with *my_configuration.ini*:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from pyrogram import Client
|
||||
|
||||
app = Client("my_account", config_file="my_configuration.ini")
|
||||
|
||||
|
||||
Configuration Sections
|
||||
----------------------
|
||||
|
||||
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*.
|
||||
|
||||
.. code-block:: ini
|
||||
|
||||
[pyrogram]
|
||||
api_id = 12345
|
||||
api_hash = 0123456789abcdef0123456789abcdef
|
||||
|
||||
`More info about API Key. <../start/Setup.html#configuration>`_
|
||||
|
||||
Proxy
|
||||
^^^^^
|
||||
|
||||
The ``[proxy]`` section contains settings about your SOCKS5 proxy.
|
||||
|
||||
.. code-block:: ini
|
||||
|
||||
[proxy]
|
||||
enabled = True
|
||||
hostname = 11.22.33.44
|
||||
port = 1080
|
||||
username = <your_username>
|
||||
password = <your_password>
|
||||
|
||||
`More info about SOCKS5 Proxy. <SOCKS5Proxy.html>`_
|
||||
|
||||
Plugins
|
||||
^^^^^^^
|
||||
|
||||
The ``[plugins]`` section contains settings about Smart Plugins.
|
||||
|
||||
.. code-block:: ini
|
||||
|
||||
[plugins]
|
||||
root = plugins
|
||||
include =
|
||||
module
|
||||
folder.module
|
||||
exclude =
|
||||
module fn2
|
||||
|
||||
`More info about Smart Plugins. <SmartPlugins.html>`_
|
@@ -1,17 +1,18 @@
|
||||
Error Handling
|
||||
==============
|
||||
|
||||
Errors are inevitable when working with the API, and they must be correctly handled by
|
||||
the use of ``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 five exception 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:`pyrogram.Error` superclass)
|
||||
|
||||
- :obj:`303 See Other <pyrogram.api.errors.SeeOther>`
|
||||
- :obj:`400 Bad Request <pyrogram.api.errors.BadRequest>`
|
||||
- :obj:`401 Unauthorized <pyrogram.api.errors.Unauthorized>`
|
||||
- :obj:`420 Flood <pyrogram.api.errors.Flood>`
|
||||
- :obj:`500 Internal Server Error <pyrogram.api.errors.InternalServerError>`
|
||||
- :obj:`303 - See Other <pyrogram.api.errors.SeeOther>`
|
||||
- :obj:`400 - Bad Request <pyrogram.api.errors.BadRequest>`
|
||||
- :obj:`401 - Unauthorized <pyrogram.api.errors.Unauthorized>`
|
||||
- :obj:`403 - Forbidden <pyrogram.api.errors.Forbidden>`
|
||||
- :obj:`406 - Not Acceptable <pyrogram.api.errors.NotAcceptable>`
|
||||
- :obj:`420 - Flood <pyrogram.api.errors.Flood>`
|
||||
- :obj:`500 - Internal Server Error <pyrogram.api.errors.InternalServerError>`
|
||||
|
||||
As stated above, there are really many (too many) errors, and in case Pyrogram does not know anything yet about a
|
||||
specific one, it raises a special :obj:`520 Unknown Error <pyrogram.api.errors.UnknownError>` exception and logs it
|
||||
@@ -56,5 +57,3 @@ before you can try again. The value is always stored in the ``x`` field of the r
|
||||
...
|
||||
except FloodWait as e:
|
||||
time.sleep(e.x)
|
||||
|
||||
**TODO: Better explanation on how to deal with exceptions**
|
221
docs/source/resources/MoreOnUpdates.rst
Normal file
221
docs/source/resources/MoreOnUpdates.rst
Normal file
@@ -0,0 +1,221 @@
|
||||
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>`_.
|
||||
|
||||
Handler Groups
|
||||
--------------
|
||||
|
||||
If you register handlers with overlapping filters, only the first one is executed and any other handler will be ignored.
|
||||
|
||||
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.
|
||||
|
||||
For example, in:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
@app.on_message(Filters.text | Filters.sticker)
|
||||
def text_or_sticker(client, message):
|
||||
print("Text or Sticker")
|
||||
|
||||
|
||||
@app.on_message(Filters.text)
|
||||
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:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
@app.on_message(Filters.text, group=1)
|
||||
def just_text(client, message):
|
||||
print("Just Text")
|
||||
|
||||
Or, if you want ``just_text`` to be fired *before* ``text_or_sticker`` (note ``-1``, which is less than ``0``):
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
@app.on_message(Filters.text, group=-1)
|
||||
def just_text(client, message):
|
||||
print("Just Text")
|
||||
|
||||
With :meth:`add_handler() <pyrogram.Client.add_handler>` (without decorators) the same can be achieved with:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
app.add_handler(MessageHandler(just_text, Filters.text), -1)
|
||||
|
||||
Update propagation
|
||||
------------------
|
||||
|
||||
Registering multiple handlers, each in a different group, becomes useful when you want to handle the same update more
|
||||
than once. Any incoming update will be sequentially processed by all of your registered functions by respecting the
|
||||
groups priority policy described above. Even in case any handler raises an unhandled exception, Pyrogram will still
|
||||
continue to propagate the same update to the next groups until all the handlers are done. Example:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
@app.on_message(Filters.private)
|
||||
def _(client, message):
|
||||
print(0)
|
||||
|
||||
|
||||
@app.on_message(Filters.private, group=1)
|
||||
def _(client, message):
|
||||
print(1 / 0) # Unhandled exception: ZeroDivisionError
|
||||
|
||||
|
||||
@app.on_message(Filters.private, group=2)
|
||||
def _(client, message):
|
||||
print(2)
|
||||
|
||||
All these handlers will handle the same kind of messages, that are, messages sent or received in private chats.
|
||||
The output for each incoming update will therefore be:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
0
|
||||
ZeroDivisionError: division by zero
|
||||
2
|
||||
|
||||
Stop Propagation
|
||||
^^^^^^^^^^^^^^^^
|
||||
|
||||
In order to prevent further propagation of an update in the dispatching phase, you can do *one* of the following:
|
||||
|
||||
- Call the update's bound-method ``.stop_propagation()`` (preferred way).
|
||||
- Manually ``raise StopPropagation`` exception (more suitable for raw updates only).
|
||||
|
||||
.. note::
|
||||
|
||||
Internally, the propagation is stopped by handling a custom exception. ``.stop_propagation()`` is just an elegant
|
||||
and intuitive way to ``raise StopPropagation``; this also means that any code coming *after* calling the method
|
||||
won't be executed as your function just raised an exception to signal the dispatcher not to propagate the
|
||||
update anymore.
|
||||
|
||||
Example with ``stop_propagation()``:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
@app.on_message(Filters.private)
|
||||
def _(client, message):
|
||||
print(0)
|
||||
|
||||
|
||||
@app.on_message(Filters.private, group=1)
|
||||
def _(client, message):
|
||||
print(1)
|
||||
message.stop_propagation()
|
||||
|
||||
|
||||
@app.on_message(Filters.private, group=2)
|
||||
def _(client, message):
|
||||
print(2)
|
||||
|
||||
Example with ``raise StopPropagation``:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from pyrogram import StopPropagation
|
||||
|
||||
@app.on_message(Filters.private)
|
||||
def _(client, message):
|
||||
print(0)
|
||||
|
||||
|
||||
@app.on_message(Filters.private, group=1)
|
||||
def _(client, message):
|
||||
print(1)
|
||||
raise StopPropagation
|
||||
|
||||
|
||||
@app.on_message(Filters.private, group=2)
|
||||
def _(client, message):
|
||||
print(2)
|
||||
|
||||
Each handler is registered in a different group, but the handler in group number 2 will never be executed because the
|
||||
propagation was stopped earlier. The output of both (equivalent) examples will be:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
0
|
||||
1
|
||||
|
||||
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:
|
||||
|
||||
- Call the update's bound-method ``.continue_propagation()`` (preferred way).
|
||||
- Manually ``raise ContinuePropagation`` exception (more suitable for raw updates only).
|
||||
|
||||
.. note::
|
||||
|
||||
Internally, the propagation is continued by handling a custom exception. ``.continue_propagation()`` is just an
|
||||
elegant and intuitive way to ``raise ContinuePropagation``; this also means that any code coming *after* calling the
|
||||
method won't be executed as your function just raised an exception to signal the dispatcher to continue with the
|
||||
next available handler.
|
||||
|
||||
|
||||
Example with ``continue_propagation()``:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
@app.on_message(Filters.private)
|
||||
def _(client, message):
|
||||
print(0)
|
||||
message.continue_propagation()
|
||||
|
||||
|
||||
@app.on_message(Filters.private)
|
||||
def _(client, message):
|
||||
print(1)
|
||||
message.continue_propagation()
|
||||
|
||||
|
||||
@app.on_message(Filters.private)
|
||||
def _(client, message):
|
||||
print(2)
|
||||
|
||||
Example with ``raise ContinuePropagation``:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from pyrogram import ContinuePropagation
|
||||
|
||||
@app.on_message(Filters.private)
|
||||
def _(client, message):
|
||||
print(0)
|
||||
raise ContinuePropagation
|
||||
|
||||
|
||||
@app.on_message(Filters.private)
|
||||
def _(client, message):
|
||||
print(1)
|
||||
raise ContinuePropagation
|
||||
|
||||
|
||||
@app.on_message(Filters.private)
|
||||
def _(client, message):
|
||||
print(2)
|
||||
|
||||
Three handlers are registered in the same group, and all of them will be executed because the propagation was continued
|
||||
in each handler (except in the last one, where is useless to do so since there is no more handlers after).
|
||||
The output of both (equivalent) examples will be:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
0
|
||||
1
|
||||
2
|
@@ -1,9 +1,9 @@
|
||||
Smart Plugins
|
||||
=============
|
||||
|
||||
Pyrogram embeds a **smart** (automatic) and lightweight plugin system that is meant to further simplify the organization
|
||||
of large projects and to provide a way for creating pluggable components that can be **easily shared** across different
|
||||
Pyrogram applications with **minimal boilerplate code**.
|
||||
Pyrogram embeds a **smart**, lightweight yet powerful plugin system that is meant to further simplify the organization
|
||||
of large projects and to provide a way for creating pluggable (modular) components that can be **easily shared** across
|
||||
different Pyrogram applications with **minimal boilerplate code**.
|
||||
|
||||
.. tip::
|
||||
|
||||
@@ -13,7 +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 do something like this...
|
||||
your applications, you had to put your function definitions in separate files and register them inside your main script,
|
||||
like this:
|
||||
|
||||
.. note::
|
||||
|
||||
@@ -63,19 +64,19 @@ your applications, you had to do something like this...
|
||||
|
||||
app.run()
|
||||
|
||||
...which is already nice and doesn't add *too much* boilerplate code, but things can get boring still; you have to
|
||||
This is already nice and doesn't add *too much* boilerplate code, but things can get boring still; you have to
|
||||
manually ``import``, manually :meth:`add_handler <pyrogram.Client.add_handler>` and manually instantiate each
|
||||
:obj:`MessageHandler <pyrogram.MessageHandler>` object because **you can't use those cool decorators** for your
|
||||
functions. So... What if you could?
|
||||
functions. So, what if you could? Smart Plugins solve this issue by taking care of handlers registration automatically.
|
||||
|
||||
Using Smart Plugins
|
||||
-------------------
|
||||
|
||||
Setting up your Pyrogram project to accommodate Smart Plugins is pretty straightforward:
|
||||
Setting up your Pyrogram project to accommodate Smart Plugins is straightforward:
|
||||
|
||||
#. Create a new folder to store all the plugins (e.g.: "plugins").
|
||||
#. Put your files full of plugins inside.
|
||||
#. Enable plugins in your Client.
|
||||
#. 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.
|
||||
#. Enable plugins in your Client or via the *config.ini* file.
|
||||
|
||||
.. note::
|
||||
|
||||
@@ -107,20 +108,252 @@ Setting up your Pyrogram project to accommodate Smart Plugins is pretty straight
|
||||
def echo_reversed(client, message):
|
||||
message.reply(message.text[::-1])
|
||||
|
||||
- ``config.ini``
|
||||
|
||||
.. code-block:: ini
|
||||
|
||||
[plugins]
|
||||
root = plugins
|
||||
|
||||
- ``main.py``
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from pyrogram import Client
|
||||
|
||||
Client("my_account", plugins_dir="plugins").run()
|
||||
Client("my_account").run()
|
||||
|
||||
The first important thing to note is the new ``plugins`` folder, whose name is passed to the the ``plugins_dir``
|
||||
parameter when creating a :obj:`Client <pyrogram.Client>` in the ``main.py`` file — you can put *any python file* in
|
||||
there and each file can contain *any decorated function* (handlers) with only one limitation: within a single plugin
|
||||
file you must use different names for each decorated function. Your Pyrogram Client instance will **automatically**
|
||||
scan the folder upon creation to search for valid handlers and register them for you.
|
||||
Alternatively, without using the *config.ini* file:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from pyrogram import Client
|
||||
|
||||
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
|
||||
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
|
||||
functions in a static way, i.e. **without having the Client instance around**: simply use ``@Client`` (Client class)
|
||||
instead of the usual ``@app`` (Client instance) namespace and things will work just the same.
|
||||
instead of the usual ``@app`` (Client instance) and things will work just the same.
|
||||
|
||||
Specifying the Plugins to include
|
||||
---------------------------------
|
||||
|
||||
By default, if you don't explicitly supply a list of plugins, every valid one found inside your plugins root folder will
|
||||
be included by following the alphabetical order of the directory structure (files and subfolders); the single handlers
|
||||
found inside each module will be, instead, loaded in the order they are defined, from top to bottom.
|
||||
|
||||
.. note::
|
||||
|
||||
Remember: there can be at most one handler, within a group, dealing with a specific update. Plugins with overlapping
|
||||
filters included a second time will not work. Learn more at `More on Updates <MoreOnUpdates.html>`_.
|
||||
|
||||
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:
|
||||
|
||||
- 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 ``exclude`` is given, the plugins specified here will be unloaded.
|
||||
|
||||
The ``include`` and ``exclude`` value is a **list of strings**. Each string containing the path of the module relative
|
||||
to the plugins root folder, in Python notation (dots instead of slashes).
|
||||
|
||||
E.g.: ``subfolder.module`` refers to ``plugins/subfolder/module.py``, with ``root="plugins"``.
|
||||
|
||||
You can also choose the order in which the single handlers inside a module are loaded, thus overriding the default
|
||||
top-to-bottom loading policy. You can do this by appending the name of the functions to the module path, each one
|
||||
separated by a blank space.
|
||||
|
||||
E.g.: ``subfolder.module fn2 fn1 fn3`` will load *fn2*, *fn1* and *fn3* from *subfolder.module*, in this order.
|
||||
|
||||
Examples
|
||||
^^^^^^^^
|
||||
|
||||
Given this plugins folder structure with three modules, each containing their own handlers (fn1, fn2, etc...), which are
|
||||
also organized in subfolders:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
myproject/
|
||||
plugins/
|
||||
subfolder1/
|
||||
plugins1.py
|
||||
- fn1
|
||||
- fn2
|
||||
- fn3
|
||||
subfolder2/
|
||||
plugins2.py
|
||||
...
|
||||
plugins0.py
|
||||
...
|
||||
...
|
||||
|
||||
- Load every handler from every module, namely *plugins0.py*, *plugins1.py* and *plugins2.py* in alphabetical order
|
||||
(files) and definition order (handlers inside files):
|
||||
|
||||
Using *config.ini* file:
|
||||
|
||||
.. code-block:: ini
|
||||
|
||||
[plugins]
|
||||
root = plugins
|
||||
|
||||
Using *Client*'s parameter:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
plugins = dict(
|
||||
root="plugins"
|
||||
)
|
||||
|
||||
Client("my_account", plugins=plugins).run()
|
||||
|
||||
- Load only handlers defined inside *plugins2.py* and *plugins0.py*, in this order:
|
||||
|
||||
Using *config.ini* file:
|
||||
|
||||
.. code-block:: ini
|
||||
|
||||
[plugins]
|
||||
root = plugins
|
||||
include =
|
||||
subfolder2.plugins2
|
||||
plugins0
|
||||
|
||||
Using *Client*'s parameter:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
plugins = dict(
|
||||
root="plugins",
|
||||
include=[
|
||||
"subfolder2.plugins2",
|
||||
"plugins0"
|
||||
]
|
||||
)
|
||||
|
||||
Client("my_account", plugins=plugins).run()
|
||||
|
||||
- Load everything except the handlers inside *plugins2.py*:
|
||||
|
||||
Using *config.ini* file:
|
||||
|
||||
.. code-block:: ini
|
||||
|
||||
[plugins]
|
||||
root = plugins
|
||||
exclude = subfolder2.plugins2
|
||||
|
||||
Using *Client*'s parameter:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
plugins = dict(
|
||||
root="plugins",
|
||||
exclude=["subfolder2.plugins2"]
|
||||
)
|
||||
|
||||
Client("my_account", plugins=plugins).run()
|
||||
|
||||
- Load only *fn3*, *fn1* and *fn2* (in this order) from *plugins1.py*:
|
||||
|
||||
Using *config.ini* file:
|
||||
|
||||
.. code-block:: ini
|
||||
|
||||
[plugins]
|
||||
root = plugins
|
||||
include = subfolder1.plugins1 fn3 fn1 fn2
|
||||
|
||||
Using *Client*'s parameter:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
plugins = dict(
|
||||
root="plugins",
|
||||
include=["subfolder1.plugins1 fn3 fn1 fn2"]
|
||||
)
|
||||
|
||||
Client("my_account", plugins=plugins).run()
|
||||
|
||||
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.
|
||||
|
||||
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
|
||||
*(handler: Handler, group: int)*. The actual callback function is therefore stored inside the handler's *callback*
|
||||
attribute. Here's an example:
|
||||
|
||||
- ``plugins/handlers.py``
|
||||
|
||||
.. code-block:: python
|
||||
:emphasize-lines: 5, 6
|
||||
|
||||
@Client.on_message(Filters.text & Filters.private)
|
||||
def echo(client, message):
|
||||
message.reply(message.text)
|
||||
|
||||
print(echo)
|
||||
print(echo[0].callback)
|
||||
|
||||
- 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
|
||||
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
|
||||
name preceded by the star ``*`` operator as argument. Example:
|
||||
|
||||
- ``main.py``
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from plugins.handlers import echo
|
||||
|
||||
...
|
||||
|
||||
app.remove_handler(*echo)
|
||||
|
||||
The star ``*`` operator is used to unpack the tuple into positional arguments so that *remove_handler* will receive
|
||||
exactly what is needed. The same could have been achieved with:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
handler, group = echo
|
||||
app.remove_handler(handler, group)
|
||||
|
||||
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:
|
||||
|
||||
- ``main.py``
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from plugins.handlers import echo
|
||||
|
||||
...
|
||||
|
||||
app.add_handler(*echo)
|
39
docs/source/resources/TestServers.rst
Normal file
39
docs/source/resources/TestServers.rst
Normal file
@@ -0,0 +1,39 @@
|
||||
Test Servers
|
||||
============
|
||||
|
||||
If you wish to test your application in a separate environment, Pyrogram is able to authorize your account into
|
||||
Telegram's test servers without hassle. All you need to do is start a new session (e.g.: "my_account_test") using
|
||||
``test_mode=True``:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from pyrogram import Client
|
||||
|
||||
with Client("my_account_test", test_mode=True) as app:
|
||||
print(app.get_me())
|
||||
|
||||
.. note::
|
||||
|
||||
If this is the first time you login into test servers, you will be asked to register your account first.
|
||||
Don't worry about your contacts and chats, they will be kept untouched inside the production environment;
|
||||
accounts authorized on test servers reside in a different, parallel instance of a Telegram database.
|
||||
|
||||
Test Mode in Official Apps
|
||||
--------------------------
|
||||
|
||||
You can also login yourself into test servers using official desktop apps, such as Webogram and TDesktop:
|
||||
|
||||
- **Webogram**: Login here: https://web.telegram.org/?test=1
|
||||
- **TDesktop**: Open settings and type ``testmode``.
|
||||
|
||||
Test Numbers
|
||||
------------
|
||||
|
||||
Beside normal numbers, the test environment allows you to login with reserved test numbers.
|
||||
Valid phone numbers follow the pattern ``99966XYYYY``, where ``X`` is the DC number (1 to 3) and ``YYYY`` are random
|
||||
numbers. Users with such numbers always get ``XXXXX`` as the confirmation code (the DC number, repeated five times).
|
||||
|
||||
.. important::
|
||||
|
||||
Do not store any important or private information in such test users' accounts; anyone can make use of the
|
||||
simplified authorization mechanism and login at any time.
|
@@ -1,5 +1,5 @@
|
||||
TgCrypto
|
||||
========
|
||||
Fast Crypto
|
||||
===========
|
||||
|
||||
Pyrogram's speed can be *dramatically* boosted up by TgCrypto_, a high-performance, easy-to-install Telegram Crypto
|
||||
Library specifically written in C for Pyrogram [#f1]_ as a Python extension.
|
||||
|
@@ -5,7 +5,8 @@ For a finer grained control over what kind of messages will be allowed or not in
|
||||
:class:`Filters <pyrogram.Filters>`.
|
||||
|
||||
.. note::
|
||||
This section makes use of Handlers to handle updates. Learn more at `Update Handling <UpdateHandling.html>`_.
|
||||
This page makes use of Handlers to show you how to handle updates.
|
||||
Learn more at `Update Handling <UpdateHandling.html>`_.
|
||||
|
||||
- This example will show you how to **only** handle messages containing an :obj:`Audio <pyrogram.Audio>` object and
|
||||
ignore any other message:
|
||||
@@ -99,45 +100,6 @@ More handlers using different filters can also live together.
|
||||
def from_pyrogramchat(client, message):
|
||||
print("New message in @PyrogramChat")
|
||||
|
||||
Handler Groups
|
||||
--------------
|
||||
|
||||
If you register handlers with overlapping filters, only the first one is executed and any other handler will be ignored.
|
||||
|
||||
In order to process the same message 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. This means that a lower group number has
|
||||
a higher priority.
|
||||
|
||||
For example, in:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
@app.on_message(Filters.text | Filters.sticker)
|
||||
def text_or_sticker(client, message):
|
||||
print("Text or Sticker")
|
||||
|
||||
|
||||
@app.on_message(Filters.text)
|
||||
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:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
@app.on_message(Filters.text, group=1)
|
||||
def just_text(client, message):
|
||||
print("Just Text")
|
||||
|
||||
or, if you want ``just_text`` to be fired *before* ``text_or_sticker`` (note ``-1``, which is less than ``0``):
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
@app.on_message(Filters.text, group=-1)
|
||||
def just_text(client, message):
|
||||
print("Just Text")
|
||||
|
||||
Custom Filters
|
||||
--------------
|
||||
|
||||
@@ -162,7 +124,7 @@ yourself. This allows you to test your filter by pressing the inline button:
|
||||
"username", # Change this to your username or id
|
||||
"Pyrogram's custom filter test",
|
||||
reply_markup=InlineKeyboardMarkup(
|
||||
[[InlineKeyboardButton("Press me", "pyrogram")]]
|
||||
[[InlineKeyboardButton("Press me", b"pyrogram")]]
|
||||
)
|
||||
)
|
||||
|
||||
@@ -178,7 +140,7 @@ containing "pyrogram" as data:
|
||||
|
||||
hardcoded_data = Filters.create(
|
||||
name="HardcodedData",
|
||||
func=lambda filter, callback_query: callback_query.data == "pyrogram"
|
||||
func=lambda filter, 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
|
||||
@@ -187,7 +149,7 @@ could be achieved with a normal function, but we don't really need it as it make
|
||||
.. code-block:: python
|
||||
|
||||
def func(filter, callback_query):
|
||||
return callback_query.data == "pyrogram"
|
||||
return callback_query.data == b"pyrogram"
|
||||
|
||||
hardcoded_data = Filters.create(
|
||||
name="HardcodedData",
|
||||
@@ -223,6 +185,6 @@ And its usage:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
@app.on_callback_query(dynamic_data("pyrogram"))
|
||||
@app.on_callback_query(dynamic_data(b"pyrogram"))
|
||||
def pyrogram_data(client, callback_query):
|
||||
client.answer_callback_query(callback_query.id, "it works!")
|
10
docs/source/resources/VoiceCalls.rst
Normal file
10
docs/source/resources/VoiceCalls.rst
Normal file
@@ -0,0 +1,10 @@
|
||||
Voice Calls
|
||||
===========
|
||||
|
||||
A working proof-of-concept of Telegram voice calls using Pyrogram can be found here:
|
||||
https://github.com/bakatrouble/pylibtgvoip. Thanks to `@bakatrouble <https://t.me/bakatrouble>`_.
|
||||
|
||||
.. note::
|
||||
|
||||
This page will be updated with more information once voice calls become eventually more usable and more integrated
|
||||
in Pyrogram itself.
|
@@ -18,23 +18,23 @@ Install Pyrogram
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
$ pip3 install --upgrade pyrogram
|
||||
$ pip3 install -U pyrogram
|
||||
|
||||
- or, with TgCrypto_ as extra requirement (recommended):
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
$ pip3 install --upgrade pyrogram[fast]
|
||||
$ pip3 install -U pyrogram[fast]
|
||||
|
||||
Bleeding Edge
|
||||
-------------
|
||||
|
||||
If you want the latest development version of Pyrogram, you can install it straight from the develop_
|
||||
branch using this command (you might need to install **git** first):
|
||||
branch using this command (note "develop.zip" in the link):
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
$ pip3 install --upgrade git+https://github.com/pyrogram/pyrogram.git
|
||||
$ pip3 install -U https://github.com/pyrogram/pyrogram/archive/develop.zip
|
||||
|
||||
Asynchronous
|
||||
------------
|
||||
@@ -43,11 +43,11 @@ Pyrogram heavily depends on IO-bound network code (it's a cloud-based messaging
|
||||
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).
|
||||
Use this command to install:
|
||||
Use this command to install (note "asyncio.zip" in the link):
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
$ pip3 install --upgrade git+https://github.com/pyrogram/pyrogram.git@asyncio
|
||||
$ pip3 install -U https://github.com/pyrogram/pyrogram/archive/asyncio.zip
|
||||
|
||||
|
||||
Pyrogram API remains the same and features are kept up to date from the non-async, default develop branch, but you
|
||||
@@ -82,7 +82,7 @@ If no error shows up you are good to go.
|
||||
|
||||
>>> import pyrogram
|
||||
>>> pyrogram.__version__
|
||||
'0.9.1'
|
||||
'0.12.0'
|
||||
|
||||
.. _TgCrypto: https://docs.pyrogram.ml/resources/TgCrypto
|
||||
.. _develop: http://github.com/pyrogram/pyrogram
|
||||
|
@@ -1,8 +1,7 @@
|
||||
Usage
|
||||
=====
|
||||
|
||||
Having your `project set up`_ and your account authorized_, it's time to play with the API.
|
||||
In this section, you'll be shown two ways of communicating with Telegram using Pyrogram. Let's start!
|
||||
Having your `project set up`_ and your account authorized_, it's time to play with the API. Let's start!
|
||||
|
||||
High-level API
|
||||
--------------
|
||||
@@ -43,79 +42,8 @@ exceptions in your code:
|
||||
|
||||
More examples on `GitHub <https://github.com/pyrogram/pyrogram/tree/develop/examples>`_.
|
||||
|
||||
Raw Functions
|
||||
-------------
|
||||
|
||||
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.
|
||||
|
||||
.. hint::
|
||||
|
||||
Every high-level method mentioned in the section above 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.
|
||||
|
||||
If you think a raw function should be wrapped and added as a high-level method, feel free to ask in our Community_!
|
||||
|
||||
Examples (more on `GitHub <https://github.com/pyrogram/pyrogram/tree/develop/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
|
||||
.. _plenty of them: ../pyrogram/Client.html#messages
|
||||
.. _types: ../pyrogram/Types.html
|
||||
.. _Raw Functions: Usage.html#using-raw-functions
|
||||
.. _Community: https://t.me/PyrogramChat
|
||||
.. _project set up: Setup.html
|
||||
.. _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
|
||||
.. _types: ../pyrogram/Types.html
|
Reference in New Issue
Block a user