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 config.ini
# Pyrogram generated code # Pyrogram generated code
pyrogram/api/errors/exceptions/ pyrogram/errors/exceptions/
pyrogram/api/functions/ pyrogram/api/functions/
pyrogram/api/types/ pyrogram/api/types/
pyrogram/api/all.py pyrogram/api/all.py

View File

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

View File

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

View File

@ -24,7 +24,7 @@ import pyrogram
from pyrogram.api import types from pyrogram.api import types
from ..handlers import ( from ..handlers import (
CallbackQueryHandler, MessageHandler, DeletedMessagesHandler, CallbackQueryHandler, MessageHandler, DeletedMessagesHandler,
UserStatusHandler, RawUpdateHandler, InlineQueryHandler UserStatusHandler, RawUpdateHandler, InlineQueryHandler, PollHandler
) )
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
@ -76,12 +76,16 @@ class Dispatcher:
async def inline_query_parser(update, users, chats): async def inline_query_parser(update, users, chats):
return pyrogram.InlineQuery._parse(self.client, update, users), InlineQueryHandler 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 = { self.update_parsers = {
Dispatcher.MESSAGE_UPDATES: message_parser, Dispatcher.MESSAGE_UPDATES: message_parser,
Dispatcher.DELETE_MESSAGES_UPDATES: deleted_messages_parser, Dispatcher.DELETE_MESSAGES_UPDATES: deleted_messages_parser,
Dispatcher.CALLBACK_QUERY_UPDATES: callback_query_parser, Dispatcher.CALLBACK_QUERY_UPDATES: callback_query_parser,
(types.UpdateUserStatus,): user_status_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} 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 .disconnect_handler import DisconnectHandler
from .inline_query_handler import InlineQueryHandler from .inline_query_handler import InlineQueryHandler
from .message_handler import MessageHandler from .message_handler import MessageHandler
from .poll_handler import PollHandler
from .raw_update_handler import RawUpdateHandler from .raw_update_handler import RawUpdateHandler
from .user_status_handler import UserStatusHandler from .user_status_handler import UserStatusHandler
__all__ = [ __all__ = [
"MessageHandler", "DeletedMessagesHandler", "CallbackQueryHandler", "RawUpdateHandler", "DisconnectHandler", "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 .unban_chat_member import UnbanChatMember
from .unpin_chat_message import UnpinChatMessage from .unpin_chat_message import UnpinChatMessage
from .update_chat_username import UpdateChatUsername from .update_chat_username import UpdateChatUsername
from .get_dialogs_count import GetDialogsCount
class Chats( class Chats(
@ -64,6 +65,7 @@ class Chats(
IterDialogs, IterDialogs,
IterChatMembers, IterChatMembers,
UpdateChatUsername, UpdateChatUsername,
RestrictChat RestrictChat,
GetDialogsCount
): ):
pass 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 .add_contacts import AddContacts
from .delete_contacts import DeleteContacts from .delete_contacts import DeleteContacts
from .get_contacts import GetContacts from .get_contacts import GetContacts
from .get_contacts_count import GetContactsCount
class Contacts( class Contacts(
GetContacts, GetContacts,
DeleteContacts, DeleteContacts,
AddContacts AddContacts,
GetContactsCount
): ):
pass 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_disconnect import OnDisconnect
from .on_inline_query import OnInlineQuery from .on_inline_query import OnInlineQuery
from .on_message import OnMessage from .on_message import OnMessage
from .on_poll import OnPoll
from .on_raw_update import OnRawUpdate from .on_raw_update import OnRawUpdate
from .on_user_status import OnUserStatus from .on_user_status import OnUserStatus
@ -32,6 +33,7 @@ class Decorators(
OnRawUpdate, OnRawUpdate,
OnDisconnect, OnDisconnect,
OnUserStatus, OnUserStatus,
OnInlineQuery OnInlineQuery,
OnPoll
): ):
pass 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 # You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>. # along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
from .close_poll import ClosePoll
from .delete_messages import DeleteMessages from .delete_messages import DeleteMessages
from .download_media import DownloadMedia from .download_media import DownloadMedia
from .edit_message_caption import EditMessageCaption from .edit_message_caption import EditMessageCaption
@ -25,6 +24,7 @@ from .edit_message_reply_markup import EditMessageReplyMarkup
from .edit_message_text import EditMessageText from .edit_message_text import EditMessageText
from .forward_messages import ForwardMessages from .forward_messages import ForwardMessages
from .get_history import GetHistory from .get_history import GetHistory
from .get_history_count import GetHistoryCount
from .get_messages import GetMessages from .get_messages import GetMessages
from .iter_history import IterHistory from .iter_history import IterHistory
from .retract_vote import RetractVote from .retract_vote import RetractVote
@ -44,6 +44,7 @@ from .send_venue import SendVenue
from .send_video import SendVideo from .send_video import SendVideo
from .send_video_note import SendVideoNote from .send_video_note import SendVideoNote
from .send_voice import SendVoice from .send_voice import SendVoice
from .stop_poll import StopPoll
from .vote_poll import VotePoll from .vote_poll import VotePoll
@ -72,10 +73,11 @@ class Messages(
SendVoice, SendVoice,
SendPoll, SendPoll,
VotePoll, VotePoll,
ClosePoll, StopPoll,
RetractVote, RetractVote,
DownloadMedia, DownloadMedia,
IterHistory, IterHistory,
SendCachedMedia SendCachedMedia,
GetHistoryCount
): ):
pass pass

View File

@ -37,7 +37,7 @@ class GetHistory(BaseClient):
offset_id: int = 0, offset_id: int = 0,
offset_date: int = 0, offset_date: int = 0,
reverse: bool = False reverse: bool = False
): ) -> "pyrogram.Messages":
"""Use this method to retrieve a chunk of the history of a chat. """Use this method to retrieve a chunk of the history of a chat.
You can get up to 100 messages at once. 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 from typing import Union
import pyrogram
from pyrogram.api import functions from pyrogram.api import functions
from pyrogram.client.ext import BaseClient from pyrogram.client.ext import BaseClient
class RetractVote(BaseClient): class RetractVote(BaseClient):
def retract_vote( async def retract_vote(
self, self,
chat_id: Union[int, str], chat_id: Union[int, str],
message_id: id message_id: int
) -> bool: ) -> "pyrogram.Poll":
"""Use this method to retract your vote in a poll. """Use this method to retract your vote in a poll.
Args: 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). For a contact that exists in your Telegram address book you can use his phone number (str).
message_id (``int``): message_id (``int``):
Unique poll message identifier inside this chat. Identifier of the original message with the poll.
Returns: Returns:
On success, True is returned. On success, the :obj:`Poll <pyrogram.Poll>` with the retracted vote is returned.
Raises: Raises:
:class:`RPCError <pyrogram.RPCError>` in case of a Telegram RPC error. :class:`RPCError <pyrogram.RPCError>` in case of a Telegram RPC error.
""" """
self.send( r = await self.send(
functions.messages.SendVote( functions.messages.SendVote(
peer=self.resolve_peer(chat_id), peer=await self.resolve_peer(chat_id),
msg_id=message_id, msg_id=message_id,
options=[] options=[]
) )
) )
return True return pyrogram.Poll._parse(self, r.updates[0])

