Merge develop -> asyncio

This commit is contained in:
Dan 2019-05-06 17:27:21 +02:00
commit 47c4fae36d
38 changed files with 540 additions and 128 deletions

2
.gitignore vendored
View File

@ -3,7 +3,7 @@
config.ini
# Pyrogram generated code
pyrogram/api/errors/exceptions/
pyrogram/errors/exceptions/
pyrogram/api/functions/
pyrogram/api/types/
pyrogram/api/all.py

View File

@ -66,10 +66,11 @@ Messages
delete_messages
get_messages
get_history
get_history_count
iter_history
send_poll
vote_poll
close_poll
stop_poll
retract_vote
download_media
@ -100,6 +101,7 @@ Chats
iter_chat_members
get_dialogs
iter_dialogs
get_dialogs_count
restrict_chat
update_chat_username
@ -112,6 +114,7 @@ Users
get_me
get_users
get_user_profile_photos
get_user_profile_photos_count
set_user_profile_photo
delete_user_profile_photos
update_username
@ -124,6 +127,7 @@ Contacts
add_contacts
get_contacts
get_contacts_count
delete_contacts
Password

View File

@ -49,7 +49,7 @@ class BaseClient:
DIALOGS_AT_ONCE = 100
UPDATES_WORKERS = 1
DOWNLOAD_WORKERS = 4
OFFLINE_SLEEP = 300
OFFLINE_SLEEP = 900
WORKERS = 4
WORKDIR = "."
CONFIG_FILE = "./config.ini"

View File

@ -24,7 +24,7 @@ import pyrogram
from pyrogram.api import types
from ..handlers import (
CallbackQueryHandler, MessageHandler, DeletedMessagesHandler,
UserStatusHandler, RawUpdateHandler, InlineQueryHandler
UserStatusHandler, RawUpdateHandler, InlineQueryHandler, PollHandler
)
log = logging.getLogger(__name__)
@ -76,12 +76,16 @@ class Dispatcher:
async def inline_query_parser(update, users, chats):
return pyrogram.InlineQuery._parse(self.client, update, users), InlineQueryHandler
async def poll_parser(update, users, chats):
return pyrogram.Poll._parse_update(self.client, update), PollHandler
self.update_parsers = {
Dispatcher.MESSAGE_UPDATES: message_parser,
Dispatcher.DELETE_MESSAGES_UPDATES: deleted_messages_parser,
Dispatcher.CALLBACK_QUERY_UPDATES: callback_query_parser,
(types.UpdateUserStatus,): user_status_parser,
(types.UpdateBotInlineQuery,): inline_query_parser
(types.UpdateBotInlineQuery,): inline_query_parser,
(types.UpdateMessagePoll,): poll_parser
}
self.update_parsers = {key: value for key_tuple, value in self.update_parsers.items() for key in key_tuple}

View File

@ -21,10 +21,11 @@ from .deleted_messages_handler import DeletedMessagesHandler
from .disconnect_handler import DisconnectHandler
from .inline_query_handler import InlineQueryHandler
from .message_handler import MessageHandler
from .poll_handler import PollHandler
from .raw_update_handler import RawUpdateHandler
from .user_status_handler import UserStatusHandler
__all__ = [
"MessageHandler", "DeletedMessagesHandler", "CallbackQueryHandler", "RawUpdateHandler", "DisconnectHandler",
"UserStatusHandler", "InlineQueryHandler"
"UserStatusHandler", "InlineQueryHandler", "PollHandler"
]

View File

@ -0,0 +1,48 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-2019 Dan Tès <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 .handler import Handler
class PollHandler(Handler):
"""The Poll handler class. Used to handle polls updates.
It is intended to be used with :meth:`add_handler() <pyrogram.Client.add_handler>`
For a nicer way to register this handler, have a look at the
:meth:`on_poll() <pyrogram.Client.on_poll>` decorator.
Args:
callback (``callable``):
Pass a function that will be called when a new poll update arrives. It takes *(client, poll)*
as positional arguments (look at the section below for a detailed description).
filters (:obj:`Filters <pyrogram.Filters>`):
Pass one or more filters to allow only a subset of polls to be passed
in your callback function.
Other parameters:
client (:obj:`Client <pyrogram.Client>`):
The Client itself, useful when you want to call other API methods inside the poll handler.
poll (:obj:`Poll <pyrogram.Poll>`):
The received poll.
"""
def __init__(self, callback: callable, filters=None):
super().__init__(callback, filters)

View File

