2
0
mirror of https://github.com/pyrogram/pyrogram synced 2025-08-31 22:35:36 +00:00

Various improvements

This commit is contained in:
Dan
2022-01-07 10:18:51 +01:00
parent 80d0966691
commit 8c8288412f
135 changed files with 842 additions and 1422 deletions

View File

@@ -26,23 +26,20 @@ the :meth:`~pyrogram.Client.run` method:
app = Client("my_account")
app.run()
This starts an interactive shell asking you to input your **phone number** (including your `Country Code`_) and the
**phone code** you will receive in your devices that are already authorized or via SMS:
This starts an interactive shell asking you to input your **phone number**, including your `Country Code`_ (the plus
``+`` and minus ``-`` symbols can be omitted) and the **phone code** you will receive in your devices that are already
authorized or via SMS:
.. code-block:: text
Enter phone number: +39**********
Is "+39**********" correct? (y/n): y
Enter phone code: 32768
Logged in successfully as Dan
Enter phone number: +1-123-456-7890
Is "+1-123-456-7890" correct? (y/n): y
Enter phone code: 12345
Logged in successfully
After successfully authorizing yourself, a new file called ``my_account.session`` will be created allowing Pyrogram to
execute API calls with your identity. This file will be loaded again when you restart your app, and as long as you
keep the session alive, Pyrogram won't ask you again to enter your phone number.
.. important::
Your ``*.session`` file is personal and must be kept secret.
execute API calls with your identity. This file is personal and will be loaded again when you restart your app, and as
long as you keep the session alive, Pyrogram won't ask you again to enter your phone number.
.. note::

View File

@@ -1,8 +1,8 @@
Error Handling
==============
Errors are inevitable when working with the API, and they can be correctly handled with ``try...except`` blocks in order
to control the behaviour of your application. Pyrogram errors all live inside the ``errors`` package:
Errors can be correctly handled with ``try...except`` blocks in order to control the behaviour of your application.
Pyrogram errors all live inside the ``errors`` package:
.. code-block:: python
@@ -25,10 +25,10 @@ This error is raised every time a method call against Telegram's API was unsucce
from pyrogram.errors import RPCError
.. warning::
.. note::
It must be noted that catching this error is bad practice, especially when no feedback is given (i.e. by
logging/printing the full error traceback), because it makes it impossible to understand what went wrong.
Avoid catching this error everywhere, especially when no feedback is given (i.e. by logging/printing the full error
traceback), because it makes it impossible to understand what went wrong.
Error Categories
----------------
@@ -84,9 +84,6 @@ whole category of errors and be sure to also handle these unknown errors.
In case a whole class of errors is unknown (that is, an error code that is unknown), Pyrogram will raise a special
``520 UnknownError`` exception.
In both cases, Pyrogram will log them in the ``unknown_errors.txt`` file. Users are invited to report
these unknown errors in the `discussion group <https://t.me/pyrogram>`_.
Errors with Values
------------------

View File