View File

@ -83,7 +83,7 @@ class SendAnimation(BaseClient):
thumb (``str``, *optional*): thumb (``str``, *optional*):
Thumbnail of the animation file sent. Thumbnail of the animation file sent.
The thumbnail should be in JPEG format and less than 200 KB in size. 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. Thumbnails can't be reused and can be only uploaded as a new file.
disable_notification (``bool``, *optional*): disable_notification (``bool``, *optional*):

View File

@ -84,7 +84,7 @@ class SendAudio(BaseClient):
thumb (``str``, *optional*): thumb (``str``, *optional*):
Thumbnail of the music file album cover. Thumbnail of the music file album cover.
The thumbnail should be in JPEG format and less than 200 KB in size. 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. Thumbnails can't be reused and can be only uploaded as a new file.
disable_notification (``bool``, *optional*): disable_notification (``bool``, *optional*):

View File

@ -62,7 +62,7 @@ class SendDocument(BaseClient):
thumb (``str``, *optional*): thumb (``str``, *optional*):
Thumbnail of the file sent. Thumbnail of the file sent.
The thumbnail should be in JPEG format and less than 200 KB in size. 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. Thumbnails can't be reused and can be only uploaded as a new file.
caption (``str``, *optional*): 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). For a contact that exists in your Telegram address book you can use his phone number (str).
question (``str``): question (``str``):
The poll question, as string. Poll question, 1-255 characters.
options (List of ``str``): 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*): disable_notification (``bool``, *optional*):
Sends the message silently. Sends the message silently.

