2
0
mirror of https://github.com/pyrogram/pyrogram synced 2025-09-01 14:55:12 +00:00

Turn examples asynchronous

This commit is contained in:
Dan
2022-04-24 11:56:07 +02:00
parent ecc90caba2
commit b47591e6d2
151 changed files with 620 additions and 859 deletions

View File

@@ -89,7 +89,7 @@ Errors with Values
Exception objects may also contain some informative values. For example, ``FloodWait`` holds the amount of seconds you
have to wait before you can try again, some other errors contain the DC number on which the request must be repeated on.
The value is stored in the ``x`` attribute of the exception object:
The value is stored in the ``value`` attribute of the exception object:
.. code-block:: python
@@ -100,5 +100,5 @@ The value is stored in the ``x`` attribute of the exception object:
try:
... # Your code
except FloodWait as e:
await asyncio.sleep(e.x) # Wait "x" seconds before continuing
await asyncio.sleep(e.value) # Wait N seconds before continuing
...

View File

@@ -12,51 +12,57 @@ like send_audio(), send_document(), send_location(), etc...
.. code-block:: python
from pyrogram import Client
from pyrogram.types import ReplyKeyboardMarkup, InlineKeyboardMarkup, InlineKeyboardButton
from pyrogram.types import (ReplyKeyboardMarkup, InlineKeyboardMarkup,
InlineKeyboardButton)
# Create a client using your bot token
app = Client("my_bot", bot_token="123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11")
with app:
app.send_message(
"me", # Edit this
"This is a ReplyKeyboardMarkup example",
reply_markup=ReplyKeyboardMarkup(
[
["A", "B", "C", "D"], # First row
["E", "F", "G"], # Second row
["H", "I"], # Third row
["J"] # Fourth row
],
resize_keyboard=True # Make the keyboard smaller
)
)
app.send_message(
"me", # Edit this
"This is a InlineKeyboardMarkup example",
reply_markup=InlineKeyboardMarkup(
[
[ # First row
InlineKeyboardButton( # Generates a callback query when pressed
"Button",
callback_data="data"
),
InlineKeyboardButton( # Opens a web URL
"URL",
url="https://docs.pyrogram.org"
),
async def main():
async with app:
await app.send_message(
"me", # Edit this
"This is a ReplyKeyboardMarkup example",
reply_markup=ReplyKeyboardMarkup(
[
["A", "B", "C", "D"], # First row
["E", "F", "G"], # Second row
["H", "I"], # Third row
["J"] # Fourth row
],
[ # Second row
InlineKeyboardButton( # Opens the inline interface
"Choose chat",
switch_inline_query="pyrogram"
),
InlineKeyboardButton( # Opens the inline interface in the current chat
"Inline here",
switch_inline_query_current_chat="pyrogram"
)
]
]
resize_keyboard=True # Make the keyboard smaller
)
)
)
await app.send_message(
"me", # Edit this
"This is a InlineKeyboardMarkup example",
reply_markup=InlineKeyboardMarkup(
[
[ # First row
InlineKeyboardButton( # Generates a callback query when pressed
"Button",
callback_data="data"
),
InlineKeyboardButton( # Opens a web URL
"URL",
url="https://docs.pyrogram.org"
),
],
[ # Second row
InlineKeyboardButton( # Opens the inline interface
"Choose chat",
switch_inline_query="pyrogram"
),
InlineKeyboardButton( # Opens the inline interface in the current chat
"Inline here",
switch_inline_query_current_chat="pyrogram"
)
]
]
)
)
app.run(main())

View File

@@ -12,8 +12,10 @@ It uses the @on_callback_query decorator to register a CallbackQueryHandler.
@app.on_callback_query()
def answer(client, callback_query):
callback_query.answer(f"Button contains: '{callback_query.data}'", show_alert=True)
async def answer(client, callback_query):
await callback_query.answer(
f"Button contains: '{callback_query.data}'",
show_alert=True)
app.run() # Automatically start() and idle()

View File

@@ -1,5 +1,5 @@
echobot
=======
echo_bot
========
This simple echo bot replies to every private text message.
@@ -14,8 +14,8 @@ 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(message.text)
async def echo(client, message):
await message.reply(message.text)
app.run() # Automatically start() and idle()

View File

@@ -0,0 +1,20 @@
get_history
===========
This example shows how to get the full message history of a chat, starting from the latest message.
.. code-block:: python
from pyrogram import Client
app = Client("my_account")
async def main():
async with app:
# "me" refers to your own chat (Saved Messages)
async for message in app.get_chat_history("me"):
print(message)
app.run(main())

View File

@@ -7,9 +7,16 @@ This example shows how to get all the members of a chat.
from pyrogram import Client
app = Client("my_account")
target = "pyrogramchat" # Target channel/supergroup
# Target channel/supergroup
TARGET = -100123456789
with app:
for member in app.iter_chat_members(target):
print(member.user.first_name)
app = Client("my_account")
async def main():
async with app:
async for member in app.get_chat_members(TARGET):
print(member)
app.run(main())

View File

@@ -9,6 +9,11 @@ This example shows how to get the full dialogs list (as user).
app = Client("my_account")
with app:
for dialog in app.iter_dialogs():
print(dialog.chat.title or dialog.chat.first_name)
async def main():
async with app:
async for dialog in app.get_dialogs():
print(dialog.chat.title or dialog.chat.first_name)
app.run(main())

View File

@@ -1,15 +0,0 @@
get_history
===========
This example shows how to get the full message history of a chat, starting from the latest message.
.. code-block:: python
from pyrogram import Client
app = Client("my_account")
target = "me" # "me" refers to your own chat (Saved Messages)
with app:
for message in app.iter_history(target):
print(message.text)

View File

@@ -10,6 +10,11 @@ This example demonstrates a basic API usage
# Create a new Client instance
app = Client("my_account")
with app:
# Send a message, Markdown is enabled by default
app.send_message("me", "Hi there! I'm using **Pyrogram**")
async def main():
async with app:
# Send a message, Markdown is enabled by default
await app.send_message("me", "Hi there! I'm using **Pyrogram**")
app.run(main())

View File

@@ -17,9 +17,9 @@ to give you a basic idea.
:align: center
:doc:`hello_world`, "Demonstration of basic API usage"
:doc:`echobot`, "Echo every private text message"
:doc:`welcomebot`, "The Welcome Bot in @PyrogramChat"
:doc:`get_history`, "Get the full message history of a chat"
:doc:`echo_bot`, "Echo every private text message"
:doc:`welcome_bot`, "The Welcome Bot in @PyrogramChat"
:doc:`get_chat_history`, "Get the full message history of a chat"
:doc:`get_chat_members`, "Get all the members of a chat"
:doc:`get_dialogs`, "Get all of your dialog chats"
:doc:`callback_queries`, "Handle callback queries (as bot) coming from inline button presses"
@@ -34,9 +34,9 @@ For more advanced examples, see https://snippets.pyrogram.org.
:hidden:
hello_world
echobot
welcomebot
get_history
echo_bot
welcome_bot
get_chat_history
get_chat_members
get_dialogs
callback_queries

View File

@@ -16,8 +16,8 @@ It uses the @on_inline_query decorator to register an InlineQueryHandler.
@app.on_inline_query()
def answer(client, inline_query):
inline_query.answer(
async def answer(client, inline_query):
await inline_query.answer(
results=[
InlineQueryResultArticle(
title="Installation",

View File

@@ -11,7 +11,7 @@ This example shows how to handle raw updates.
@app.on_raw_update()
def raw(client, update, users, chats):
async def raw(client, update, users, chats):
print(update)

View File

@@ -10,9 +10,16 @@ This example shows how to query an inline bot (as user).
# Create a new Client
app = Client("my_account")
with app:
# 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)
async def main():
async with app:
# Get bot results for "hello" from the inline bot @vid
bot_results = await app.get_inline_bot_results("vid", "hello")
# Send the first result to your own chat (Saved Messages)
await app.send_inline_bot_result(
"me", bot_results.query_id,
bot_results.results[0].id)
app.run(main())

View File

@@ -1,5 +1,5 @@
welcomebot
==========
welcome_bot
===========
This example uses the ``emoji`` module to easily add emoji in your text messages and ``filters``
to make it only work for specific messages in a specific chat.
@@ -8,24 +8,23 @@ to make it only work for specific messages in a specific chat.
from pyrogram import Client, emoji, filters
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
# Target chat. Can also be a list of multiple chat ids/usernames
TARGET = -100123456789
# Welcome message template
MESSAGE = "{} Welcome to [Pyrogram](https://docs.pyrogram.org/)'s group chat {}!"
app = Client("my_account")
# Filter in only new_chat_members updates generated in TARGET chat
@app.on_message(filters.chat(TARGET) & filters.new_chat_members)
def welcome(client, message):
async def welcome(client, message):
# Build the new members list (with mentions) by using their first_name
new_members = [u.mention for u in message.new_chat_members]
# Build the welcome message by using an emoji and the list we built above
text = MESSAGE.format(emoji.SPARKLES, ", ".join(new_members))
# Send the welcome message, without the web page preview
message.reply_text(text, disable_web_page_preview=True)
await message.reply_text(text, disable_web_page_preview=True)
app.run() # Automatically start() and idle()

View File

@@ -1,5 +1,5 @@
Calling Methods
===============
Invoking 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 framework.
@@ -14,7 +14,7 @@ account; we are now aiming towards the core of the framework.
Basic Usage
-----------
Making API method calls with Pyrogram is very simple. Here's a basic example we are going to examine step by step:
Making API calls with Pyrogram is very simple. Here's a basic example we are going to examine step by step:
.. code-block:: python
@@ -43,7 +43,7 @@ Step-by-step
app = Client("my_account")
#. Async methods can't be executed at the top level, because they must be inside an async context.
#. Async methods must be invoked within 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.
@@ -101,24 +101,4 @@ be instantiated inside the main function.
async with app:
await app.send_message("me", "Hi!")
asyncio.run(main())
Synchronous Calls
------------------
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
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.
asyncio.run(main())

View File

@@ -1,8 +1,8 @@
Handling Updates
================
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.
:doc:`Invoking API methods <invoking>` sequentially is one way to use Pyrogram. This page deals with Telegram updates
and how to handle new incoming messages or other events in Pyrogram.
.. contents:: Contents
:backlinks: none
@@ -14,7 +14,7 @@ new message arrives? This page deals with updates and how to handle such events
Defining Updates
----------------
As hinted already, updates are simply events that happen in your Telegram account (incoming messages, new members join,
As hinted already, updates are 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>`.
@@ -52,25 +52,6 @@ In the last line we see again the :meth:`~pyrogram.Client.run` method, this time
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 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()
def my_handler(client, message):
message.forward("me")
.. note::
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()
^^^^^^^^^^^^^^^^^^^
@@ -91,16 +72,3 @@ function and registers it in your Client. It is useful in case you want to progr
app.add_handler(my_handler)
app.run()
The same about synchronous handlers applies for :meth:`~pyrogram.Client.add_handler`:
.. code-block:: python
def my_function(client, message):
message.forward("me")
.. note::
From now on, you'll see examples using synchronous code (i.e.: without ``async`` and ``await``, unless when actually
relevant). This is done to keep snippets concise and more readable. Once you get the idea behind a feature, you can
easily turn examples asynchronous later on.