@ -39,6 +39,7 @@ from .set_chat_title import SetChatTitle
from .unban_chat_member import UnbanChatMember
from .unpin_chat_message import UnpinChatMessage
from .update_chat_username import UpdateChatUsername
from .get_dialogs_count import GetDialogsCount
class Chats(
@ -64,6 +65,7 @@ class Chats(
IterDialogs,
IterChatMembers,
UpdateChatUsername,
RestrictChat
RestrictChat,
GetDialogsCount
):
pass

View File

@ -0,0 +1,54 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-2019 Dan Tès <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 pyrogram.api import functions, types
from ...ext import BaseClient
class GetDialogsCount(BaseClient):
async def get_dialogs_count(self, pinned_only: bool = False) -> int:
"""Use this method to get the total count of your dialogs.
pinned_only (``bool``, *optional*):
Pass True if you want to count only pinned dialogs.
Defaults to False.
Returns:
On success, an integer is returned.
Raises:
:class:`RPCError <pyrogram.RPCError>` in case of a Telegram RPC error.
"""
if pinned_only:
return len((await self.send(functions.messages.GetPinnedDialogs())).dialogs)
else:
r = await self.send(
functions.messages.GetDialogs(
offset_date=0,
offset_id=0,
offset_peer=types.InputPeerEmpty(),
limit=1,
hash=0
)
)
if isinstance(r, types.messages.Dialogs):
return len(r.dialogs)
else:
return r.count

View File

@ -19,11 +19,13 @@
from .add_contacts import AddContacts
from .delete_contacts import DeleteContacts
from .get_contacts import GetContacts
from .get_contacts_count import GetContactsCount
class Contacts(
GetContacts,
DeleteContacts,
AddContacts
AddContacts,
GetContactsCount
):
pass

View File

@ -0,0 +1,34 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-2019 Dan Tès <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 pyrogram.api import functions
from ...ext import BaseClient
class GetContactsCount(BaseClient):
async def get_contacts_count(self) -> int:
"""Use this method to get the total count of contacts from your Telegram address book.
Returns:
On success, an integer is returned.
Raises:
:class:`RPCError <pyrogram.RPCError>` in case of a Telegram RPC error.
"""
return len((await self.send(functions.contacts.GetContacts(hash=0))).contacts)

View File

@ -21,6 +21,7 @@ from .on_deleted_messages import OnDeletedMessages
from .on_disconnect import OnDisconnect
from .on_inline_query import OnInlineQuery
from .on_message import OnMessage
from .on_poll import OnPoll
from .on_raw_update import OnRawUpdate
from .on_user_status import OnUserStatus
@ -32,6 +33,7 @@ class Decorators(
OnRawUpdate,
OnDisconnect,
OnUserStatus,
OnInlineQuery
OnInlineQuery,
OnPoll
):
pass

View File

@ -0,0 +1,59 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-2019 Dan Tès <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 Tuple
import pyrogram
from pyrogram.client.filters.filter import Filter
from pyrogram.client.handlers.handler import Handler
from ...ext import BaseClient
class OnPoll(BaseClient):
def on_poll(
self=None,
filters=None,
group: int = 0
) -> callable:
"""Use this decorator to automatically register a function for handling poll updates.
This does the same thing as :meth:`add_handler` using the :class:`PollHandler`.
Args:
filters (:obj:`Filters <pyrogram.Filters>`):
Pass one or more filters to allow only a subset of polls to be passed
in your function.
group (``int``, *optional*):
The group identifier, defaults to 0.
"""
def decorator(func: callable) -> Tuple[Handler, int]:
if isinstance(func, tuple):
func = func[0].callback
handler = pyrogram.PollHandler(func, filters)
if isinstance(self, Filter):
return pyrogram.PollHandler(func, self), group if filters is None else filters
if self is not None:
self.add_handler(handler, group)
return handler, group
return decorator

View File

@ -16,7 +16,6 @@
# 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 .close_poll import ClosePoll
from .delete_messages import DeleteMessages
from .download_media import DownloadMedia
from .edit_message_caption import EditMessageCaption
@ -25,6 +24,7 @@ from .edit_message_reply_markup import EditMessageReplyMarkup
from .edit_message_text import EditMessageText
from .forward_messages import ForwardMessages
from .get_history import GetHistory
from .get_history_count import GetHistoryCount
from .get_messages import GetMessages
from .iter_history import IterHistory
from .retract_vote import RetractVote
@ -44,6 +44,7 @@ from .send_venue import SendVenue
from .send_video import SendVideo
from .send_video_note import SendVideoNote
from .send_voice import SendVoice
from .stop_poll import StopPoll
from .vote_poll import VotePoll
@ -72,10 +73,11 @@ class Messages(
SendVoice,
SendPoll,
VotePoll,
ClosePoll,
StopPoll,
RetractVote,
DownloadMedia,
IterHistory,
SendCachedMedia
SendCachedMedia,
GetHistoryCount
):
pass

View File

@ -37,7 +37,7 @@ class GetHistory(BaseClient):
offset_id: int = 0,
offset_date: int = 0,
reverse: bool = False
):
) -> "pyrogram.Messages":
"""Use this method to retrieve a chunk of the history of a chat.
You can get up to 100 messages at once.

View File

@ -0,0 +1,84 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-2019 Dan Tès <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/>.
import logging
import time
from typing import Union
from pyrogram.api import types, functions
from pyrogram.client.ext import BaseClient
from pyrogram.errors import FloodWait
log = logging.getLogger(__name__)
class GetHistoryCount(BaseClient):
async def get_history_count(
self,
chat_id: Union[int, str]
) -> int:
"""Use this method to get the total count of messages in a chat.
.. note::
Due to Telegram latest internal changes, the server can't reliably find anymore the total count of messages
a **private** or a **basic group** chat has with a single method call. To overcome this limitation, Pyrogram
has to iterate over all the messages. Channels and supergroups are not affected by this limitation.
Args:
chat_id (``int`` | ``str``):
Unique identifier (int) or username (str) of the target chat.
Returns:
On success, an integer is returned.
Raises:
:class:`RPCError <pyrogram.RPCError>` in case of a Telegram RPC error.
"""
peer = await self.resolve_peer(chat_id)
if not isinstance(peer, types.InputPeerChannel):
offset = 0
limit = 100
while True:
try:
r = await self.send(
functions.messages.GetHistory(
peer=peer,
offset_id=1,
offset_date=0,
add_offset=-offset - limit,
limit=limit,
max_id=0,
min_id=0,
hash=0
)
)
except FloodWait as e:
log.warning("Sleeping for {}s".format(e.x))
time.sleep(e.x)
continue
if not r.messages:
return offset
offset += len(r.messages)
return (await self.get_history(chat_id=chat_id, limit=1)).total_count

View File

@ -18,16 +18,17 @@
from typing import Union
import pyrogram
from pyrogram.api import functions
from pyrogram.client.ext import BaseClient
class RetractVote(BaseClient):
def retract_vote(
async def retract_vote(
self,
chat_id: Union[int, str],
message_id: id
) -> bool:
message_id: int
) -> "pyrogram.Poll":
"""Use this method to retract your vote in a poll.
Args:
@ -37,20 +38,20 @@ class RetractVote(BaseClient):
For a contact that exists in your Telegram address book you can use his phone number (str).
message_id (``int``):
Unique poll message identifier inside this chat.
Identifier of the original message with the poll.
Returns:
On success, True is returned.
On success, the :obj:`Poll <pyrogram.Poll>` with the retracted vote is returned.
Raises:
:class:`RPCError <pyrogram.RPCError>` in case of a Telegram RPC error.
"""
self.send(
r = await self.send(
functions.messages.SendVote(
peer=self.resolve_peer(chat_id),
peer=await self.resolve_peer(chat_id),
msg_id=message_id,
options=[]
)
)
return True
return pyrogram.Poll._parse(self, r.updates[0])

View File

@ -83,7 +83,7 @@ class SendAnimation(BaseClient):
thumb (``str``, *optional*):
Thumbnail of the animation file sent.
The thumbnail should be in JPEG format and less than 200 KB in size.
A thumbnail's width and height should not exceed 90 pixels.
A thumbnail's width and height should not exceed 320 pixels.
Thumbnails can't be reused and can be only uploaded as a new file.
disable_notification (``bool``, *optional*):

View File

@ -84,7 +84,7 @@ class SendAudio(BaseClient):
thumb (``str``, *optional*):
Thumbnail of the music file album cover.
The thumbnail should be in JPEG format and less than 200 KB in size.
A thumbnail's width and height should not exceed 90 pixels.
A thumbnail's width and height should not exceed 320 pixels.
Thumbnails can't be reused and can be only uploaded as a new file.
disable_notification (``bool``, *optional*):

View File

@ -62,7 +62,7 @@ class SendDocument(BaseClient):
thumb (``str``, *optional*):
Thumbnail of the file sent.
The thumbnail should be in JPEG format and less than 200 KB in size.
A thumbnail's width and height should not exceed 90 pixels.
A thumbnail's width and height should not exceed 320 pixels.
Thumbnails can't be reused and can be only uploaded as a new file.
caption (``str``, *optional*):

View File

@ -47,10 +47,10 @@ class SendPoll(BaseClient):
For a contact that exists in your Telegram address book you can use his phone number (str).
question (``str``):
The poll question, as string.
Poll question, 1-255 characters.
options (List of ``str``):
The poll options, as list of strings (2 to 10 options are allowed).
List of answer options, 2-10 strings 1-100 characters each.
disable_notification (``bool``, *optional*):
Sends the message silently.

View File

@ -84,7 +84,7 @@ class SendVideo(BaseClient):
thumb (``str``, *optional*):
Thumbnail of the video sent.
The thumbnail should be in JPEG format and less than 200 KB in size.
A thumbnail's width and height should not exceed 90 pixels.
A thumbnail's width and height should not exceed 320 pixels.
Thumbnails can't be reused and can be only uploaded as a new file.
supports_streaming (``bool``, *optional*):

View File

@ -69,7 +69,7 @@ class SendVideoNote(BaseClient):
thumb (``str``, *optional*):
Thumbnail of the video sent.
The thumbnail should be in JPEG format and less than 200 KB in size.
A thumbnail's width and height should not exceed 90 pixels.
A thumbnail's width and height should not exceed 320 pixels.
Thumbnails can't be reused and can be only uploaded as a new file.
disable_notification (``bool``, *optional*):

View File

@ -18,19 +18,21 @@
from typing import Union
import pyrogram
from pyrogram.api import functions, types
from pyrogram.client.ext import BaseClient
class ClosePoll(BaseClient):
def close_poll(
class StopPoll(BaseClient):
async def stop_poll(
self,
chat_id: Union[int, str],
message_id: id
) -> bool:
"""Use this method to close (stop) a poll.
message_id: int,
reply_markup: "pyrogram.InlineKeyboardMarkup" = None
) -> "pyrogram.Poll":
"""Use this method to stop a poll which was sent by you.
Closed polls can't be reopened and nobody will be able to vote in it anymore.
Stopped polls can't be reopened and nobody will be able to vote in it anymore.
Args:
chat_id (``int`` | ``str``):
@ -39,19 +41,22 @@ class ClosePoll(BaseClient):
For a contact that exists in your Telegram address book you can use his phone number (str).
message_id (``int``):
Unique poll message identifier inside this chat.
Identifier of the original message with the poll.
reply_markup (:obj:`InlineKeyboardMarkup`, *optional*):
An InlineKeyboardMarkup object.
Returns:
On success, True is returned.
On success, the stopped :obj:`Poll <pyrogram.Poll>` with the final results is returned.
Raises:
:class:`RPCError <pyrogram.RPCError>` in case of a Telegram RPC error.
"""
poll = self.get_messages(chat_id, message_id).poll
poll = (await self.get_messages(chat_id, message_id)).poll
self.send(
r = await self.send(
functions.messages.EditMessage(
peer=self.resolve_peer(chat_id),
peer=await self.resolve_peer(chat_id),
id=message_id,
media=types.InputMediaPoll(
poll=types.Poll(
@ -60,8 +65,9 @@ class ClosePoll(BaseClient):
question="",
answers=[]
)
)
),
reply_markup=reply_markup.write() if reply_markup else None
)
)
return True
return pyrogram.Poll._parse(self, r.updates[0])

