2
0
mirror of https://github.com/pyrogram/pyrogram synced 2025-08-31 06:16:06 +00:00

Deep rewrite: preparing for v1.0

- Pyrogram core is now fully asynchronous
- Ditched Python 3.5, welcome 3.6 as minimum version.
- Moved all types to pyrogram.types
- Turned the Filters class into a module (filters)
- Moved all filters to pyrogram.filters
- Moved all handlers to pyrogram.handlers
- Moved all emoji to pyrogram.emoji
- Renamed pyrogram.api to pyrogram.raw
- Clock is now synced with server's time
- Telegram schema updated to Layer 117
- Greatly improved the TL compiler (proper type-constructor hierarchy)
- Added "do not edit" warning in generated files
- Crypto parts are executed in a thread pool to avoid blocking the event loop
- idle() is now a separate function (it doesn't deal with Client instances)
- Async storage, async filters and async progress callback (optional, can be sync too)
- Added getpass back, for hidden password inputs
This commit is contained in:
Dan
2020-08-22 08:05:05 +02:00
parent 2f0a1f4119
commit 538f1e3972
367 changed files with 12085 additions and 15090 deletions

View File

@@ -10,6 +10,7 @@ Telegram API with its functions and types.
.. contents:: Contents
:backlinks: none
:depth: 1
:local:
-----
@@ -18,7 +19,7 @@ Telegram Raw API
----------------
If you can't find a high-level method for your needs or if you want complete, low-level access to the whole
Telegram API, you have to use the raw :mod:`~pyrogram.api.functions` and :mod:`~pyrogram.api.types`.
Telegram API, you have to use the raw :mod:`~pyrogram.raw.functions` and :mod:`~pyrogram.raw.types`.
As already hinted, raw functions and types can be really confusing, mainly because people don't realize soon enough they
accept *only* the right types and that all required parameters must be filled in. This section will therefore explain
@@ -41,7 +42,7 @@ Unlike the :doc:`methods <../api/methods/index>` found in Pyrogram's API, which
functions to be invoked from the raw Telegram API have a different way of usage and are more complex.
First of all, both :doc:`raw functions <../telegram/functions/index>` and :doc:`raw types <../telegram/types/index>`
live in their respective packages (and sub-packages): ``pyrogram.api.functions``, ``pyrogram.api.types``. They all exist
live in their respective packages (and sub-packages): ``pyrogram.raw.functions``, ``pyrogram.raw.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.
@@ -55,7 +56,7 @@ Here's some examples:
.. code-block:: python
from pyrogram import Client
from pyrogram.api import functions
from pyrogram.raw import functions
with Client("my_account") as app:
app.send(
@@ -70,7 +71,7 @@ Here's some examples:
.. code-block:: python
from pyrogram import Client
from pyrogram.api import functions, types
from pyrogram.raw import functions, types
with Client("my_account") as app:
app.send(
@@ -85,7 +86,7 @@ Here's some examples:
.. code-block:: python
from pyrogram import Client
from pyrogram.api import functions, types
from pyrogram.raw import functions, types
with Client("my_account") as app:
app.send(
@@ -109,9 +110,9 @@ sending messages with IDs only thanks to cached access hashes.
There are three different InputPeer types, one for each kind of Telegram entity.
Whenever an InputPeer is needed you must pass one of these:
- :class:`~pyrogram.api.types.InputPeerUser` - Users
- :class:`~pyrogram.api.types.InputPeerChat` - Basic Chats
- :class:`~pyrogram.api.types.InputPeerChannel` - Either Channels or Supergroups
- :class:`~pyrogram.raw.types.InputPeerUser` - Users
- :class:`~pyrogram.raw.types.InputPeerChat` - Basic Chats
- :class:`~pyrogram.raw.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:`~pyrogram.Client.resolve_peer` as a convenience utility method that returns the correct InputPeer

View File

@@ -5,6 +5,7 @@ Users can interact with other bots via plain text messages as well as inline que
.. contents:: Contents
:backlinks: none
:depth: 1
:local:
-----

View File

@@ -6,6 +6,7 @@ This page explains how this file is structured, how to use it and why.
.. contents:: Contents
:backlinks: none
:depth: 1
:local:
-----

View File

@@ -1,16 +1,12 @@
Creating Filters
================
Pyrogram already provides lots of built-in :class:`~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 kind of handler,
for example) you can use :meth:`~pyrogram.Filters.create`.
.. note::
At the moment, the built-in filters are intended to be used with the :class:`~pyrogram.MessageHandler` only.
Pyrogram already provides lots of built-in :class:`~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 you can use :meth:`~pyrogram.filters.create`.
.. contents:: Contents
:backlinks: none
:depth: 1
:local:
-----
@@ -19,14 +15,14 @@ Custom Filters
--------------
An example to demonstrate how custom filters work is to show how to create and use one for the
:class:`~pyrogram.CallbackQueryHandler`. Note that callback queries updates are only received by bots as result of a
user pressing an inline button attached to the bot's message; create and :doc:`authorize your bot <../start/auth>`,
:class:`~pyrogram.handlers.CallbackQueryHandler`. Note that callback queries updates are only received by bots as result
of a user pressing an inline button attached to the bot's message; create and :doc:`authorize your bot <../start/auth>`,
then send a message with an inline keyboard to yourself. This allows you to test your filter by pressing the inline
button:
.. code-block:: python
from pyrogram import InlineKeyboardMarkup, InlineKeyboardButton
from pyrogram.types import InlineKeyboardMarkup, InlineKeyboardButton
app.send_message(
"username", # Change this to your username or id
@@ -39,7 +35,7 @@ button:
Basic Filters
-------------
For this basic filter we will be using only the first parameter of :meth:`~pyrogram.Filters.create`.
For this basic filter we will be using only the first parameter of :meth:`~pyrogram.filters.create`.
The code below creates a simple filter for hardcoded, static callback data. This filter will only allow callback queries
containing "pyrogram" as data, that is, the function *func* you pass returns True in case the callback query data
@@ -47,17 +43,21 @@ equals to ``"pyrogram"``.
.. code-block:: python
static_data_filter = Filters.create(lambda _, query: query.data == "pyrogram")
from pyrogram import filters
static_data_filter = filters.create(lambda _, query: query.data == "pyrogram")
The ``lambda`` operator in python is used to create small anonymous functions and is perfect for this example, the same
could be achieved with a normal function, but we don't really need it as it makes sense only inside the filter scope:
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
from pyrogram import filters
def func(_, query):
return query.data == "pyrogram"
static_data_filter = Filters.create(func)
static_data_filter = filters.create(func)
The filter usage remains the same:
@@ -71,14 +71,16 @@ Filters with Arguments
----------------------
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 named arguments for the :meth:`~pyrogram.Filters.create` method.
A dynamic filter like this will make use of named arguments for the :meth:`~pyrogram.filters.create` method.
This is how a dynamic custom filter looks like:
.. code-block:: python
from pyrogram import filters
def dynamic_data_filter(data):
return Filters.create(
return filters.create(
lambda flt, query: flt.data == query.data,
data=data # "data" kwarg is accessed with "flt.data" above
)

View File

@@ -6,6 +6,7 @@ to actually worry about -- that's normal -- and luckily for you, Pyrogram provid
.. contents:: Contents
:backlinks: none
:depth: 1
:local:
-----

View File

@@ -6,6 +6,7 @@ Here we'll show some advanced usages when working with :doc:`update handlers <..
.. contents:: Contents
:backlinks: none
:depth: 1
:local:
-----
@@ -25,21 +26,21 @@ For example, take these two handlers:
.. 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):
print("Text or Sticker")
@app.on_message(Filters.text)
@app.on_message(filters.text)
def just_text(client, message):
print("Just Text")
Here, ``just_text`` is never executed because ``text_or_sticker``, which has been registered first, already handles
texts (``Filters.text`` is shared and conflicting). To enable it, register the handler using a different group:
texts (``filters.text`` is shared and conflicting). To enable it, register the handler using a different group:
.. code-block:: python
@app.on_message(Filters.text, group=1)
@app.on_message(filters.text, group=1)
def just_text(client, message):
print("Just Text")
@@ -47,7 +48,7 @@ Or, if you want ``just_text`` to be executed *before* ``text_or_sticker`` (note
.. code-block:: python
@app.on_message(Filters.text, group=-1)
@app.on_message(filters.text, group=-1)
def just_text(client, message):
print("Just Text")
@@ -55,7 +56,7 @@ With :meth:`~pyrogram.Client.add_handler` (without decorators) the same can be a
.. code-block:: python
app.add_handler(MessageHandler(just_text, Filters.text), -1)
app.add_handler(MessageHandler(just_text, filters.text), -1)
Update propagation
------------------
@@ -67,17 +68,17 @@ continue to propagate the same update to the next groups until all the handlers
.. code-block:: python
@app.on_message(Filters.private)
@app.on_message(filters.private)
def _(client, message):
print(0)
@app.on_message(Filters.private, group=1)
@app.on_message(filters.private, group=1)
def _(client, message):
raise Exception("Unhandled exception!") # Simulate an unhandled exception
@app.on_message(Filters.private, group=2)
@app.on_message(filters.private, group=2)
def _(client, message):
print(2)
@@ -109,18 +110,18 @@ Example with ``stop_propagation()``:
.. code-block:: python
@app.on_message(Filters.private)
@app.on_message(filters.private)
def _(client, message):
print(0)
@app.on_message(Filters.private, group=1)
@app.on_message(filters.private, group=1)
def _(client, message):
print(1)
message.stop_propagation()
@app.on_message(Filters.private, group=2)
@app.on_message(filters.private, group=2)
def _(client, message):
print(2)
@@ -130,18 +131,18 @@ Example with ``raise StopPropagation``:
from pyrogram import StopPropagation
@app.on_message(Filters.private)
@app.on_message(filters.private)
def _(client, message):
print(0)
@app.on_message(Filters.private, group=1)
@app.on_message(filters.private, group=1)
def _(client, message):
print(1)
raise StopPropagation
@app.on_message(Filters.private, group=2)
@app.on_message(filters.private, group=2)
def _(client, message):
print(2)
@@ -177,19 +178,19 @@ Example with ``continue_propagation()``:
.. code-block:: python
@app.on_message(Filters.private)
@app.on_message(filters.private)
def _(client, message):
print(0)
message.continue_propagation()
@app.on_message(Filters.private)
@app.on_message(filters.private)
def _(client, message):
print(1)
message.continue_propagation()
@app.on_message(Filters.private)
@app.on_message(filters.private)
def _(client, message):
print(2)
@@ -199,19 +200,19 @@ Example with ``raise ContinuePropagation``:
from pyrogram import ContinuePropagation
@app.on_message(Filters.private)
@app.on_message(filters.private)
def _(client, message):
print(0)
raise ContinuePropagation
@app.on_message(Filters.private)
@app.on_message(filters.private)
def _(client, message):
print(1)
raise ContinuePropagation
@app.on_message(Filters.private)
@app.on_message(filters.private)
def _(client, message):
print(2)

View File

@@ -8,6 +8,7 @@ actually is the MTProto and the Bot API.
.. contents:: Contents
:backlinks: none
:depth: 1
:local:
-----

View File

@@ -6,6 +6,7 @@ through an intermediate SOCKS5 proxy server.
.. contents:: Contents
:backlinks: none
:depth: 1
:local:
-----

View File

@@ -10,6 +10,7 @@ visit and learn from each library documentation.
.. contents:: Contents
:backlinks: none
:depth: 1
:local:
-----
@@ -69,8 +70,7 @@ Using ``apscheduler``
scheduler.start()
app.run()
``apscheduler`` does also support async code, here's an example with
`Pyrogram Asyncio <https://docs.pyrogram.org/intro/install.html#asynchronous>`_:
``apscheduler`` does also support async code, here's an example:
.. code-block:: python

View File

@@ -7,6 +7,7 @@ humans and another more compact for machines that is able to recover the origina
.. contents:: Contents
:backlinks: none
:depth: 1
:local:
-----

View File

@@ -22,6 +22,7 @@ That's how a session looks like on the Android app, showing the three main piece
.. contents:: Contents
:backlinks: none
:depth: 1
:local:
-----

View File

@@ -11,6 +11,7 @@ different Pyrogram applications with **minimal boilerplate code**.
.. contents:: Contents
:backlinks: none
:depth: 1
:local:
-----
@@ -51,7 +52,8 @@ after importing your modules, like this:
.. code-block:: python
from pyrogram import Client, MessageHandler, Filters
from pyrogram import Client, filters
from pyrogram.handlers import MessageHandler
from handlers import echo, echo_reversed
@@ -60,19 +62,19 @@ after importing your modules, like this:
app.add_handler(
MessageHandler(
echo,
Filters.text & Filters.private))
filters.text & filters.private))
app.add_handler(
MessageHandler(
echo_reversed,
Filters.text & Filters.private),
filters.text & filters.private),
group=1)
app.run()
This is already nice and doesn't add *too much* boilerplate code, but things can get boring still; you have to
manually ``import``, manually :meth:`~pyrogram.Client.add_handler` and manually instantiate each
:class:`~pyrogram.MessageHandler` object because **you can't use those cool decorators** for your
:class:`~pyrogram.handlers.MessageHandler` object because **you can't use those cool decorators** for your
functions. So, what if you could? Smart Plugins solve this issue by taking care of handlers registration automatically.
Using Smart Plugins
@@ -102,15 +104,15 @@ Setting up your Pyrogram project to accommodate Smart Plugins is pretty straight
.. code-block:: python
:emphasize-lines: 4, 9
from pyrogram import Client, Filters
from pyrogram import Client, filters
@Client.on_message(Filters.text & Filters.private)
@Client.on_message(filters.text & filters.private)
def echo(client, message):
message.reply(message.text)
@Client.on_message(Filters.text & Filters.private, group=1)
@Client.on_message(filters.text & filters.private, group=1)
def echo_reversed(client, message):
message.reply(message.text[::-1])
@@ -306,7 +308,7 @@ updates) will be modified in such a way that a special ``handler`` attribute poi
.. code-block:: python
:emphasize-lines: 5, 6
@Client.on_message(Filters.text & Filters.private)
@Client.on_message(filters.text & filters.private)
def echo(client, message):
message.reply(message.text)

