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:
Dan 2018-12-15 11:12:30 +01:00
commit 976eae63ed
14 changed files with 107 additions and 21 deletions

View File

@ -51,7 +51,7 @@ BOT_INLINE_DISABLED The inline feature of the bot is disabled
INLINE_RESULT_EXPIRED The inline bot query expired
INVITE_HASH_INVALID The invite link hash is invalid
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
CHANNEL_INVALID The channel 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
EMAIL_INVALID The email provided is invalid
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
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
@ -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
CHANNEL_PRIVATE The channel/supergroup is not accessible
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
1 id message
51 INLINE_RESULT_EXPIRED The inline bot query expired
52 INVITE_HASH_INVALID The invite link hash is invalid
53 USER_ALREADY_PARTICIPANT The user is already a participant of this chat
54 TTL_MEDIA_INVALID This kind of media does not support self-destruction The media does not support self-destruction
55 MAX_ID_INVALID The max_id parameter is invalid
56 CHANNEL_INVALID The channel parameter is invalid
57 DC_ID_INVALID The dc_id parameter is invalid
59 OFFSET_INVALID The offset parameter is invalid
60 EMAIL_INVALID The email provided is invalid
61 USER_IS_BOT A bot cannot send messages to other bots or to itself
62 WEBPAGE_CURL_FAILED Telegram could not fetch the provided URL Telegram server could not fetch the provided URL
63 STICKERSET_INVALID The requested sticker set is invalid
64 PEER_FLOOD The method can't be used because your account is limited
65 MEDIA_CAPTION_TOO_LONG The media caption is longer than 200 characters
69 USER_NOT_PARTICIPANT The user is not a member of this chat
70 CHANNEL_PRIVATE The channel/supergroup is not accessible
71 MESSAGE_IDS_EMPTY The requested message doesn't exist
72 WEBPAGE_MEDIA_EMPTY The URL doesn't contain any valid media
73 QUERY_ID_INVALID The callback query id is invalid
74 MEDIA_EMPTY The media is invalid
75 USER_IS_BLOCKED The user blocked you
76 YOU_BLOCKED_USER You blocked this user
77 ADMINS_TOO_MUCH The chat has too many administrators
78 BOTS_TOO_MUCH The chat has too many bots
79 USER_ADMIN_INVALID The action requires admin privileges

View File

@ -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
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
RANDOM_ID_DUPLICATE Telegram is having internal problems. Please try again later
1 id message
5 PERSISTENT_TIMESTAMP_OUTDATED Telegram is having internal problems. Please try again later
6 HISTORY_GET_FAILED Telegram is having internal problems. Please try again later
7 REG_ID_GENERATE_FAILED Telegram is having internal problems. Please try again later
8 RANDOM_ID_DUPLICATE Telegram is having internal problems. Please try again later

View File

@ -6,22 +6,40 @@ to make it only work for specific messages in a specific chat.
from pyrogram import Client, Emoji, Filters
MENTION = "[{}](tg://user?id={})"
MESSAGE = "{} Welcome to [Pyrogram](https://docs.pyrogram.ml/)'s group chat {}!"
USER = "**{}**"
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.on_message(Filters.chat("PyrogramChat") & Filters.new_chat_members)
@app.on_message(enabled_groups & Filters.new_chat_members)
def welcome(client, message):
# Build the new members list (with mentions) by using their first_name
new_members = [MENTION.format(i.first_name, i.id) for i in message.new_chat_members]
chat_id = message.chat.id
# Build the welcome message by using an emoji and the list we built above
text = MESSAGE.format(Emoji.SPARKLES, ", ".join(new_members))
# Get the previous welcome message and members, if any
previous_welcome, previous_members = last_welcomes.pop(chat_id, (None, []))
# Send the welcome message
message.reply(text, disable_web_page_preview=True)
# Delete the previous message, if exists
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()

View File