View File

@ -84,7 +84,7 @@ class SendVideo(BaseClient):
thumb (``str``, *optional*): thumb (``str``, *optional*):
Thumbnail of the video sent. Thumbnail of the video sent.
The thumbnail should be in JPEG format and less than 200 KB in size. 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. Thumbnails can't be reused and can be only uploaded as a new file.
supports_streaming (``bool``, *optional*): supports_streaming (``bool``, *optional*):

View File

@ -69,7 +69,7 @@ class SendVideoNote(BaseClient):
thumb (``str``, *optional*): thumb (``str``, *optional*):
Thumbnail of the video sent. Thumbnail of the video sent.
The thumbnail should be in JPEG format and less than 200 KB in size. 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. Thumbnails can't be reused and can be only uploaded as a new file.
disable_notification (``bool``, *optional*): disable_notification (``bool``, *optional*):

View File

@ -18,19 +18,21 @@
from typing import Union from typing import Union
import pyrogram
from pyrogram.api import functions, types from pyrogram.api import functions, types
from pyrogram.client.ext import BaseClient from pyrogram.client.ext import BaseClient
class ClosePoll(BaseClient): class StopPoll(BaseClient):
def close_poll( async def stop_poll(
self, self,
chat_id: Union[int, str], chat_id: Union[int, str],
message_id: id message_id: int,
) -> bool: reply_markup: "pyrogram.InlineKeyboardMarkup" = None
"""Use this method to close (stop) a poll. ) -> "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: Args:
chat_id (``int`` | ``str``): 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). For a contact that exists in your Telegram address book you can use his phone number (str).
message_id (``int``): 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: Returns:
On success, True is returned. On success, the stopped :obj:`Poll <pyrogram.Poll>` with the final results is returned.
Raises: Raises:
:class:`RPCError <pyrogram.RPCError>` in case of a Telegram RPC error. :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( functions.messages.EditMessage(
peer=self.resolve_peer(chat_id), peer=await self.resolve_peer(chat_id),
id=message_id, id=message_id,
media=types.InputMediaPoll( media=types.InputMediaPoll(
poll=types.Poll( poll=types.Poll(
@ -60,8 +65,9 @@ class ClosePoll(BaseClient):
question="", question="",
answers=[] 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 from typing import Union
import pyrogram
from pyrogram.api import functions from pyrogram.api import functions
from pyrogram.client.ext import BaseClient from pyrogram.client.ext import BaseClient
class VotePoll(BaseClient): class VotePoll(BaseClient):
def vote_poll( async def vote_poll(
self, self,
chat_id: Union[int, str], chat_id: Union[int, str],
message_id: id, message_id: id,
option: int option: int
) -> bool: ) -> "pyrogram.Poll":
"""Use this method to vote a poll. """Use this method to vote a poll.
Args: 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). For a contact that exists in your Telegram address book you can use his phone number (str).
message_id (``int``): message_id (``int``):
Unique poll message identifier inside this chat. Identifier of the original message with the poll.
option (``int``): option (``int``):
Index of the poll option you want to vote for (0 to 9). Index of the poll option you want to vote for (0 to 9).
Returns: Returns:
On success, True is returned. On success, the :obj:`Poll <pyrogram.Poll>` with the chosen option is returned.
Raises: Raises:
:class:`RPCError <pyrogram.RPCError>` in case of a Telegram RPC error. :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( functions.messages.SendVote(
peer=self.resolve_peer(chat_id), peer=await self.resolve_peer(chat_id),
msg_id=message_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 .delete_user_profile_photos import DeleteUserProfilePhotos
from .get_me import GetMe from .get_me import GetMe
from .get_user_profile_photos import GetUserProfilePhotos from .get_user_profile_photos import GetUserProfilePhotos
from .get_user_profile_photos_count import GetUserProfilePhotosCount
from .get_users import GetUsers from .get_users import GetUsers
from .set_user_profile_photo import SetUserProfilePhoto from .set_user_profile_photo import SetUserProfilePhoto
from .update_username import UpdateUsername from .update_username import UpdateUsername
@ -30,6 +31,7 @@ class Users(
DeleteUserProfilePhotos, DeleteUserProfilePhotos,
GetUsers, GetUsers,
GetMe, GetMe,
UpdateUsername UpdateUsername,
GetUserProfilePhotosCount
): ):
pass 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*): thumb (``str``, *optional*):
Thumbnail of the animation file sent. Thumbnail of the animation file sent.
The thumbnail should be in JPEG format and less than 200 KB in size. 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. Thumbnails can't be reused and can be only uploaded as a new file.
caption (``str``, *optional*): caption (``str``, *optional*):

View File

@ -32,7 +32,7 @@ class InputMediaAudio(InputMedia):
thumb (``str``, *optional*): thumb (``str``, *optional*):
Thumbnail of the music file album cover. Thumbnail of the music file album cover.
The thumbnail should be in JPEG format and less than 200 KB in size. 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. Thumbnails can't be reused and can be only uploaded as a new file.
caption (``str``, *optional*): caption (``str``, *optional*):

View File

@ -31,7 +31,7 @@ class InputMediaDocument(InputMedia):
thumb (``str``): thumb (``str``):
Thumbnail of the file sent. Thumbnail of the file sent.
The thumbnail should be in JPEG format and less than 200 KB in size. 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. Thumbnails can't be reused and can be only uploaded as a new file.
caption (``str``, *optional*): caption (``str``, *optional*):

View File

@ -33,7 +33,7 @@ class InputMediaVideo(InputMedia):
thumb (``str``): thumb (``str``):
Thumbnail of the video sent. Thumbnail of the video sent.
The thumbnail should be in JPEG format and less than 200 KB in size. 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. Thumbnails can't be reused and can be only uploaded as a new file.
caption (``str``, *optional*): caption (``str``, *optional*):

View File

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

View File

@ -16,91 +16,125 @@
# You should have received a copy of the GNU Lesser General Public License # You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>. # along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
from typing import List from typing import List, Union
import pyrogram import pyrogram
from pyrogram.api import types from pyrogram.api import types
from .poll_option import PollOption from .poll_option import PollOption
from ..pyrogram_type import PyrogramType from ..pyrogram_type import PyrogramType
from ..update import Update
class Poll(PyrogramType): class Poll(PyrogramType, Update):
"""This object represents a Poll. """This object represents a Poll.
Args: Args:
id (``int``): id (``str``):
The poll id in this chat. Unique poll identifier.
closed (``bool``):
Whether the poll is closed or not.
question (``str``): question (``str``):
Poll question. Poll question, 1-255 characters.
options (List of :obj:`PollOption`): 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_voters (``int``):
Total amount of voters for this poll. Total count of voters for this poll.
option_chosen (``int``, *optional*): chosen_option (``int``, *optional*):
The index of your chosen option (in case you voted already), None otherwise. 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__( def __init__(
self, self,
*, *,
client: "pyrogram.client.ext.BaseClient", client: "pyrogram.client.ext.BaseClient",
id: int, id: str,
closed: bool,
question: str, question: str,
options: List[PollOption], options: List[PollOption],
is_closed: bool,
total_voters: int, total_voters: int,
option_chosen: int = None chosen_option: int = None
): ):
super().__init__(client) super().__init__(client)
self.id = id self.id = id
self.closed = closed
self.question = question self.question = question
self.options = options self.options = options
self.is_closed = is_closed
self.total_voters = total_voters self.total_voters = total_voters
self.option_chosen = option_chosen self.chosen_option = chosen_option
@staticmethod @staticmethod
def _parse(client, media_poll: types.MessageMediaPoll) -> "Poll": def _parse(client, media_poll: Union[types.MessageMediaPoll, types.UpdateMessagePoll]) -> "Poll":
poll = media_poll.poll poll = media_poll.poll
results = media_poll.results.results results = media_poll.results.results
total_voters = media_poll.results.total_voters total_voters = media_poll.results.total_voters
option_chosen = None chosen_option = None
options = [] options = []
for i, answer in enumerate(poll.answers): for i, answer in enumerate(poll.answers):
voters = 0 voter_count = 0
if results: if results:
result = results[i] result = results[i]
voters = result.voters voter_count = result.voters
if result.chosen: if result.chosen:
option_chosen = i chosen_option = i
options.append(PollOption( options.append(
text=answer.text, PollOption(
voters=voters, text=answer.text,
data=answer.option, voter_count=voter_count,
client=client data=answer.option,
)) client=client
)
)
return Poll( return Poll(
id=poll.id, id=str(poll.id),
closed=poll.closed,
question=poll.question, question=poll.question,
options=options, options=options,
is_closed=poll.closed,
total_voters=total_voters, 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 client=client
) )

View File

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

View File

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

View File

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

View File

@ -185,6 +185,12 @@ class Chat(PyrogramType):
if isinstance(chat_full, types.UserFull): if isinstance(chat_full, types.UserFull):
parsed_chat = Chat._parse_user_chat(client, chat_full.user) parsed_chat = Chat._parse_user_chat(client, chat_full.user)
parsed_chat.description = chat_full.about 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: else:
full_chat = chat_full.full_chat full_chat = chat_full.full_chat
chat = None chat = None

View File

@ -36,6 +36,9 @@ class ChatMember(PyrogramType):
date (``int``, *optional*): date (``int``, *optional*):
Date when the user joined, unix time. Not available for creator. 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*): invited_by (:obj:`User <pyrogram.User>`, *optional*):
Administrators and self member only. Information about the user who invited this member. 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". 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. 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__( def __init__(
self, self,
@ -60,6 +63,7 @@ class ChatMember(PyrogramType):
user: "pyrogram.User", user: "pyrogram.User",
status: str, status: str,
date: int = None, date: int = None,
is_member: bool = None,
invited_by: "pyrogram.User" = None, invited_by: "pyrogram.User" = None,
promoted_by: "pyrogram.User" = None, promoted_by: "pyrogram.User" = None,
restricted_by: "pyrogram.User" = None, restricted_by: "pyrogram.User" = None,
@ -70,6 +74,7 @@ class ChatMember(PyrogramType):
self.user = user self.user = user
self.status = status self.status = status
self.date = date self.date = date
self.is_member = is_member
self.invited_by = invited_by self.invited_by = invited_by
self.promoted_by = promoted_by self.promoted_by = promoted_by
self.restricted_by = restricted_by self.restricted_by = restricted_by
@ -123,12 +128,9 @@ class ChatMember(PyrogramType):
if isinstance(member, types.ChannelParticipantBanned): if isinstance(member, types.ChannelParticipantBanned):
return ChatMember( return ChatMember(
user=user, user=user,
status=( status="kicked" if member.banned_rights.view_messages else "restricted",
"kicked" if member.banned_rights.view_messages
else "left" if member.left
else "restricted"
),
date=member.date, date=member.date,
is_member=not member.left,
restricted_by=pyrogram.User._parse(client, users[member.kicked_by]), restricted_by=pyrogram.User._parse(client, users[member.kicked_by]),
permissions=pyrogram.ChatPermissions._parse(member), permissions=pyrogram.ChatPermissions._parse(member),
client=client client=client

View File

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