View File

@@ -7,6 +7,7 @@ decide to manually terminate it) and is used to authorize a client to execute AP
.. contents:: Contents
:backlinks: none
:depth: 1
:local:
-----

View File

@@ -20,6 +20,7 @@ Telegram's test servers without hassle. All you need to do is start a new sessio
.. contents:: Contents
:backlinks: none
:depth: 1
:local:
-----

View File

@@ -19,6 +19,7 @@ variety of decorations that can also be nested in order to combine multiple styl
.. contents:: Contents
:backlinks: none
:depth: 1
:local:
-----

View File

@@ -1,14 +1,15 @@
Using Filters
=============
So far we've seen :doc:`how to register a callback function <../start/updates>` that executes every time a specific update
comes from the server, but there's much more than that to come.
So far we've seen :doc:`how to register a callback function <../start/updates>` that executes every time an update comes
from the server, but there's much more than that to come.
Here we'll discuss about :class:`~pyrogram.Filters`. Filters enable a fine-grain control over what kind of
Here we'll discuss about :obj:`~pyrogram.filters`. Filters enable a fine-grain control over what kind of
updates are allowed or not to be passed in your callback functions, based on their inner details.
.. contents:: Contents
:backlinks: none
:depth: 1
:local:
-----
@@ -24,10 +25,10 @@ Let's start right away with a simple example:
.. code-block:: python
:emphasize-lines: 4
from pyrogram import Filters
from pyrogram import filters
@app.on_message(Filters.audio)
@app.on_message(filters.audio)
def my_handler(client, message):
print(message)
@@ -35,16 +36,17 @@ Let's start right away with a simple example:
callback function itself:
.. code-block:: python
:emphasize-lines: 8
:emphasize-lines: 9
from pyrogram import Filters, MessageHandler
from pyrogram import filters
from pyrogram.handlers import MessageHandler
def my_handler(client, message):
print(message)
app.add_handler(MessageHandler(my_handler, Filters.audio))
app.add_handler(MessageHandler(my_handler, filters.audio))
Combining Filters
-----------------
@@ -61,7 +63,7 @@ Here are some examples:
.. code-block:: python
@app.on_message(Filters.text & ~Filters.edited)
@app.on_message(filters.text & ~filters.edited)
def my_handler(client, message):
print(message)
@@ -69,21 +71,21 @@ Here are some examples:
.. code-block:: python
@app.on_message(Filters.sticker & (Filters.channel | Filters.private))
@app.on_message(filters.sticker & (filters.channel | filters.private))
def my_handler(client, message):
print(message)
Advanced Filters
----------------
Some filters, like :meth:`~pyrogram.Filters.command` or :meth:`~pyrogram.Filters.regex`
Some filters, like :meth:`~pyrogram.filters.command` or :meth:`~pyrogram.filters.regex`
can also accept arguments:
- Message is either a */start* or */help* **command**.
.. code-block:: python
@app.on_message(Filters.command(["start", "help"]))
@app.on_message(filters.command(["start", "help"]))
def my_handler(client, message):
print(message)
@@ -91,7 +93,7 @@ can also accept arguments:
.. code-block:: python
@app.on_message(Filters.regex("pyrogram"))
@app.on_message(filters.regex("pyrogram"))
def my_handler(client, message):
print(message)
@@ -99,16 +101,16 @@ More handlers using different filters can also live together.
.. code-block:: python
@app.on_message(Filters.command("start"))
@app.on_message(filters.command("start"))
def start_command(client, message):
print("This is the /start command")
@app.on_message(Filters.command("help"))
@app.on_message(filters.command("help"))
def help_command(client, message):
print("This is the /help command")
@app.on_message(Filters.chat("PyrogramChat"))
@app.on_message(filters.chat("PyrogramChat"))
def from_pyrogramchat(client, message):
print("New message in @PyrogramChat")