View File

@ -18,17 +18,18 @@
from typing import Union
import pyrogram
from pyrogram.api import functions
from pyrogram.client.ext import BaseClient
class VotePoll(BaseClient):
def vote_poll(
async def vote_poll(
self,
chat_id: Union[int, str],
message_id: id,
option: int
) -> bool:
) -> "pyrogram.Poll":
"""Use this method to vote a poll.
Args:
@ -38,25 +39,26 @@ class VotePoll(BaseClient):
For a contact that exists in your Telegram address book you can use his phone number (str).
message_id (``int``):
Unique poll message identifier inside this chat.
Identifier of the original message with the poll.
option (``int``):
Index of the poll option you want to vote for (0 to 9).
Returns:
On success, True is returned.
On success, the :obj:`Poll <pyrogram.Poll>` with the chosen option is returned.
Raises:
:class:`RPCError <pyrogram.RPCError>` in case of a Telegram RPC error.
"""
poll = self.get_messages(chat_id, message_id).poll
self.send(
poll = (await self.get_messages(chat_id, message_id)).poll
r = await self.send(
functions.messages.SendVote(
peer=self.resolve_peer(chat_id),
peer=await self.resolve_peer(chat_id),
msg_id=message_id,
options=[poll.options[option].data]
options=[poll.options[option]._data]
)
)
return True
return pyrogram.Poll._parse(self, r.updates[0])

View File

@ -19,6 +19,7 @@
from .delete_user_profile_photos import DeleteUserProfilePhotos
from .get_me import GetMe
from .get_user_profile_photos import GetUserProfilePhotos
from .get_user_profile_photos_count import GetUserProfilePhotosCount
from .get_users import GetUsers
from .set_user_profile_photo import SetUserProfilePhoto
from .update_username import UpdateUsername
@ -30,6 +31,7 @@ class Users(
DeleteUserProfilePhotos,
GetUsers,
GetMe,
UpdateUsername
UpdateUsername,
GetUserProfilePhotosCount
):
pass

View File

@ -0,0 +1,54 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-2019 Dan Tès <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
from pyrogram.api import functions, types
from ...ext import BaseClient
class GetUserProfilePhotosCount(BaseClient):
async def get_user_profile_photos_count(self, user_id: Union[int, str]) -> int:
"""Use this method to get the total count of profile pictures for a user.
Args:
user_id (``int`` | ``str``):
Unique identifier (int) or username (str) of the target chat.
For your personal cloud (Saved Messages) you can simply use "me" or "self".
For a contact that exists in your Telegram address book you can use his phone number (str).
Returns:
On success, an integer is returned.
Raises:
:class:`RPCError <pyrogram.RPCError>` in case of a Telegram RPC error.
"""
r = await self.send(
functions.photos.GetUserPhotos(
user_id=await self.resolve_peer(user_id),
offset=0,
max_id=0,
limit=1
)
)
if isinstance(r, types.photos.Photos):
return len(r.photos)
else:
return r.count

View File

@ -31,7 +31,7 @@ class InputMediaAnimation(InputMedia):
thumb (``str``, *optional*):
Thumbnail of the animation file sent.
The thumbnail should be in JPEG format and less than 200 KB in size.
A thumbnail's width and height should not exceed 90 pixels.
A thumbnail's width and height should not exceed 320 pixels.
Thumbnails can't be reused and can be only uploaded as a new file.
caption (``str``, *optional*):

View File

@ -32,7 +32,7 @@ class InputMediaAudio(InputMedia):
thumb (``str``, *optional*):
Thumbnail of the music file album cover.
The thumbnail should be in JPEG format and less than 200 KB in size.
A thumbnail's width and height should not exceed 90 pixels.
A thumbnail's width and height should not exceed 320 pixels.
Thumbnails can't be reused and can be only uploaded as a new file.
caption (``str``, *optional*):

View File

@ -31,7 +31,7 @@ class InputMediaDocument(InputMedia):
thumb (``str``):
Thumbnail of the file sent.
The thumbnail should be in JPEG format and less than 200 KB in size.
A thumbnail's width and height should not exceed 90 pixels.
A thumbnail's width and height should not exceed 320 pixels.
Thumbnails can't be reused and can be only uploaded as a new file.
caption (``str``, *optional*):

View File

@ -33,7 +33,7 @@ class InputMediaVideo(InputMedia):
thumb (``str``):
Thumbnail of the video sent.
The thumbnail should be in JPEG format and less than 200 KB in size.
A thumbnail's width and height should not exceed 90 pixels.
A thumbnail's width and height should not exceed 320 pixels.
Thumbnails can't be reused and can be only uploaded as a new file.
caption (``str``, *optional*):

View File

@ -79,7 +79,7 @@ class Message(PyrogramType, Update):
forward_from (:obj:`User <pyrogram.User>`, *optional*):
For forwarded messages, sender of the original message.
forward_from_name (``str``, *optional*):
forward_sender_name (``str``, *optional*):
For messages forwarded from users who have hidden their accounts, name of the user.
forward_from_chat (:obj:`Chat <pyrogram.Chat>`, *optional*):
@ -186,6 +186,9 @@ class Message(PyrogramType, Update):
web page preview. In future versions this property could turn into a full web page object that contains
more details.
poll (:obj:`Poll <pyrogram.Poll>`, *optional*):
Message is a native poll, information about the poll.
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).
@ -267,7 +270,7 @@ class Message(PyrogramType, Update):
# TODO: Add game missing field. Also invoice, successful_payment, connected_website
__slots__ = [
"message_id", "date", "chat", "from_user", "forward_from", "forward_from_name", "forward_from_chat",
"message_id", "date", "chat", "from_user", "forward_from", "forward_sender_name", "forward_from_chat",
"forward_from_message_id", "forward_signature", "forward_date", "reply_to_message", "mentioned", "empty",
"service", "media", "edit_date", "media_group_id", "author_signature", "text", "entities", "caption_entities",
"audio", "document", "photo", "sticker", "animation", "game", "video", "voice", "video_note", "caption",
@ -286,7 +289,7 @@ class Message(PyrogramType, Update):
chat: Chat = None,
from_user: User = None,
forward_from: User = None,
forward_from_name: str = None,
forward_sender_name: str = None,
forward_from_chat: Chat = None,
forward_from_message_id: int = None,
forward_signature: str = None,
@ -348,7 +351,7 @@ class Message(PyrogramType, Update):
self.chat = chat
self.from_user = from_user
self.forward_from = forward_from
self.forward_from_name = forward_from_name
self.forward_sender_name = forward_sender_name
self.forward_from_chat = forward_from_chat
self.forward_from_message_id = forward_from_message_id
self.forward_signature = forward_signature
@ -487,7 +490,7 @@ class Message(PyrogramType, Update):
entities = list(filter(lambda x: x is not None, entities))
forward_from = None
forward_from_name = None
forward_sender_name = None
forward_from_chat = None
forward_from_message_id = None
forward_signature = None
@ -501,7 +504,7 @@ class Message(PyrogramType, Update):
if forward_header.from_id:
forward_from = User._parse(client, users[forward_header.from_id])
elif forward_header.from_name:
forward_from_name = forward_header.from_name
forward_sender_name = forward_header.from_name
else:
forward_from_chat = Chat._parse_channel_chat(client, chats[forward_header.channel_id])
forward_from_message_id = forward_header.channel_post
@ -607,7 +610,7 @@ class Message(PyrogramType, Update):
caption_entities=entities or None if media is not None else None,
author_signature=message.post_author,
forward_from=forward_from,
forward_from_name=forward_from_name,
forward_sender_name=forward_sender_name,
forward_from_chat=forward_from_chat,
forward_from_message_id=forward_from_message_id,
forward_signature=forward_signature,
@ -795,7 +798,7 @@ class Message(PyrogramType, Update):
thumb (``str``, *optional*):
Thumbnail of the animation file sent.
The thumbnail should be in JPEG format and less than 200 KB in size.
A thumbnail's width and height should not exceed 90 pixels.
A thumbnail's width and height should not exceed 320 pixels.
Thumbnails can't be reused and can be only uploaded as a new file.
disable_notification (``bool``, *optional*):
@ -930,7 +933,7 @@ class Message(PyrogramType, Update):
thumb (``str``, *optional*):
Thumbnail of the music file album cover.
The thumbnail should be in JPEG format and less than 200 KB in size.
A thumbnail's width and height should not exceed 90 pixels.
A thumbnail's width and height should not exceed 320 pixels.
Thumbnails can't be reused and can be only uploaded as a new file.
disable_notification (``bool``, *optional*):
@ -1257,7 +1260,7 @@ class Message(PyrogramType, Update):
thumb (``str``, *optional*):
Thumbnail of the file sent.
The thumbnail should be in JPEG format and less than 200 KB in size.
A thumbnail's width and height should not exceed 90 pixels.
A thumbnail's width and height should not exceed 320 pixels.
Thumbnails can't be reused and can be only uploaded as a new file.
caption (``str``, *optional*):
@ -2064,7 +2067,7 @@ class Message(PyrogramType, Update):
thumb (``str``, *optional*):
Thumbnail of the video sent.
The thumbnail should be in JPEG format and less than 200 KB in size.
A thumbnail's width and height should not exceed 90 pixels.
A thumbnail's width and height should not exceed 320 pixels.
Thumbnails can't be reused and can be only uploaded as a new file.
supports_streaming (``bool``, *optional*):
@ -2189,7 +2192,7 @@ class Message(PyrogramType, Update):
thumb (``str``, *optional*):
Thumbnail of the video sent.
The thumbnail should be in JPEG format and less than 200 KB in size.
A thumbnail's width and height should not exceed 90 pixels.
A thumbnail's width and height should not exceed 320 pixels.
Thumbnails can't be reused and can be only uploaded as a new file.
disable_notification (``bool``, *optional*):

View File

@ -16,91 +16,125 @@
# 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 List
from typing import List, Union
import pyrogram
from pyrogram.api import types
from .poll_option import PollOption
from ..pyrogram_type import PyrogramType
from ..update import Update
class Poll(PyrogramType):
class Poll(PyrogramType, Update):
"""This object represents a Poll.
Args:
id (``int``):
The poll id in this chat.
closed (``bool``):
Whether the poll is closed or not.
id (``str``):
Unique poll identifier.
question (``str``):
Poll question.
Poll question, 1-255 characters.
options (List of :obj:`PollOption`):
The available poll options.
List of poll options.
is_closed (``bool``):
True, if the poll is closed.
total_voters (``int``):
Total amount of voters for this poll.
Total count of voters for this poll.
option_chosen (``int``, *optional*):
The index of your chosen option (in case you voted already), None otherwise.
chosen_option (``int``, *optional*):
Index of your chosen option (0-9), None in case you haven't voted yet.
"""
__slots__ = ["id", "closed", "question", "options", "total_voters", "option_chosen"]
__slots__ = ["id", "question", "options", "is_closed", "total_voters", "chosen_option"]
def __init__(
self,
*,
client: "pyrogram.client.ext.BaseClient",
id: int,
closed: bool,
id: str,
question: str,
options: List[PollOption],
is_closed: bool,
total_voters: int,
option_chosen: int = None
chosen_option: int = None
):
super().__init__(client)
self.id = id
self.closed = closed
self.question = question
self.options = options
self.is_closed = is_closed
self.total_voters = total_voters
self.option_chosen = option_chosen
self.chosen_option = chosen_option
@staticmethod
def _parse(client, media_poll: types.MessageMediaPoll) -> "Poll":
def _parse(client, media_poll: Union[types.MessageMediaPoll, types.UpdateMessagePoll]) -> "Poll":
poll = media_poll.poll
results = media_poll.results.results
total_voters = media_poll.results.total_voters
option_chosen = None
chosen_option = None
options = []
for i, answer in enumerate(poll.answers):
voters = 0
voter_count = 0
if results:
result = results[i]
voters = result.voters
voter_count = result.voters
if result.chosen:
option_chosen = i
chosen_option = i
options.append(PollOption(
options.append(
PollOption(
text=answer.text,
voters=voters,
voter_count=voter_count,
data=answer.option,
client=client
))
)
)
return Poll(
id=poll.id,
closed=poll.closed,
id=str(poll.id),
question=poll.question,
options=options,
is_closed=poll.closed,
total_voters=total_voters,
option_chosen=option_chosen,
chosen_option=chosen_option,
client=client
)
@staticmethod
def _parse_update(client, update: types.UpdateMessagePoll):
if update.poll is not None:
return Poll._parse(client, update)
results = update.results.results
chosen_option = None
options = []
for i, result in enumerate(results):
if result.chosen:
chosen_option = i
options.append(
PollOption(
text="",
voter_count=result.voters,
data=result.option,
client=client
)
)
return Poll(
id=str(update.poll_id),
question="",
options=options,
is_closed=False,
total_voters=update.results.total_voters,
chosen_option=chosen_option,
client=client
)

View File

@ -21,32 +21,29 @@ from ..pyrogram_type import PyrogramType
class PollOption(PyrogramType):
"""This object represents a Poll Option.
"""This object contains information about one answer option in a poll.
Args:
text (``str``):
Text of the poll option.
Option text, 1-100 characters.
voters (``int``):
The number of users who voted this option.
It will be 0 until you vote for the poll.
data (``bytes``):
Unique data that identifies this option among all the other options in a poll.
voter_count (``int``):
Number of users that voted for this option.
Equals to 0 until you vote.
"""
__slots__ = ["text", "voters", "data"]
__slots__ = ["text", "voter_count", "_data"]
def __init__(
self,
*,
client: "pyrogram.client.ext.BaseClient",
text: str,
voters: int,
voter_count: int,
data: bytes
):
super().__init__(client)
self.text = text
self.voters = voters
self.data = data
self.voter_count = voter_count
self._data = data # Hidden

View File

@ -50,6 +50,9 @@ class Video(PyrogramType):
mime_type (``str``, *optional*):
Mime type of a file as defined by sender.
supports_streaming (``bool``, *optional*):
True, if the video was uploaded with streaming support.
file_size (``int``, *optional*):
File size.
@ -57,7 +60,10 @@ class Video(PyrogramType):
Date the video was sent in Unix time.
"""
__slots__ = ["file_id", "thumb", "file_name", "mime_type", "file_size", "date", "width", "height", "duration"]
__slots__ = [
"file_id", "width", "height", "duration", "thumb", "file_name", "mime_type", "supports_streaming", "file_size",
"date"
]
def __init__(
self,
@ -70,20 +76,22 @@ class Video(PyrogramType):
thumb: PhotoSize = None,
file_name: str = None,
mime_type: str = None,
supports_streaming: bool = None,
file_size: int = None,
date: int = None
):
super().__init__(client)
self.file_id = file_id
self.thumb = thumb
self.file_name = file_name
self.mime_type = mime_type
self.file_size = file_size
self.date = date
self.width = width
self.height = height
self.duration = duration
self.thumb = thumb
self.file_name = file_name
self.mime_type = mime_type
self.supports_streaming = supports_streaming
self.file_size = file_size
self.date = date
@staticmethod
def _parse(client, video: types.Document, video_attributes: types.DocumentAttributeVideo,
@ -102,9 +110,10 @@ class Video(PyrogramType):
height=video_attributes.h,
duration=video_attributes.duration,
thumb=PhotoSize._parse(client, video.thumbs),
mime_type=video.mime_type,
file_size=video.size,
file_name=file_name,
mime_type=video.mime_type,
supports_streaming=video_attributes.supports_streaming,
file_size=video.size,
date=video.date,
client=client
)

View File

@ -51,7 +51,7 @@ def default(o: PyrogramType):
return remove_none(
OrderedDict(
[("_", "pyrogram." + o.__class__.__name__)]
+ [i for i in content.items()]
+ [i for i in content.items() if not i[0].startswith("_")]
)
)
except AttributeError:

View File

@ -185,6 +185,12 @@ class Chat(PyrogramType):
if isinstance(chat_full, types.UserFull):
parsed_chat = Chat._parse_user_chat(client, chat_full.user)
parsed_chat.description = chat_full.about
if chat_full.pinned_msg_id:
parsed_chat.pinned_message = await client.get_messages(
parsed_chat.id,
message_ids=chat_full.pinned_msg_id
)
else:
full_chat = chat_full.full_chat
chat = None

View File

@ -36,6 +36,9 @@ class ChatMember(PyrogramType):
date (``int``, *optional*):
Date when the user joined, unix time. Not available for creator.
is_member (``bool``, *optional*):
Restricted only. True, if the user is a member of the chat at the moment of the request.
invited_by (:obj:`User <pyrogram.User>`, *optional*):
Administrators and self member only. Information about the user who invited this member.
In case the user joined by himself this will be the same as "user".
@ -51,7 +54,7 @@ class ChatMember(PyrogramType):
Information about the member permissions.
"""
__slots__ = ["user", "status", "date", "invited_by", "promoted_by", "restricted_by", "permissions"]
__slots__ = ["user", "status", "date", "is_member", "invited_by", "promoted_by", "restricted_by", "permissions"]
def __init__(
self,
@ -60,6 +63,7 @@ class ChatMember(PyrogramType):
user: "pyrogram.User",
status: str,
date: int = None,
is_member: bool = None,
invited_by: "pyrogram.User" = None,
promoted_by: "pyrogram.User" = None,
restricted_by: "pyrogram.User" = None,
@ -70,6 +74,7 @@ class ChatMember(PyrogramType):
self.user = user
self.status = status
self.date = date
self.is_member = is_member
self.invited_by = invited_by
self.promoted_by = promoted_by
self.restricted_by = restricted_by
@ -123,12 +128,9 @@ class ChatMember(PyrogramType):
if isinstance(member, types.ChannelParticipantBanned):
return ChatMember(
user=user,
status=(
"kicked" if member.banned_rights.view_messages
else "left" if member.left
else "restricted"
),
status="kicked" if member.banned_rights.view_messages else "restricted",
date=member.date,
is_member=not member.left,
restricted_by=pyrogram.User._parse(client, users[member.kicked_by]),
permissions=pyrogram.ChatPermissions._parse(member),
client=client

View File

@ -34,7 +34,7 @@ class Dialog(PyrogramType):
The last message sent in the dialog at this time.
unread_messages_count (``int``):
Amount of unread messages in this dialogs.
Amount of unread messages in this dialog.
unread_mentions_count (``int``):
Amount of unread messages containing a mention in this dialog.