@@ -19,7 +19,7 @@ like send_audio(), send_document(), send_location(), etc...
with app:
app.send_message(
"haskell", # Edit this
"me", # Edit this
"This is a ReplyKeyboardMarkup example",
reply_markup=ReplyKeyboardMarkup(
[
@@ -33,7 +33,7 @@ like send_audio(), send_document(), send_location(), etc...
)
app.send_message(
"haskell", # Edit this
"me", # Edit this
"This is a InlineKeyboardMarkup example",
reply_markup=InlineKeyboardMarkup(
[

View File

@@ -15,7 +15,7 @@ It uses the ``@on_message`` decorator to register a ``MessageHandler`` and appli
@app.on_message(filters.text & filters.private)
def echo(client, message):
message.reply_text(message.text)
message.reply(message.text)
app.run() # Automatically start() and idle()

View File

@@ -13,9 +13,3 @@ This example demonstrates a basic API usage
with app:
# Send a message, Markdown is enabled by default
app.send_message("me", "Hi there! I'm using **Pyrogram**")
# Send a location
app.send_location("me", 51.500729, -0.124583)
# Send a sticker
app.send_sticker("me", "CAADBAADzg4AAvLQYAEz_x2EOgdRwBYE")

View File

@@ -26,7 +26,6 @@ It uses the @on_inline_query decorator to register an InlineQueryHandler.
),
url="https://docs.pyrogram.org/intro/install",
description="How to install Pyrogram",
thumb_url="https://i.imgur.com/JyxrStE.png",
reply_markup=InlineKeyboardMarkup(
[
[InlineKeyboardButton(
@@ -43,7 +42,6 @@ It uses the @on_inline_query decorator to register an InlineQueryHandler.
),
url="https://docs.pyrogram.org/start/invoking",
description="How to use Pyrogram",
thumb_url="https://i.imgur.com/JyxrStE.png",
reply_markup=InlineKeyboardMarkup(
[
[InlineKeyboardButton(

View File

@@ -11,8 +11,8 @@ This example shows how to query an inline bot (as user).
app = Client("my_account")
with app:
# Get bot results for "Fuzz Universe" from the inline bot @vid
bot_results = app.get_inline_bot_results("vid", "Fuzz Universe")
# Get bot results for "hello" from the inline bot @vid
bot_results = app.get_inline_bot_results("vid", "hello")
# Send the first result (bot_results.results[0]) to your own chat (Saved Messages)
app.send_inline_bot_result("me", bot_results.query_id, bot_results.results[0].id)

View File

@@ -8,7 +8,7 @@ to make it only work for specific messages in a specific chat.
from pyrogram import Client, emoji, filters
TARGET = "PyrogramChat" # Target chat. Can also be a list of multiple chat ids/usernames
TARGET = -100123456789 # Target chat. Can also be a list of multiple chat ids/usernames
MENTION = "[{}](tg://user?id={})" # User mention markup
MESSAGE = "{} Welcome to [Pyrogram](https://docs.pyrogram.org/)'s group chat {}!" # Welcome message

View File

@@ -2,7 +2,7 @@ Calling Methods
===============
At this point, we have successfully :doc:`installed Pyrogram <../intro/install>` and :doc:`authorized <auth>` our
account; we are now aiming towards the core of the library. It's time to start playing with the API!
account; we are now aiming towards the core of the framework.
.. contents:: Contents
:backlinks: none
@@ -22,60 +22,53 @@ Making API method calls with Pyrogram is very simple. Here's a basic example we
app = Client("my_account")
with app:
app.send_message("me", "Hi!")
async def main():
async with app:
await app.send_message("me", "Hi!")
Basic step-by-step
^^^^^^^^^^^^^^^^^^
app.run(main())
#. Let's begin by importing the Client class:
Step-by-step
^^^^^^^^^^^^
#. Let's begin by importing the Client class.
.. code-block:: python
from pyrogram import Client
#. Now instantiate a new Client object, "my_account" is a session name of your choice:
#. Now instantiate a new Client object, "my_account" is a session name of your choice.
.. code-block:: python
app = Client("my_account")
#. The ``with`` context manager is a shortcut for starting, executing and stopping the Client:
#. Async methods can't be executed at the top level, because they must be inside an async context.
Here we define an async function and put our code inside. Also notice the ``await`` keyword in front of the method
call; this is required for all asynchronous methods.
.. code-block:: python
with app:
async def main():
async with app:
await app.send_message("me", "Hi!")
#. Now, you can call any method you like:
#. Finally, we tell Python to schedule our ``main()`` async function by using Pyrogram's :meth:`~pyrogram.Client.run`
method.
.. code-block:: python
app.send_message("me", "Hi!")
app.run(main())
Context Manager
---------------
The ``with`` statement starts a context manager used as a shortcut to automatically call :meth:`~pyrogram.Client.start`
and :meth:`~pyrogram.Client.stop`, which are methods required for Pyrogram to work properly. The context manager does
also gracefully stop the client, even in case of unhandled exceptions in your code.
The ``async with`` statement starts a context manager, which is used as a shortcut for starting, executing and stopping
the Client, asynchronously. It does so by automatically calling :meth:`~pyrogram.Client.start` and
:meth:`~pyrogram.Client.stop` in a more convenient way which also gracefully stops the client, even in case of
unhandled exceptions in your code.
This is how Pyrogram looks without the context manager:
.. code-block:: python
from pyrogram import Client
app = Client("my_account")
app.start()
app.send_message("me", "Hi!")
app.stop()
Asynchronous Calls
------------------
In case you want Pyrogram to run asynchronously (e.g.: if you are using third party libraries that require you to call
them with ``await``), use the asynchronous context manager:
Below there's the same example as above, but without the use of the context manager:
.. code-block:: python
@@ -84,36 +77,48 @@ them with ``await``), use the asynchronous context manager:
app = Client("my_account")
async def main():
async with app:
await app.send_message("me", "Hi!")
await app.start()
await app.send_message("me", "Hi!")
await app.stop()
app.run(main())
Asynchronous step-by-step
^^^^^^^^^^^^^^^^^^^^^^^^^
Using asyncio.run()
-------------------
#. Import the Client class and create an instance:
Alternatively to the :meth:`~pyrogram.Client.run` method, you can use Python's ``asyncio.run()`` to execute the main
function, with one little caveat: the Client instance (and possibly other asyncio resources you are going to use) must
be instantiated inside the main function.
.. code-block:: python
.. code-block:: python
from pyrogram import Client
import asyncio
from pyrogram import Client
async def main():
app = Client("my_account")
#. Async methods can't normally be executed at the top level, because they must be inside an async-defined function;
here we define one and put our code inside; the context manager is also being used differently in asyncio and
method calls require the await keyword:
async with app:
await app.send_message("me", "Hi!")
.. code-block:: python
asyncio.run(main())
async def main():
async with app:
await app.send_message("me", "Hi!")
Synchronous Calls
------------------
#. Finally, we tell Python to schedule our ``main()`` async function, which in turn will execute Pyrogram's methods.
Using :meth:`~pyrogram.Client.run` this way is a friendly alternative for the much more verbose
``asyncio.get_event_loop().run_until_complete(main())``:
Pyrogram is an asynchronous framework, but it also provides a convenience way for calling methods without the need
of async/await keywords and the extra boilerplate. In case you want Pyrogram to run synchronously, simply use the
synchronous context manager:
.. code-block:: python
.. code-block:: python
app.run(main())
from pyrogram import Client
app = Client("my_account")
with app:
app.send_message("me", "Hi!")
As you can see, the non-async example becomes less cluttered. Use Pyrogram in this non-asynchronous way only when you
want to write something without the boilerplate or in case you want to combine Pyrogram with other libraries that are
not async.

View File

@@ -1,8 +1,8 @@
Handling Updates
================
Calling :doc:`API methods <invoking>` sequentially is cool, but how to react when, for example, a new message arrives?
This page deals with updates and how to handle such events in Pyrogram. Let's have a look at how they work.
Calling :doc:`API methods <invoking>` sequentially is one way to use Pyrogram, but how to react when, for example, a
new message arrives? This page deals with updates and how to handle such events in Pyrogram.
.. contents:: Contents
:backlinks: none
@@ -14,10 +14,9 @@ This page deals with updates and how to handle such events in Pyrogram. Let's ha
Defining Updates
----------------
First, let's define what are these updates. As hinted already, updates are simply events that happen in your Telegram
account (incoming messages, new members join, bot button presses, etc...), which are meant to notify you about a new
specific state that has changed. These updates are handled by registering one or more callback functions in your app
using :doc:`Handlers <../api/handlers>`.
As hinted already, updates are simply events that happen in your Telegram account (incoming messages, new members join,
bot button presses, etc.), which are meant to notify you about a new specific state that has changed. These updates are
handled by registering one or more callback functions in your app using :doc:`Handlers <../api/handlers>`.
Each handler deals with a specific event and once a matching update arrives from Telegram, your registered callback
function will be called back by the framework and its body executed.
@@ -40,50 +39,51 @@ The most elegant way to register a message handler is by using the :meth:`~pyrog
app = Client("my_account")
@app.on_message()
def my_handler(client, message):
message.forward("me")
async def my_handler(client, message):
await message.forward("me")
app.run()
The defined function ``my_handler``, which accepts the two arguments *(client, message)*, will be the function that gets
executed every time a new message arrives.
Asynchronous handlers
In the last line we see again the :meth:`~pyrogram.Client.run` method, this time used without any argument.
Its purpose here is simply to automatically :meth:`~pyrogram.Client.start`, keep the Client online so that it can listen
for updates and :meth:`~pyrogram.Client.stop` it once you hit ``CTRL+C``.
Synchronous handlers
^^^^^^^^^^^^^^^^^^^^^
You can also have asynchronous handlers; you only need to define the callback function using ``async def`` and call API
methods by placing ``await`` in front of them:
You can also have synchronous handlers; you only need to define the callback function without using ``async def`` and
call API methods by not placing ``await`` in front of them:
.. code-block:: python
@app.on_message()
async def my_handler(client, message):
await message.forward("me")
def my_handler(client, message):
message.forward("me")
.. note::
You can mix ``def`` and ``async def`` handlers as much as you need, Pyrogram will still work concurrently and
efficiently regardless of what you choose.
You can mix ``def`` and ``async def`` handlers as much as you like, Pyrogram will still work concurrently and
efficiently regardless of what you choose. However, it is recommended to use Pyrogram in its native, asynchronous
form at all times, unless you want to write something without the boilerplate or in case you want to combine
Pyrogram with other libraries that are not async.
Using add_handler()
^^^^^^^^^^^^^^^^^^^
The :meth:`~pyrogram.Client.add_handler` method takes any handler instance that wraps around your defined callback
function and registers it in your Client. It is useful in case you want to programmatically add handlers (or in case,
for some reason, you don't like to use decorators).
function and registers it in your Client. It is useful in case you want to programmatically add handlers.
.. code-block:: python
from pyrogram import Client
from pyrogram.handlers import MessageHandler
def my_function(client, message):
message.forward("me")
async def my_function(client, message):
await message.forward("me")
app = Client("my_account")
@@ -92,12 +92,12 @@ for some reason, you don't like to use decorators).
app.run()
The same about asynchronous handlers applies for :meth:`~pyrogram.Client.add_handler`:
The same about synchronous handlers applies for :meth:`~pyrogram.Client.add_handler`:
.. code-block:: python
async def my_function(client, message):
await message.forward("me")
def my_function(client, message):
message.forward("me")
.. note::