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

@ -534,7 +534,6 @@ def pyrogram_api():
Chat.promote_member
Chat.get_member
Chat.get_members
Chat.iter_members
Chat.add_members
Chat.join
Chat.leave

View File

@ -20,4 +20,6 @@ help:
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
lhtml: # live html
sphinx-autobuild --host $(shell ifconfig | grep "inet " | grep -v 127.0.0.1 | cut -d\ -f2) -b html "$(SOURCEDIR)" "$(BUILDDIR)/html" $(SPHINXOPTS)
sphinx-autobuild --host $(shell ifconfig | grep "inet " | grep -v 127.0.0.1 | cut -d\ -f2) \
--watch ../pyrogram \
-b html "$(SOURCEDIR)" "$(BUILDDIR)/html" $(SPHINXOPTS)

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.
@ -102,23 +102,3 @@ be instantiated inside the main function.
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.

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.

View File

@ -35,15 +35,8 @@ class ContinuePropagation(StopAsyncIteration):
pass
import asyncio
from . import raw, types, filters, handlers, emoji, enums
from .client import Client
from .sync import idle
# Save the main thread loop for future references
main_event_loop = asyncio.get_event_loop()
CRYPTO_EXECUTOR_SIZE_THRESHOLD = 512
crypto_executor = ThreadPoolExecutor(1, thread_name_prefix="CryptoWorker")

View File

