mirror of
https://github.com/pyrogram/pyrogram
synced 2025-08-31 22:35:36 +00:00
Various improvements
This commit is contained in:
@@ -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::
|
||||
|
||||
|
@@ -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
|
||||
------------------
|
||||
|
||||
|
@@ -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(
|
||||
[
|
||||
|
@@ -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()
|
@@ -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")
|
@@ -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(
|
||||
|
@@ -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)
|
@@ -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
|
||||
|
||||
|
@@ -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.
|
@@ -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::
|
||||
|
||||
|
Reference in New Issue
Block a user