@ -199,10 +199,9 @@ class Client(Methods, BaseClient):
self.dispatcher = Dispatcher(self, workers)
def __enter__(self):
self.start()
return self
return self.start()
def __exit__(self, exc_type, exc_val, exc_tb):
def __exit__(self, *args):
self.stop()
@property
@ -284,6 +283,8 @@ class Client(Methods, BaseClient):
mimetypes.init()
return self
async def stop(self):
"""Use this method to manually stop the Client.
Requires no parameters.
@ -318,6 +319,8 @@ class Client(Methods, BaseClient):
self.is_started = False
await self.session.stop()
return self
async def idle(self, stop_signals: tuple = (SIGINT, SIGTERM, SIGABRT)):
"""Blocks the program execution until one of the signals are received,
then gently stop the Client by closing the underlying connection.
@ -439,6 +442,8 @@ class Client(Methods, BaseClient):
else:
self.user_id = r.user.id
print("Logged in successfully as @{}".format(r.user.username))
async def authorize_user(self):
phone_number_invalid_raises = self.phone_number 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.user_id = r.user.id
print("Login successful")
print("Logged in successfully as {}".format(r.user.first_name))
def fetch_peers(self, entities: list):
for entity in entities:
@ -1234,7 +1239,7 @@ class Client(Methods, BaseClient):
version: int = 0,
size: int = None,
progress: callable = None,
progress_args: tuple = None) -> str:
progress_args: tuple = ()) -> str:
with await self.media_sessions_lock:
session = self.media_sessions.get(dc_id, None)
@ -1316,7 +1321,7 @@ class Client(Methods, BaseClient):
offset += limit
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(
functions.upload.GetFile(
@ -1398,7 +1403,7 @@ class Client(Methods, BaseClient):
offset += limit
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:
break

View File

@ -338,6 +338,7 @@ async def parse_messages(
video_note = None
sticker = None
document = None
web_page = None
media = message.media
@ -585,6 +586,8 @@ async def parse_messages(
file_size=doc.size,
date=doc.date
)
elif isinstance(media, types.MessageMediaWebPage):
web_page = True
else:
media = None
@ -632,6 +635,7 @@ async def parse_messages(
video_note=video_note,
sticker=sticker,
document=document,
web_page=web_page,
views=message.views,
via_bot=parse_user(users.get(message.via_bot_id, None)),
outgoing=message.out,

View File

@ -118,6 +118,9 @@ class Filters:
venue = create("Venue", lambda _, m: bool(m.venue))
"""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"))
"""Filter messages sent in private chats."""
@ -169,6 +172,9 @@ class Filters:
mentioned = create("Mentioned", lambda _, m: bool(m.mentioned))
"""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))
"""Filter service messages. A service message contains any of the following fields set

View File

@ -27,6 +27,13 @@ class OnCallbackQuery(BaseClient):
callback queries. This does the same thing as :meth:`add_handler` using the
: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:
filters (:obj:`Filters <pyrogram.Filters>`):
Pass one or more filters to allow only a subset of callback queries to be passed

View File

@ -27,6 +27,13 @@ class OnDeletedMessages(BaseClient):
deleted messages. This does the same thing as :meth:`add_handler` using the
: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:
filters (:obj:`Filters <pyrogram.Filters>`):
Pass one or more filters to allow only a subset of messages to be passed

View File

@ -27,6 +27,13 @@ class OnMessage(BaseClient):
messages. This does the same thing as :meth:`add_handler` using the
: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:
filters (:obj:`Filters <pyrogram.Filters>`):
Pass one or more filters to allow only a subset of messages to be passed

View File

@ -26,6 +26,13 @@ class OnRawUpdate(BaseClient):
raw updates. This does the same thing as :meth:`add_handler` using the
: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:
group (``int``, *optional*):
The group identifier, defaults to 0.

View File

@ -27,6 +27,13 @@ class OnUserStatus(BaseClient):
user status updates. This does the same thing as :meth:`add_handler` using the
: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:
filters (:obj:`Filters <pyrogram.Filters>`):
Pass one or more filters to allow only a subset of UserStatus updated to be passed in your function.

View File

@ -108,6 +108,7 @@ class SendMediaGroup(BaseClient):
peer=await self.resolve_peer(chat_id),
media=types.InputMediaUploadedDocument(
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"],
attributes=[
types.DocumentAttributeVideo(

View File

@ -28,7 +28,7 @@ class DownloadMedia(BaseClient):
file_name: str = "",
block: bool = True,
progress: callable = None,
progress_args: tuple = None):
progress_args: tuple = ()):
"""Use this method to download the media from a Message.
Args:

View File

@ -134,6 +134,12 @@ class Message(Object):
venue (:obj:`Venue <pyrogram.Venue>`, *optional*):
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 members that were added to the group or supergroup and information about them
(the bot itself may be one of these members).
@ -246,6 +252,7 @@ class Message(Object):
contact=None,
location=None,
venue=None,
web_page=None,
new_chat_members: list = None,
left_chat_member=None,
new_chat_title: str = None,
@ -297,6 +304,7 @@ class Message(Object):
self.contact = contact # flags.22?Contact
self.location = location # flags.23?Location
self.venue = venue # flags.24?Venue
self.web_page = web_page
self.new_chat_members = new_chat_members # flags.25?Vector<User>
self.left_chat_member = left_chat_member # flags.26?User
self.new_chat_title = new_chat_title # flags.27?string