@ -452,29 +452,26 @@ class Client(Methods):
Example:
.. code-block:: python
from pyrogram import Client, enums
from pyrogram import enums
app = Client("my_account")
# Default combined mode: Markdown + HTML
await app.send_message("me", "1. **markdown** and <i>html</i>")
with app:
# Default combined mode: Markdown + HTML
app.send_message("me", "1. **markdown** and <i>html</i>")
# Force Markdown-only, HTML is disabled
app.set_parse_mode(enums.ParseMode.MARKDOWN)
await app.send_message("me", "2. **markdown** and <i>html</i>")
# Force Markdown-only, HTML is disabled
app.set_parse_mode(enums.ParseMode.MARKDOWN)
app.send_message("me", "2. **markdown** and <i>html</i>")
# Force HTML-only, Markdown is disabled
app.set_parse_mode(enums.ParseMode.HTML)
await app.send_message("me", "3. **markdown** and <i>html</i>")
# Force HTML-only, Markdown is disabled
app.set_parse_mode(enums.ParseMode.HTML)
app.send_message("me", "3. **markdown** and <i>html</i>")
# Disable the parser completely
app.set_parse_mode(enums.ParseMode.DISABLED)
await app.send_message("me", "4. **markdown** and <i>html</i>")
# Disable the parser completely
app.set_parse_mode(enums.ParseMode.DISABLED)
app.send_message("me", "4. **markdown** and <i>html</i>")
# Bring back the default combined mode
app.set_parse_mode(enums.ParseMode.DEFAULT)
app.send_message("me", "5. **markdown** and <i>html</i>")
# Bring back the default combined mode
app.set_parse_mode(enums.ParseMode.DEFAULT)
await app.send_message("me", "5. **markdown** and <i>html</i>")
"""
self.parse_mode = parse_mode

View File

@ -60,13 +60,13 @@ class AnswerCallbackQuery:
.. code-block:: python
# Answer only (remove the spinning circles)
app.answer_callback_query(query_id)
await app.answer_callback_query(query_id)
# Answer without alert
app.answer_callback_query(query_id, text=text)
await app.answer_callback_query(query_id, text=text)
# Answer with alert
app.answer_callback_query(query_id, text=text, show_alert=True)
await app.answer_callback_query(query_id, text=text, show_alert=True)
"""
return await self.invoke(
raw.functions.messages.SetBotCallbackAnswer(

View File

@ -86,7 +86,7 @@ class AnswerInlineQuery:
from pyrogram.types import InlineQueryResultArticle, InputTextMessageContent
app.answer_inline_query(
await app.answer_inline_query(
inline_query_id,
results=[
InlineQueryResultArticle(

View File

@ -49,7 +49,7 @@ class DeleteBotCommands:
.. code-block:: python
# Delete commands
app.delete_bot_commands()
await app.delete_bot_commands()
"""
return await self.invoke(

View File

@ -51,7 +51,7 @@ class GetBotCommands:
.. code-block:: python
# Get commands
commands = app.get_bot_commands()
commands = await app.get_bot_commands()
print(commands)
"""

View File

@ -54,7 +54,7 @@ class GetGameHighScores:
Example:
.. code-block:: python
scores = app.get_game_high_scores(user_id, chat_id, message_id)
scores = await app.get_game_high_scores(user_id, chat_id, message_id)
print(scores)
"""
# TODO: inline_message_id

View File

@ -64,7 +64,7 @@ class GetInlineBotResults:
Example:
.. code-block:: python
results = app.get_inline_bot_results("pyrogrambot")
results = await app.get_inline_bot_results("pyrogrambot")
print(results)
"""
# TODO: Don't return the raw type

View File

@ -58,7 +58,7 @@ class RequestCallbackAnswer:
Example:
.. code-block:: python
app.request_callback_answer(chat_id, message_id, "callback_data")
await app.request_callback_answer(chat_id, message_id, "callback_data")
"""
# Telegram only wants bytes, but we are allowed to pass strings too.

View File

@ -69,7 +69,7 @@ class SendGame:
Example:
.. code-block:: python
app.send_game(chat_id, "gamename")
await app.send_game(chat_id, "gamename")
"""
r = await self.invoke(
raw.functions.messages.SendMedia(

View File

@ -59,7 +59,7 @@ class SendInlineBotResult:
Example:
.. code-block:: python
app.send_inline_bot_result(chat_id, query_id, result_id)
await app.send_inline_bot_result(chat_id, query_id, result_id)
"""
return await self.invoke(
raw.functions.messages.SendInlineBotResult(

View File

@ -57,7 +57,7 @@ class SetBotCommands:
from pyrogram.types import BotCommand
# Set new commands
app.set_bot_commands([
await app.set_bot_commands([
BotCommand("start", "Start the bot"),
BotCommand("settings", "Bot settings")])
"""

View File

@ -70,10 +70,10 @@ class SetGameScore:
.. code-block:: python
# Set new score
app.set_game_score(user_id, 1000)
await app.set_game_score(user_id, 1000)
# Force set new score
app.set_game_score(user_id, 25, force=True)
await app.set_game_score(user_id, 25, force=True)
"""
r = await self.invoke(
raw.functions.messages.SetGameScore(

View File

@ -36,7 +36,6 @@ from .get_dialogs import GetDialogs
from .get_dialogs_count import GetDialogsCount
from .get_nearby_chats import GetNearbyChats
from .get_send_as_chats import GetSendAsChats
from .iter_chat_members import IterChatMembers
from .iter_dialogs import IterDialogs
from .join_chat import JoinChat
from .leave_chat import LeaveChat
@ -78,7 +77,6 @@ class Chats(
GetDialogs,
GetChatMembersCount,
IterDialogs,
IterChatMembers,
SetChatUsername,
SetChatPermissions,
GetDialogsCount,

View File

@ -52,13 +52,13 @@ class AddChatMembers:
.. code-block:: python
# Add one member to a group or channel
app.add_chat_members(chat_id, user_id)
await app.add_chat_members(chat_id, user_id)
# Add multiple members to a group or channel
app.add_chat_members(chat_id, [user_id1, user_id2, user_id3])
await app.add_chat_members(chat_id, [user_id1, user_id2, user_id3])
# Change forward_limit (for basic groups only)
app.add_chat_members(chat_id, user_id, forward_limit=25)
await app.add_chat_members(chat_id, user_id, forward_limit=25)
"""
peer = await self.resolve_peer(chat_id)

View File

@ -41,10 +41,10 @@ class ArchiveChats:
.. code-block:: python
# Archive chat
app.archive_chats(chat_id)
await app.archive_chats(chat_id)
# Archive multiple chats at once
app.archive_chats([chat_id1, chat_id2, chat_id3])
await app.archive_chats([chat_id1, chat_id2, chat_id3])
"""
if not isinstance(chat_ids, list):

View File

@ -64,10 +64,10 @@ class BanChatMember:
from datetime import datetime, timedelta
# Ban chat member forever
app.ban_chat_member(chat_id, user_id)
await app.ban_chat_member(chat_id, user_id)
# Ban chat member and automatically unban after 24h
app.ban_chat_member(chat_id, user_id, datetime.now() + timedelta(days=1))
await app.ban_chat_member(chat_id, user_id, datetime.now() + timedelta(days=1))
"""
chat_peer = await self.resolve_peer(chat_id)
user_peer = await self.resolve_peer(user_id)

View File

@ -41,7 +41,7 @@ class CreateChannel:
Example:
.. code-block:: python
app.create_channel("Channel Title", "Channel Description")
await app.create_channel("Channel Title", "Channel Description")
"""
r = await self.invoke(
raw.functions.channels.CreateChannel(

View File

@ -50,7 +50,7 @@ class CreateGroup:
Example:
.. code-block:: python
app.create_group("Group Title", user_id)
await app.create_group("Group Title", user_id)
"""
if not isinstance(users, list):
users = [users]

View File

@ -45,7 +45,7 @@ class CreateSupergroup:
Example:
.. code-block:: python
app.create_supergroup("Supergroup Title", "Supergroup Description")
await app.create_supergroup("Supergroup Title", "Supergroup Description")
"""
r = await self.invoke(
raw.functions.channels.CreateChannel(

View File

@ -39,7 +39,7 @@ class DeleteChannel:
Example:
.. code-block:: python
app.delete_channel(channel_id)
await app.delete_channel(channel_id)
"""
await self.invoke(
raw.functions.channels.DeleteChannel(

View File

@ -44,7 +44,7 @@ class DeleteChatPhoto:
Example:
.. code-block:: python
app.delete_chat_photo(chat_id)
await app.delete_chat_photo(chat_id)
"""
peer = await self.resolve_peer(chat_id)

View File

@ -39,7 +39,7 @@ class DeleteSupergroup:
Example:
.. code-block:: python
app.delete_supergroup(supergroup_id)
await app.delete_supergroup(supergroup_id)
"""
await self.invoke(
raw.functions.channels.DeleteChannel(

View File

@ -50,7 +50,7 @@ class GetChat:
Example:
.. code-block:: python
chat = app.get_chat("pyrogram")
chat = await app.get_chat("pyrogram")
print(chat)
"""
match = self.INVITE_LINK_RE.match(str(chat_id))

View File

@ -64,6 +64,12 @@ class GetChatEventLog:
Yields:
:obj:`~pyrogram.types.ChatEvent` objects.
Example:
.. code-block:: python
async for event in app.get_chat_event_log(chat_id):
print(event)
"""
current = 0
total = abs(limit) or (1 << 31)

View File

@ -47,7 +47,7 @@ class GetChatMember:
Example:
.. code-block:: python
member = app.get_chat_member(chat_id, "me")
member = await app.get_chat_member(chat_id, "me")
print(member)
"""
chat = await self.resolve_peer(chat_id)

View File

@ -97,16 +97,16 @@ class GetChatMembers:
from pyrogram import enums
# Get members
for member in app.get_chat_members(chat_id):
async for member in app.get_chat_members(chat_id):
print(member)
# Get administrators
administrators = list(app.get_chat_members(
administrators = list(await app.get_chat_members(
chat_id,
filter=enums.ChatMembersFilter.ADMINISTRATORS))
# Get bots
bots = list(app.get_chat_members(
bots = list(await app.get_chat_members(
chat_id,
filter=enums.ChatMembersFilter.BOTS))
"""

View File

@ -42,7 +42,7 @@ class GetChatMembersCount:
Example:
.. code-block:: python
count = app.get_chat_members_count(chat_id)
count = await app.get_chat_members_count(chat_id)
print(count)
"""
peer = await self.resolve_peer(chat_id)

View File

@ -39,7 +39,7 @@ class GetChatOnlineCount:
Example:
.. code-block:: python
online = app.get_chat_online_count(chat_id)
online = await app.get_chat_online_count(chat_id)
print(online)
"""
return (await self.invoke(

View File

@ -60,10 +60,10 @@ class GetDialogs:
.. code-block:: python
# Get first 100 dialogs
app.get_dialogs()
await app.get_dialogs()
# Get pinned dialogs
app.get_dialogs(pinned_only=True)
await app.get_dialogs(pinned_only=True)
"""
if pinned_only:

View File

@ -37,7 +37,7 @@ class GetDialogsCount:
Example:
.. code-block:: python
count = app.get_dialogs_count()
count = await app.get_dialogs_count()
print(count)
"""

View File

@ -45,7 +45,7 @@ class GetNearbyChats:
Example:
.. code-block:: python
chats = app.get_nearby_chats(51.500729, -0.124583)
chats = await app.get_nearby_chats(latitude, longitude)
print(chats)
"""

View File

@ -40,7 +40,7 @@ class GetSendAsChats:
Example:
.. code-block:: python
chats = app.get_send_as_chats(chat_id)
chats = await app.get_send_as_chats(chat_id)
print(chats)
"""
r = await self.invoke(

View File

@ -1,127 +0,0 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-present Dan <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#
# Pyrogram is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Pyrogram is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
from typing import Union, AsyncGenerator, Optional
import pyrogram
from pyrogram import raw
from pyrogram import types
class Filters:
ALL = "all"
BANNED = "banned"
RESTRICTED = "restricted"
BOTS = "bots"
RECENT = "recent"
ADMINISTRATORS = "administrators"
class IterChatMembers:
async def iter_chat_members(
self: "pyrogram.Client",
chat_id: Union[int, str],
limit: int = 0,
query: str = "",
filter: str = Filters.RECENT
) -> Optional[AsyncGenerator["types.ChatMember", None]]:
"""Iterate through the members of a chat sequentially.
This convenience method does the same as repeatedly calling :meth:`~pyrogram.Client.get_chat_members` in a loop,
thus saving you from the hassle of setting up boilerplate code. It is useful for getting the whole members list
of a chat with a single call.
Parameters:
chat_id (``int`` | ``str``):
Unique identifier (int) or username (str) of the target chat.
limit (``int``, *optional*):
Limits the number of members to be retrieved.
query (``str``, *optional*):
Query string to filter members based on their display names and usernames.
Defaults to "" (empty string).
A query string is applicable only for *"all"*, *"banned"* and *"restricted"* filters only.
filter (``str``, *optional*):
Filter used to select the kind of members you want to retrieve. Only applicable for supergroups
and channels. It can be any of the followings:
*"all"* - all kind of members,
*"banned"* - banned members only,
*"restricted"* - restricted members only,
*"bots"* - bots only,
*"recent"* - recent members only,
*"administrators"* - chat administrators only.
Defaults to *"recent"*.
Returns:
``Generator``: A generator yielding :obj:`~pyrogram.types.ChatMember` objects.
Example:
.. code-block:: python
# Iterate though all chat members
for member in app.iter_chat_members(chat_id):
print(member.user.first_name)
# Iterate though all administrators
for member in app.iter_chat_members(chat_id, filter="administrators"):
print(member.user.first_name)
# Iterate though all bots
for member in app.iter_chat_members(chat_id, filter="bots"):
print(member.user.first_name)
"""
current = 0
yielded = set()
total = limit or (1 << 31) - 1
limit = min(200, total)
resolved_chat_id = await self.resolve_peer(chat_id)
offset = 0
while True:
chat_members = await self.get_chat_members(
chat_id=chat_id,
offset=offset,
limit=limit,
query=query,
filter=filter
)
if not chat_members:
break
if isinstance(resolved_chat_id, raw.types.InputPeerChat):
total = len(chat_members)
offset += len(chat_members)
for chat_member in chat_members:
peer_id = chat_member.user.id if chat_member.user else chat_member.chat.id
if peer_id in yielded:
continue
yield chat_member
yielded.add(peer_id)
current += 1
if current >= total:
return

View File

@ -45,7 +45,7 @@ class IterDialogs:
.. code-block:: python
# Iterate through all dialogs
for dialog in app.iter_dialogs():
async for dialog in app.iter_dialogs():
print(dialog.chat.first_name or dialog.chat.title)
"""
current = 0

View File

@ -41,14 +41,14 @@ class JoinChat:
Example:
.. code-block:: python
# Join chat via username
app.join_chat("pyrogram")
# Join chat via invite link
app.join_chat("https://t.me/joinchat/AAAAAE0QmSW3IUmm3UFR7A")
await app.join_chat("https://t.me/+AbCdEf0123456789")
# Join chat via username
await app.join_chat("pyrogram")
# Join a linked chat
app.join_chat(app.get_chat("pyrogram").linked_chat.id)
await app.join_chat(app.get_chat("pyrogram").linked_chat.id)
"""
match = self.INVITE_LINK_RE.match(str(chat_id))

View File

@ -43,10 +43,10 @@ class LeaveChat:
.. code-block:: python
# Leave chat or channel
app.leave_chat(chat_id)
await app.leave_chat(chat_id)
# Leave basic chat and also delete the dialog
app.leave_chat(chat_id, delete=True)
await app.leave_chat(chat_id, delete=True)
"""
peer = await self.resolve_peer(chat_id)

View File

@ -56,10 +56,10 @@ class PinChatMessage:
.. code-block:: python
# Pin with notification
app.pin_chat_message(chat_id, message_id)
await app.pin_chat_message(chat_id, message_id)
# Pin without notification
app.pin_chat_message(chat_id, message_id, disable_notification=True)
await app.pin_chat_message(chat_id, message_id, disable_notification=True)
"""
r = await self.invoke(
raw.functions.messages.UpdatePinnedMessage(

View File

@ -27,7 +27,7 @@ class PromoteChatMember:
self: "pyrogram.Client",
chat_id: Union[int, str],
user_id: Union[int, str],
privileges: "types.ChatPrivileges" = types.ChatPrivileges(),
privileges: "types.ChatPrivileges" = None,
) -> bool:
"""Promote or demote a user in a supergroup or a channel.
@ -52,11 +52,15 @@ class PromoteChatMember:
.. code-block:: python
# Promote chat member to admin
app.promote_chat_member(chat_id, user_id)
await app.promote_chat_member(chat_id, user_id)
"""
chat_id = await self.resolve_peer(chat_id)
user_id = await self.resolve_peer(user_id)
# See Chat.promote_member for the reason of this (instead of setting types.ChatPrivileges() as default arg).
if privileges is None:
privileges = types.ChatPrivileges()
raw_chat_member = (await self.invoke(
raw.functions.channels.GetParticipant(
channel=chat_id,

View File

@ -60,17 +60,18 @@ class RestrictChatMember:
.. code-block:: python
from datetime import datetime, timedelta
from pyrogram.types import ChatPermissions
# Completely restrict chat member (mute) forever
app.restrict_chat_member(chat_id, user_id, ChatPermissions())
await app.restrict_chat_member(chat_id, user_id, ChatPermissions())
# Chat member muted for 24h
app.restrict_chat_member(chat_id, user_id, ChatPermissions(), datetime.now() + timedelta(days=1))
await app.restrict_chat_member(chat_id, user_id, ChatPermissions(),
datetime.now() + timedelta(days=1))
# Chat member can only send text messages
app.restrict_chat_member(chat_id, user_id, ChatPermissions(can_send_messages=True))
await app.restrict_chat_member(chat_id, user_id,
ChatPermissions(can_send_messages=True))
"""
r = await self.invoke(
raw.functions.channels.EditBanned(

View File

@ -52,7 +52,7 @@ class SetAdministratorTitle:
Example:
.. code-block:: python
app.set_administrator_title(chat_id, user_id, "Admin Title")
await app.set_administrator_title(chat_id, user_id, "Admin Title")
"""
chat_id = await self.resolve_peer(chat_id)
user_id = await self.resolve_peer(user_id)

View File

@ -47,7 +47,7 @@ class SetChatDescription:
Example:
.. code-block:: python
app.set_chat_description(chat_id, "New Description")
await app.set_chat_description(chat_id, "New Description")
"""
peer = await self.resolve_peer(chat_id)

View File

@ -50,10 +50,10 @@ class SetChatPermissions:
from pyrogram.types import ChatPermissions
# Completely restrict chat
app.set_chat_permissions(chat_id, ChatPermissions())
await app.set_chat_permissions(chat_id, ChatPermissions())
# Chat members can only send text messages and media messages
app.set_chat_permissions(
await app.set_chat_permissions(
chat_id,
ChatPermissions(
can_send_messages=True,

View File

@ -68,17 +68,17 @@ class SetChatPhoto:
.. code-block:: python
# Set chat photo using a local file
app.set_chat_photo(chat_id, photo="photo.jpg")
await app.set_chat_photo(chat_id, photo="photo.jpg")
# Set chat photo using an exiting Photo file_id
app.set_chat_photo(chat_id, photo=photo.file_id)
await app.set_chat_photo(chat_id, photo=photo.file_id)
# Set chat video using a local file
app.set_chat_photo(chat_id, video="video.mp4")
await app.set_chat_photo(chat_id, video="video.mp4")
# Set chat photo using an exiting Video file_id
app.set_chat_photo(chat_id, video=video.file_id)
await app.set_chat_photo(chat_id, video=video.file_id)
"""
peer = await self.resolve_peer(chat_id)

View File

@ -52,7 +52,7 @@ class SetChatTitle:
Example:
.. code-block:: python
app.set_chat_title(chat_id, "New Title")
await app.set_chat_title(chat_id, "New Title")
"""
peer = await self.resolve_peer(chat_id)

View File

@ -48,7 +48,7 @@ class SetChatUsername:
Example:
.. code-block:: python
app.set_chat_username(chat_id, "new_username")
await app.set_chat_username(chat_id, "new_username")
"""
peer = await self.resolve_peer(chat_id)

View File

@ -45,7 +45,7 @@ class SetSendAsChat:
Example:
.. code-block:: python
app.set_send_as_chat(chat_id, send_as_chat_id)
await app.set_send_as_chat(chat_id, send_as_chat_id)
"""
return await self.invoke(
raw.functions.messages.SaveDefaultSendAs(

View File

@ -45,10 +45,10 @@ class SetSlowMode:
.. code-block:: python
# Set slow mode to 60 seconds
app.set_slow_mode(chat_id, 60)
await app.set_slow_mode(chat_id, 60)
# Disable slow mode
app.set_slow_mode(chat_id, None)
await app.set_slow_mode(chat_id, None)
"""
await self.invoke(

View File

@ -41,10 +41,10 @@ class UnarchiveChats:
.. code-block:: python
# Unarchive chat
app.unarchive_chats(chat_id)
await app.unarchive_chats(chat_id)
# Unarchive multiple chats at once
app.unarchive_chats([chat_id1, chat_id2, chat_id3])
await app.unarchive_chats([chat_id1, chat_id2, chat_id3])
"""
if not isinstance(chat_ids, list):

View File

@ -47,7 +47,7 @@ class UnbanChatMember:
.. code-block:: python
# Unban chat member right now
app.unban_chat_member(chat_id, user_id)
await app.unban_chat_member(chat_id, user_id)
"""
await self.invoke(
raw.functions.channels.EditBanned(

View File

@ -42,7 +42,7 @@ class UnpinAllChatMessages:
.. code-block:: python
# Unpin all chat messages
app.unpin_all_chat_messages(chat_id)
await app.unpin_all_chat_messages(chat_id)
"""
await self.invoke(
raw.functions.messages.UnpinAllMessages(

View File

@ -46,7 +46,7 @@ class UnpinChatMessage:
Example:
.. code-block:: python
app.unpin_chat_message(chat_id, message_id)
await app.unpin_chat_message(chat_id, message_id)
"""
await self.invoke(
raw.functions.messages.UpdatePinnedMessage(

View File

@ -57,8 +57,11 @@ class AddContact:
Example:
.. code-block:: python
app.add_contact(12345678, "Foo")
app.add_contact("username", "Bar")
# Add contact by id
await app.add_contact(12345678, "Foo")
# Add contact by username
await app.add_contact("username", "Bar")
"""
r = await self.invoke(
raw.functions.contacts.AddContact(

View File

@ -42,8 +42,8 @@ class DeleteContacts:
Example:
.. code-block:: python
app.delete_contacts(user_id)
app.delete_contacts([user_id1, user_id2, user_id3])
await app.delete_contacts(user_id)
await app.delete_contacts([user_id1, user_id2, user_id3])
"""
is_user_ids_list = isinstance(user_ids, list)

View File

@ -38,7 +38,7 @@ class GetContacts:
Example:
.. code-block:: python
contacts = app.get_contacts()
contacts = await app.get_contacts()
print(contacts)
"""
contacts = await self.invoke(raw.functions.contacts.GetContacts(hash=0))

View File

@ -32,7 +32,7 @@ class GetContactsCount:
Example:
.. code-block:: python
count = app.get_contacts_count()
count = await app.get_contacts_count()
print(count)
"""

View File

@ -42,7 +42,7 @@ class ImportContacts:
from pyrogram.types import InputPhoneContact
app.import_contacts([
await app.import_contacts([
InputPhoneContact("+1-123-456-7890", "Foo"),
InputPhoneContact("+1-456-789-0123", "Bar"),
InputPhoneContact("+1-789-012-3456", "Baz")])

View File

@ -67,10 +67,10 @@ class CreateChatInviteLink:
.. code-block:: python
# Create a new link without limits
link = app.create_chat_invite_link(chat_id)
link = await app.create_chat_invite_link(chat_id)
# Create a new link for up to 7 new users
link = app.create_chat_invite_link(chat_id, member_limit=7)
# Create a new link for up to 3 new users
link = await app.create_chat_invite_link(chat_id, member_limit=3)
"""
r = await self.invoke(
raw.functions.messages.ExportChatInvite(

View File

@ -69,10 +69,10 @@ class EditChatInviteLink:
.. code-block:: python
# Edit the member limit of a link
link = app.edit_chat_invite_link(chat_id, invite_link, member_limit=9)
link = await app.edit_chat_invite_link(chat_id, invite_link, member_limit=5)
# Set no expiration date of a link
link = app.edit_chat_invite_link(chat_id, invite_link, expire_date=0)
link = await app.edit_chat_invite_link(chat_id, invite_link, expire_date=0)
"""
r = await self.invoke(
raw.functions.messages.EditExportedChatInvite(

View File

@ -51,7 +51,7 @@ class ExportChatInviteLink:
.. code-block:: python
# Generate a new primary link
link = app.export_chat_invite_link(chat_id)
link = await app.export_chat_invite_link(chat_id)
"""
r = await self.invoke(
raw.functions.messages.ExportChatInvite(

View File

@ -76,9 +76,12 @@ class CopyMediaGroup:
.. code-block:: python
# Copy a media group
app.copy_media_group("me", source_chat, message_id)
app.copy_media_group("me", source_chat, message_id, captions="single caption")
app.copy_media_group("me", source_chat, message_id, captions=["caption 1", None, ""])
await app.copy_media_group(to_chat, from_chat, 123)
await app.copy_media_group(to_chat, from_chat, 123, captions="single caption")
await app.copy_media_group(to_chat, from_chat, 123,
captions=["caption 1", None, ""])
"""
media_group = await self.get_media_group(from_chat_id, message_id)

View File

@ -101,7 +101,7 @@ class CopyMessage:
.. code-block:: python
# Copy a message
app.copy_message("me", "pyrogram", 20)
await app.copy_message(to_chat, from_chat, 123)
"""
message: types.Message = await self.get_messages(from_chat_id, message_id)

View File

@ -54,13 +54,13 @@ class DeleteMessages:
.. code-block:: python
# Delete one message
app.delete_messages(chat_id, message_id)
await app.delete_messages(chat_id, message_id)
# Delete multiple messages at once
app.delete_messages(chat_id, list_of_message_ids)
await app.delete_messages(chat_id, list_of_message_ids)
# Delete messages only on your side (without revoking)
app.delete_messages(chat_id, message_id, revoke=False)
await app.delete_messages(chat_id, message_id, revoke=False)
"""
peer = await self.resolve_peer(chat_id)
message_ids = list(message_ids) if not isinstance(message_ids, int) else [message_ids]

View File

@ -89,16 +89,16 @@ class DownloadMedia:
.. code-block:: python
# Download from Message
app.download_media(message)
await app.download_media(message)
# Download from file id
app.download_media(message.photo.file_id)
await app.download_media(message.photo.file_id)
# Keep track of the progress while downloading
def progress(current, total):
async def progress(current, total):
print(f"{current * 100 / total:.1f}%")
app.download_media(message, progress=progress)
await app.download_media(message, progress=progress)
"""
available_media = ("audio", "document", "photo", "sticker", "animation", "video", "voice", "video_note",
"new_chat_photo")

View File

@ -53,7 +53,7 @@ class EditInlineCaption:
.. code-block:: python
# Bots only
app.edit_inline_caption(inline_message_id, "new media caption")
await app.edit_inline_caption(inline_message_id, "new media caption")
"""
return await self.edit_inline_text(
inline_message_id=inline_message_id,

View File

@ -61,13 +61,13 @@ class EditInlineMedia:
# Bots only
# Replace the current media with a local photo
app.edit_inline_media(inline_message_id, InputMediaPhoto("new_photo.jpg"))
await app.edit_inline_media(inline_message_id, InputMediaPhoto("new_photo.jpg"))
# Replace the current media with a local video
app.edit_inline_media(inline_message_id, InputMediaVideo("new_video.mp4"))
await app.edit_inline_media(inline_message_id, InputMediaVideo("new_video.mp4"))
# Replace the current media with a local audio
app.edit_inline_media(inline_message_id, InputMediaAudio("new_audio.mp3"))
await app.edit_inline_media(inline_message_id, InputMediaAudio("new_audio.mp3"))
"""
caption = media.caption
parse_mode = media.parse_mode

View File

@ -47,7 +47,7 @@ class EditInlineReplyMarkup:
from pyrogram.types import InlineKeyboardMarkup, InlineKeyboardButton
# Bots only
app.edit_inline_reply_markup(
await app.edit_inline_reply_markup(
inline_message_id,
InlineKeyboardMarkup([[
InlineKeyboardButton("New button", callback_data="new_data")]]))

View File

@ -62,10 +62,10 @@ class EditInlineText:
# Bots only
# Simple edit text
app.edit_inline_text(inline_message_id, "new text")
await app.edit_inline_text(inline_message_id, "new text")
# Take the same text message, remove the web page preview only
app.edit_inline_text(
await app.edit_inline_text(
inline_message_id, message.text,
disable_web_page_preview=True)
"""

View File

@ -62,7 +62,7 @@ class EditMessageCaption:
Example:
.. code-block:: python
app.edit_message_caption(chat_id, message_id, "new media caption")
await app.edit_message_caption(chat_id, message_id, "new media caption")
"""
return await self.edit_message_text(
chat_id=chat_id,

View File

@ -69,13 +69,16 @@ class EditMessageMedia:
from pyrogram.types import InputMediaPhoto, InputMediaVideo, InputMediaAudio
# Replace the current media with a local photo
app.edit_message_media(chat_id, message_id, InputMediaPhoto("new_photo.jpg"))
await app.edit_message_media(chat_id, message_id,
InputMediaPhoto("new_photo.jpg"))
# Replace the current media with a local video
app.edit_message_media(chat_id, message_id, InputMediaVideo("new_video.mp4"))
await app.edit_message_media(chat_id, message_id,
InputMediaVideo("new_video.mp4"))
# Replace the current media with a local audio
app.edit_message_media(chat_id, message_id, InputMediaAudio("new_audio.mp3"))
await app.edit_message_media(chat_id, message_id,
InputMediaAudio("new_audio.mp3"))
"""
caption = media.caption
parse_mode = media.parse_mode

View File

@ -53,7 +53,7 @@ class EditMessageReplyMarkup:
from pyrogram.types import InlineKeyboardMarkup, InlineKeyboardButton
# Bots only
app.edit_message_reply_markup(
await app.edit_message_reply_markup(
chat_id, message_id,
InlineKeyboardMarkup([[
InlineKeyboardButton("New button", callback_data="new_data")]]))

View File

@ -69,10 +69,10 @@ class EditMessageText:
.. code-block:: python
# Simple edit text
app.edit_message_text(chat_id, message_id, "new text")
await app.edit_message_text(chat_id, message_id, "new text")
# Take the same text message, remove the web page preview only
app.edit_message_text(
await app.edit_message_text(
chat_id, message_id, message.text,
disable_web_page_preview=True)
"""

View File

@ -70,10 +70,10 @@ class ForwardMessages:
.. code-block:: python
# Forward a single message
app.forward_messages("me", "pyrogram", 20)
await app.forward_messages(to_chat, from_chat, 123)
# Forward multiple messages at once
app.forward_messages("me", "pyrogram", [3, 20, 27])
await app.forward_messages(to_chat, from_chat, [1, 2, 3])
"""
is_iterable = not isinstance(message_ids, int)

View File

@ -88,7 +88,7 @@ class GetChatHistory:
Example:
.. code-block:: python
for message in app.get_chat_history(chat_id):
async for message in app.get_chat_history(chat_id):
print(message.text)
"""
current = 0

View File

@ -48,7 +48,7 @@ class GetChatHistoryCount:
Example:
.. code-block:: python
app.get_history_count(chat_id)
await app.get_history_count(chat_id)
"""
r = await self.invoke(

View File

@ -45,10 +45,10 @@ class GetDiscussionMessage:
.. code-block:: python
# Get the discussion message
m = app.get_discussion_message(channel_id, message_id)
m = await app.get_discussion_message(channel_id, message_id)
# Comment to the post by replying
m.reply("comment")
await m.reply("comment")
"""
r = await self.invoke(
raw.functions.messages.GetDiscussionMessage(

View File

@ -45,8 +45,8 @@ class GetDiscussionReplies:
Example:
.. code-block:: python
for m in app.get_discussion_replies(chat_id, message_id):
print(m)
async for message in app.get_discussion_replies(chat_id, message_id):
print(message)
"""
current = 0

View File

@ -40,7 +40,7 @@ class GetDiscussionRepliesCount:
Example:
.. code-block:: python
count = app.get_discussion_replies_count(chat_id, message_id)
count = await app.get_discussion_replies_count(chat_id, message_id)
"""
r = await self.invoke(

View File

@ -71,19 +71,19 @@ class GetMessages:
.. code-block:: python
# Get one message
app.get_messages(chat_id, 12345)
await app.get_messages(chat_id, 12345)
# Get more than one message (list of messages)
app.get_messages(chat_id, [12345, 12346])
await app.get_messages(chat_id, [12345, 12346])
# Get message by ignoring any replied-to message
app.get_messages(chat_id, message_id, replies=0)
await app.get_messages(chat_id, message_id, replies=0)
# Get message with all chained replied-to messages
app.get_messages(chat_id, message_id, replies=-1)
await app.get_messages(chat_id, message_id, replies=-1)
# Get the replied-to message of a message
app.get_messages(chat_id, reply_to_message_ids=message_id)
await app.get_messages(chat_id, reply_to_message_ids=message_id)
Raises:
ValueError: In case of invalid arguments.

View File

@ -47,10 +47,10 @@ class ReadChatHistory:
.. code-block:: python
# Mark the whole chat as read
app.read_history(chat_id)
await app.read_history(chat_id)
# Mark messages as read only up to the given message id
app.read_history(chat_id, 123456)
await app.read_history(chat_id, 12345)
"""
peer = await self.resolve_peer(chat_id)

View File

@ -46,7 +46,7 @@ class RetractVote:
Example:
.. code-block:: python
app.retract_vote(chat_id, message_id)
await app.retract_vote(chat_id, message_id)
"""
r = await self.invoke(
raw.functions.messages.SendVote(

View File

@ -59,12 +59,14 @@ class SearchGlobal:
Example:
.. code-block:: python
from pyrogram import enums
# Search for "pyrogram". Get the first 50 results
for message in app.search_global("pyrogram", limit=50):
async for message in app.search_global("pyrogram", limit=50):
print(message.text)
# Search for recent photos from Global. Get the first 20 results
for message in app.search_global(filter="photo", limit=20):
async for message in app.search_global(filter=enums.MessagesFilter.PHOTO, limit=20):
print(message.photo)
"""
current = 0

Some files were not shown because too many files have changed in this diff Show More