mirror of
https://github.com/TeamPGM/pyrogram.git
synced 2024-11-18 05:30:15 +00:00
Merge branch 'develop' into asyncio
# Conflicts: # pyrogram/client/client.py # pyrogram/client/methods/messages/send_media_group.py # pyrogram/client/methods/utilities/download_media.py
This commit is contained in:
commit
976eae63ed
@ -51,7 +51,7 @@ BOT_INLINE_DISABLED The inline feature of the bot is disabled
|
|||||||
INLINE_RESULT_EXPIRED The inline bot query expired
|
INLINE_RESULT_EXPIRED The inline bot query expired
|
||||||
INVITE_HASH_INVALID The invite link hash is invalid
|
INVITE_HASH_INVALID The invite link hash is invalid
|
||||||
USER_ALREADY_PARTICIPANT The user is already a participant of this chat
|
USER_ALREADY_PARTICIPANT The user is already a participant of this chat
|
||||||
TTL_MEDIA_INVALID This kind of media does not support self-destruction
|
TTL_MEDIA_INVALID The media does not support self-destruction
|
||||||
MAX_ID_INVALID The max_id parameter is invalid
|
MAX_ID_INVALID The max_id parameter is invalid
|
||||||
CHANNEL_INVALID The channel parameter is invalid
|
CHANNEL_INVALID The channel parameter is invalid
|
||||||
DC_ID_INVALID The dc_id parameter is invalid
|
DC_ID_INVALID The dc_id parameter is invalid
|
||||||
@ -59,7 +59,7 @@ LIMIT_INVALID The limit parameter is invalid
|
|||||||
OFFSET_INVALID The offset parameter is invalid
|
OFFSET_INVALID The offset parameter is invalid
|
||||||
EMAIL_INVALID The email provided is invalid
|
EMAIL_INVALID The email provided is invalid
|
||||||
USER_IS_BOT A bot cannot send messages to other bots or to itself
|
USER_IS_BOT A bot cannot send messages to other bots or to itself
|
||||||
WEBPAGE_CURL_FAILED Telegram could not fetch the provided URL
|
WEBPAGE_CURL_FAILED Telegram server could not fetch the provided URL
|
||||||
STICKERSET_INVALID The requested sticker set is invalid
|
STICKERSET_INVALID The requested sticker set is invalid
|
||||||
PEER_FLOOD The method can't be used because your account is limited
|
PEER_FLOOD The method can't be used because your account is limited
|
||||||
MEDIA_CAPTION_TOO_LONG The media caption is longer than 200 characters
|
MEDIA_CAPTION_TOO_LONG The media caption is longer than 200 characters
|
||||||
@ -69,3 +69,11 @@ API_ID_PUBLISHED_FLOOD You are using an API key that is limited on the server si
|
|||||||
USER_NOT_PARTICIPANT The user is not a member of this chat
|
USER_NOT_PARTICIPANT The user is not a member of this chat
|
||||||
CHANNEL_PRIVATE The channel/supergroup is not accessible
|
CHANNEL_PRIVATE The channel/supergroup is not accessible
|
||||||
MESSAGE_IDS_EMPTY The requested message doesn't exist
|
MESSAGE_IDS_EMPTY The requested message doesn't exist
|
||||||
|
WEBPAGE_MEDIA_EMPTY The URL doesn't contain any valid media
|
||||||
|
QUERY_ID_INVALID The callback query id is invalid
|
||||||
|
MEDIA_EMPTY The media is invalid
|
||||||
|
USER_IS_BLOCKED The user blocked you
|
||||||
|
YOU_BLOCKED_USER You blocked this user
|
||||||
|
ADMINS_TOO_MUCH The chat has too many administrators
|
||||||
|
BOTS_TOO_MUCH The chat has too many bots
|
||||||
|
USER_ADMIN_INVALID The action requires admin privileges
|
|
@ -5,3 +5,4 @@ RPC_MCGET_FAIL Telegram is having internal problems. Please try again later
|
|||||||
PERSISTENT_TIMESTAMP_OUTDATED Telegram is having internal problems. Please try again later
|
PERSISTENT_TIMESTAMP_OUTDATED Telegram is having internal problems. Please try again later
|
||||||
HISTORY_GET_FAILED Telegram is having internal problems. Please try again later
|
HISTORY_GET_FAILED Telegram is having internal problems. Please try again later
|
||||||
REG_ID_GENERATE_FAILED Telegram is having internal problems. Please try again later
|
REG_ID_GENERATE_FAILED Telegram is having internal problems. Please try again later
|
||||||
|
RANDOM_ID_DUPLICATE Telegram is having internal problems. Please try again later
|
|
@ -6,22 +6,40 @@ to make it only work for specific messages in a specific chat.
|
|||||||
|
|
||||||
from pyrogram import Client, Emoji, Filters
|
from pyrogram import Client, Emoji, Filters
|
||||||
|
|
||||||
MENTION = "[{}](tg://user?id={})"
|
USER = "**{}**"
|
||||||
MESSAGE = "{} Welcome to [Pyrogram](https://docs.pyrogram.ml/)'s group chat {}!"
|
MESSAGE = "{} Welcome to [Pyrogram](https://docs.pyrogram.ml/)'s group chat {{}}!".format(Emoji.SPARKLES)
|
||||||
|
|
||||||
|
enabled_groups = Filters.chat("PyrogramChat")
|
||||||
|
last_welcomes = {}
|
||||||
|
|
||||||
app = Client("my_account")
|
app = Client("my_account")
|
||||||
|
|
||||||
|
|
||||||
@app.on_message(Filters.chat("PyrogramChat") & Filters.new_chat_members)
|
@app.on_message(enabled_groups & Filters.new_chat_members)
|
||||||
def welcome(client, message):
|
def welcome(client, message):
|
||||||
# Build the new members list (with mentions) by using their first_name
|
chat_id = message.chat.id
|
||||||
new_members = [MENTION.format(i.first_name, i.id) for i in message.new_chat_members]
|
|
||||||
|
|
||||||
# Build the welcome message by using an emoji and the list we built above
|
# Get the previous welcome message and members, if any
|
||||||
text = MESSAGE.format(Emoji.SPARKLES, ", ".join(new_members))
|
previous_welcome, previous_members = last_welcomes.pop(chat_id, (None, []))
|
||||||
|
|
||||||
# Send the welcome message
|
# Delete the previous message, if exists
|
||||||
message.reply(text, disable_web_page_preview=True)
|
if previous_welcome:
|
||||||
|
previous_welcome.delete()
|
||||||
|
|
||||||
|
# Build the new members list by using their first_name. Also append the previous members, if any
|
||||||
|
new_members = [USER.format(i.first_name) for i in message.new_chat_members] + previous_members
|
||||||
|
|
||||||
|
# Build the welcome message by using an emoji and the list we created above
|
||||||
|
text = MESSAGE.format(", ".join(new_members))
|
||||||
|
|
||||||
|
# Actually send the welcome and save the new message and the new members list
|
||||||
|
last_welcomes[message.chat.id] = message.reply(text, disable_web_page_preview=True), new_members
|
||||||
|
|
||||||
|
|
||||||
|
@app.on_message(enabled_groups)
|
||||||
|
def reset(client, message):
|
||||||
|
# Don't make the bot delete the previous welcome in case someone talks in the middle
|
||||||
|
last_welcomes.pop(message.chat.id, None)
|
||||||
|
|
||||||
|
|
||||||
app.run() # Automatically start() and idle()
|
app.run() # Automatically start() and idle()
|
||||||
|
@ -199,10 +199,9 @@ class Client(Methods, BaseClient):
|
|||||||
self.dispatcher = Dispatcher(self, workers)
|
self.dispatcher = Dispatcher(self, workers)
|
||||||
|
|
||||||
def __enter__(self):
|
def __enter__(self):
|
||||||
self.start()
|
return self.start()
|
||||||
return self
|
|
||||||
|
|
||||||
def __exit__(self, exc_type, exc_val, exc_tb):
|
def __exit__(self, *args):
|
||||||
self.stop()
|
self.stop()
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@ -284,6 +283,8 @@ class Client(Methods, BaseClient):
|
|||||||
|
|
||||||
mimetypes.init()
|
mimetypes.init()
|
||||||
|
|
||||||
|
return self
|
||||||
|
|
||||||
async def stop(self):
|
async def stop(self):
|
||||||
"""Use this method to manually stop the Client.
|
"""Use this method to manually stop the Client.
|
||||||
Requires no parameters.
|
Requires no parameters.
|
||||||
@ -318,6 +319,8 @@ class Client(Methods, BaseClient):
|
|||||||
self.is_started = False
|
self.is_started = False
|
||||||
await self.session.stop()
|
await self.session.stop()
|
||||||
|
|
||||||
|
return self
|
||||||
|
|
||||||
async def idle(self, stop_signals: tuple = (SIGINT, SIGTERM, SIGABRT)):
|
async def idle(self, stop_signals: tuple = (SIGINT, SIGTERM, SIGABRT)):
|
||||||
"""Blocks the program execution until one of the signals are received,
|
"""Blocks the program execution until one of the signals are received,
|
||||||
then gently stop the Client by closing the underlying connection.
|
then gently stop the Client by closing the underlying connection.
|
||||||
@ -439,6 +442,8 @@ class Client(Methods, BaseClient):
|
|||||||
else:
|
else:
|
||||||
self.user_id = r.user.id
|
self.user_id = r.user.id
|
||||||
|
|
||||||
|
print("Logged in successfully as @{}".format(r.user.username))
|
||||||
|
|
||||||
async def authorize_user(self):
|
async def authorize_user(self):
|
||||||
phone_number_invalid_raises = self.phone_number is not None
|
phone_number_invalid_raises = self.phone_number is not None
|
||||||
phone_code_invalid_raises = self.phone_code is not None
|
phone_code_invalid_raises = self.phone_code is not None
|
||||||
@ -623,7 +628,7 @@ class Client(Methods, BaseClient):
|
|||||||
self.password = None
|
self.password = None
|
||||||
self.user_id = r.user.id
|
self.user_id = r.user.id
|
||||||
|
|
||||||
print("Login successful")
|
print("Logged in successfully as {}".format(r.user.first_name))
|
||||||
|
|
||||||
def fetch_peers(self, entities: list):
|
def fetch_peers(self, entities: list):
|
||||||
for entity in entities:
|
for entity in entities:
|
||||||
@ -1234,7 +1239,7 @@ class Client(Methods, BaseClient):
|
|||||||
version: int = 0,
|
version: int = 0,
|
||||||
size: int = None,
|
size: int = None,
|
||||||
progress: callable = None,
|
progress: callable = None,
|
||||||
progress_args: tuple = None) -> str:
|
progress_args: tuple = ()) -> str:
|
||||||
with await self.media_sessions_lock:
|
with await self.media_sessions_lock:
|
||||||
session = self.media_sessions.get(dc_id, None)
|
session = self.media_sessions.get(dc_id, None)
|
||||||
|
|
||||||
@ -1316,7 +1321,7 @@ class Client(Methods, BaseClient):
|
|||||||
offset += limit
|
offset += limit
|
||||||
|
|
||||||
if progress:
|
if progress:
|
||||||
progress(self, min(offset, size), size, *progress_args)
|
progress(self, min(offset, size) if size != 0 else offset, size, *progress_args)
|
||||||
|
|
||||||
r = await session.send(
|
r = await session.send(
|
||||||
functions.upload.GetFile(
|
functions.upload.GetFile(
|
||||||
@ -1398,7 +1403,7 @@ class Client(Methods, BaseClient):
|
|||||||
offset += limit
|
offset += limit
|
||||||
|
|
||||||
if progress:
|
if progress:
|
||||||
progress(self, min(offset, size), size, *progress_args)
|
progress(self, min(offset, size) if size != 0 else offset, size, *progress_args)
|
||||||
|
|
||||||
if len(chunk) < limit:
|
if len(chunk) < limit:
|
||||||
break
|
break
|
||||||
|
@ -338,6 +338,7 @@ async def parse_messages(
|
|||||||
video_note = None
|
video_note = None
|
||||||
sticker = None
|
sticker = None
|
||||||
document = None
|
document = None
|
||||||
|
web_page = None
|
||||||
|
|
||||||
media = message.media
|
media = message.media
|
||||||
|
|
||||||
@ -585,6 +586,8 @@ async def parse_messages(
|
|||||||
file_size=doc.size,
|
file_size=doc.size,
|
||||||
date=doc.date
|
date=doc.date
|
||||||
)
|
)
|
||||||
|
elif isinstance(media, types.MessageMediaWebPage):
|
||||||
|
web_page = True
|
||||||
else:
|
else:
|
||||||
media = None
|
media = None
|
||||||
|
|
||||||
@ -632,6 +635,7 @@ async def parse_messages(
|
|||||||
video_note=video_note,
|
video_note=video_note,
|
||||||
sticker=sticker,
|
sticker=sticker,
|
||||||
document=document,
|
document=document,
|
||||||
|
web_page=web_page,
|
||||||
views=message.views,
|
views=message.views,
|
||||||
via_bot=parse_user(users.get(message.via_bot_id, None)),
|
via_bot=parse_user(users.get(message.via_bot_id, None)),
|
||||||
outgoing=message.out,
|
outgoing=message.out,
|
||||||
|
@ -118,6 +118,9 @@ class Filters:
|
|||||||
venue = create("Venue", lambda _, m: bool(m.venue))
|
venue = create("Venue", lambda _, m: bool(m.venue))
|
||||||
"""Filter messages that contain :obj:`Venue <pyrogram.api.types.pyrogram.Venue>` objects."""
|
"""Filter messages that contain :obj:`Venue <pyrogram.api.types.pyrogram.Venue>` objects."""
|
||||||
|
|
||||||
|
web_page = create("WebPage", lambda _, m: m.web_page)
|
||||||
|
"""Filter messages sent with a webpage preview."""
|
||||||
|
|
||||||
private = create("Private", lambda _, m: bool(m.chat and m.chat.type == "private"))
|
private = create("Private", lambda _, m: bool(m.chat and m.chat.type == "private"))
|
||||||
"""Filter messages sent in private chats."""
|
"""Filter messages sent in private chats."""
|
||||||
|
|
||||||
@ -169,6 +172,9 @@ class Filters:
|
|||||||
mentioned = create("Mentioned", lambda _, m: bool(m.mentioned))
|
mentioned = create("Mentioned", lambda _, m: bool(m.mentioned))
|
||||||
"""Filter messages containing mentions"""
|
"""Filter messages containing mentions"""
|
||||||
|
|
||||||
|
via_bot = create("ViaBot", lambda _, m: bool(m.via_bot))
|
||||||
|
"""Filter messages sent via inline bots"""
|
||||||
|
|
||||||
service = create("Service", lambda _, m: bool(m.service))
|
service = create("Service", lambda _, m: bool(m.service))
|
||||||
"""Filter service messages. A service message contains any of the following fields set
|
"""Filter service messages. A service message contains any of the following fields set
|
||||||
|
|
||||||
|
@ -27,6 +27,13 @@ class OnCallbackQuery(BaseClient):
|
|||||||
callback queries. This does the same thing as :meth:`add_handler` using the
|
callback queries. This does the same thing as :meth:`add_handler` using the
|
||||||
:class:`CallbackQueryHandler`.
|
:class:`CallbackQueryHandler`.
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
This decorator will wrap your defined function in a tuple consisting of *(Handler, group)*.
|
||||||
|
|
||||||
|
To reference your own function after it has been decorated, you need to access
|
||||||
|
*my_function[0].callback*, that is, the *callback* field of Handler object which is the the
|
||||||
|
first element in the tuple.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
filters (:obj:`Filters <pyrogram.Filters>`):
|
filters (:obj:`Filters <pyrogram.Filters>`):
|
||||||
Pass one or more filters to allow only a subset of callback queries to be passed
|
Pass one or more filters to allow only a subset of callback queries to be passed
|
||||||
|
@ -27,6 +27,13 @@ class OnDeletedMessages(BaseClient):
|
|||||||
deleted messages. This does the same thing as :meth:`add_handler` using the
|
deleted messages. This does the same thing as :meth:`add_handler` using the
|
||||||
:class:`DeletedMessagesHandler`.
|
:class:`DeletedMessagesHandler`.
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
This decorator will wrap your defined function in a tuple consisting of *(Handler, group)*.
|
||||||
|
|
||||||
|
To reference your own function after it has been decorated, you need to access
|
||||||
|
*my_function[0].callback*, that is, the *callback* field of Handler object which is the the
|
||||||
|
first element in the tuple.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
filters (:obj:`Filters <pyrogram.Filters>`):
|
filters (:obj:`Filters <pyrogram.Filters>`):
|
||||||
Pass one or more filters to allow only a subset of messages to be passed
|
Pass one or more filters to allow only a subset of messages to be passed
|
||||||
|
@ -27,6 +27,13 @@ class OnMessage(BaseClient):
|
|||||||
messages. This does the same thing as :meth:`add_handler` using the
|
messages. This does the same thing as :meth:`add_handler` using the
|
||||||
:class:`MessageHandler`.
|
:class:`MessageHandler`.
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
This decorator will wrap your defined function in a tuple consisting of *(Handler, group)*.
|
||||||
|
|
||||||
|
To reference your own function after it has been decorated, you need to access
|
||||||
|
*my_function[0].callback*, that is, the *callback* field of Handler object which is the the
|
||||||
|
first element in the tuple.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
filters (:obj:`Filters <pyrogram.Filters>`):
|
filters (:obj:`Filters <pyrogram.Filters>`):
|
||||||
Pass one or more filters to allow only a subset of messages to be passed
|
Pass one or more filters to allow only a subset of messages to be passed
|
||||||
|
@ -26,6 +26,13 @@ class OnRawUpdate(BaseClient):
|
|||||||
raw updates. This does the same thing as :meth:`add_handler` using the
|
raw updates. This does the same thing as :meth:`add_handler` using the
|
||||||
:class:`RawUpdateHandler`.
|
:class:`RawUpdateHandler`.
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
This decorator will wrap your defined function in a tuple consisting of *(Handler, group)*.
|
||||||
|
|
||||||
|
To reference your own function after it has been decorated, you need to access
|
||||||
|
*my_function[0].callback*, that is, the *callback* field of Handler object which is the the
|
||||||
|
first element in the tuple.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
group (``int``, *optional*):
|
group (``int``, *optional*):
|
||||||
The group identifier, defaults to 0.
|
The group identifier, defaults to 0.
|
||||||
|
@ -27,6 +27,13 @@ class OnUserStatus(BaseClient):
|
|||||||
user status updates. This does the same thing as :meth:`add_handler` using the
|
user status updates. This does the same thing as :meth:`add_handler` using the
|
||||||
:class:`UserStatusHandler`.
|
:class:`UserStatusHandler`.
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
This decorator will wrap your defined function in a tuple consisting of *(Handler, group)*.
|
||||||
|
|
||||||
|
To reference your own function after it has been decorated, you need to access
|
||||||
|
*my_function[0].callback*, that is, the *callback* field of Handler object which is the the
|
||||||
|
first element in the tuple.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
filters (:obj:`Filters <pyrogram.Filters>`):
|
filters (:obj:`Filters <pyrogram.Filters>`):
|
||||||
Pass one or more filters to allow only a subset of UserStatus updated to be passed in your function.
|
Pass one or more filters to allow only a subset of UserStatus updated to be passed in your function.
|
||||||
|
@ -108,6 +108,7 @@ class SendMediaGroup(BaseClient):
|
|||||||
peer=await self.resolve_peer(chat_id),
|
peer=await self.resolve_peer(chat_id),
|
||||||
media=types.InputMediaUploadedDocument(
|
media=types.InputMediaUploadedDocument(
|
||||||
file=await self.save_file(i.media),
|
file=await self.save_file(i.media),
|
||||||
|
thumb=None if i.thumb is None else self.save_file(i.thumb),
|
||||||
mime_type=mimetypes.types_map[".mp4"],
|
mime_type=mimetypes.types_map[".mp4"],
|
||||||
attributes=[
|
attributes=[
|
||||||
types.DocumentAttributeVideo(
|
types.DocumentAttributeVideo(
|
||||||
|
@ -28,7 +28,7 @@ class DownloadMedia(BaseClient):
|
|||||||
file_name: str = "",
|
file_name: str = "",
|
||||||
block: bool = True,
|
block: bool = True,
|
||||||
progress: callable = None,
|
progress: callable = None,
|
||||||
progress_args: tuple = None):
|
progress_args: tuple = ()):
|
||||||
"""Use this method to download the media from a Message.
|
"""Use this method to download the media from a Message.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
|
@ -134,6 +134,12 @@ class Message(Object):
|
|||||||
venue (:obj:`Venue <pyrogram.Venue>`, *optional*):
|
venue (:obj:`Venue <pyrogram.Venue>`, *optional*):
|
||||||
Message is a venue, information about the venue.
|
Message is a venue, information about the venue.
|
||||||
|
|
||||||
|
web_page (``bool``, *optional*):
|
||||||
|
Message was sent with a webpage preview.
|
||||||
|
**Note:** Support for web pages is still basic; a simple boolean is set in case the message contains a
|
||||||
|
web page preview. In future versions this property could turn into a full web page object that contains
|
||||||
|
more details.
|
||||||
|
|
||||||
new_chat_members (List of :obj:`User <pyrogram.User>`, *optional*):
|
new_chat_members (List of :obj:`User <pyrogram.User>`, *optional*):
|
||||||
New members that were added to the group or supergroup and information about them
|
New members that were added to the group or supergroup and information about them
|
||||||
(the bot itself may be one of these members).
|
(the bot itself may be one of these members).
|
||||||
@ -246,6 +252,7 @@ class Message(Object):
|
|||||||
contact=None,
|
contact=None,
|
||||||
location=None,
|
location=None,
|
||||||
venue=None,
|
venue=None,
|
||||||
|
web_page=None,
|
||||||
new_chat_members: list = None,
|
new_chat_members: list = None,
|
||||||
left_chat_member=None,
|
left_chat_member=None,
|
||||||
new_chat_title: str = None,
|
new_chat_title: str = None,
|
||||||
@ -297,6 +304,7 @@ class Message(Object):
|
|||||||
self.contact = contact # flags.22?Contact
|
self.contact = contact # flags.22?Contact
|
||||||
self.location = location # flags.23?Location
|
self.location = location # flags.23?Location
|
||||||
self.venue = venue # flags.24?Venue
|
self.venue = venue # flags.24?Venue
|
||||||
|
self.web_page = web_page
|
||||||
self.new_chat_members = new_chat_members # flags.25?Vector<User>
|
self.new_chat_members = new_chat_members # flags.25?Vector<User>
|
||||||
self.left_chat_member = left_chat_member # flags.26?User
|
self.left_chat_member = left_chat_member # flags.26?User
|
||||||
self.new_chat_title = new_chat_title # flags.27?string
|
self.new_chat_title = new_chat_title # flags.27?string
|
||||||
|
Loading…
Reference in New Issue
Block a user