diff --git a/compiler/docs/compiler.py b/compiler/docs/compiler.py index dd857fc3..9d1b7434 100644 --- a/compiler/docs/compiler.py +++ b/compiler/docs/compiler.py @@ -213,7 +213,6 @@ def pyrogram_api(): get_chat_members get_chat_members_count get_dialogs - iter_dialogs get_dialogs_count set_chat_username get_nearby_chats @@ -238,9 +237,8 @@ def pyrogram_api(): Users get_me get_users - get_profile_photos - get_profile_photos_count - iter_profile_photos + get_chat_photos + get_chat_photos_count set_profile_photo delete_profile_photos set_username diff --git a/pyrogram/methods/chats/__init__.py b/pyrogram/methods/chats/__init__.py index 1b744a05..a2bdde08 100644 --- a/pyrogram/methods/chats/__init__.py +++ b/pyrogram/methods/chats/__init__.py @@ -36,7 +36,6 @@ from .get_dialogs import GetDialogs from .get_dialogs_count import GetDialogsCount from .get_nearby_chats import GetNearbyChats from .get_send_as_chats import GetSendAsChats -from .iter_dialogs import IterDialogs from .join_chat import JoinChat from .leave_chat import LeaveChat from .mark_chat_unread import MarkChatUnread @@ -76,7 +75,6 @@ class Chats( UnpinChatMessage, GetDialogs, GetChatMembersCount, - IterDialogs, SetChatUsername, SetChatPermissions, GetDialogsCount, diff --git a/pyrogram/methods/chats/get_dialogs.py b/pyrogram/methods/chats/get_dialogs.py index f888c3ef..2869a6a1 100644 --- a/pyrogram/methods/chats/get_dialogs.py +++ b/pyrogram/methods/chats/get_dialogs.py @@ -16,92 +16,87 @@ # You should have received a copy of the GNU Lesser General Public License # along with Pyrogram. If not, see . -import logging -from datetime import datetime -from typing import List +from typing import AsyncGenerator, Optional import pyrogram -from pyrogram import raw -from pyrogram import types -from pyrogram import utils - -log = logging.getLogger(__name__) +from pyrogram import types, raw, utils class GetDialogs: async def get_dialogs( self: "pyrogram.Client", - offset_date: datetime = datetime.fromtimestamp(0), - limit: int = 100, - pinned_only: bool = False - ) -> List["types.Dialog"]: - """Get a chunk of the user's dialogs. - - You can get up to 100 dialogs at once. - For a more convenient way of getting a user's dialogs see :meth:`~pyrogram.Client.iter_dialogs`. + limit: int = 0 + ) -> Optional[AsyncGenerator["types.Dialog", None]]: + """Get a user's dialogs sequentially. Parameters: - offset_date (:py:obj:`~datetime.datetime`): - The offset date taken from the top message of a :obj:`~pyrogram.types.Dialog`. - Defaults to epoch. Valid for non-pinned dialogs only. - - limit (``str``, *optional*): + limit (``int``, *optional*): Limits the number of dialogs to be retrieved. - Defaults to 100. Valid for non-pinned dialogs only. - - pinned_only (``bool``, *optional*): - Pass True if you want to get only pinned dialogs. - Defaults to False. + By default, no limit is applied and all dialogs are returned. Returns: - List of :obj:`~pyrogram.types.Dialog`: On success, a list of dialogs is returned. + ``Generator``: A generator yielding :obj:`~pyrogram.types.Dialog` objects. Example: .. code-block:: python - # Get first 100 dialogs - await app.get_dialogs() - - # Get pinned dialogs - await app.get_dialogs(pinned_only=True) + # Iterate through all dialogs + async for dialog in app.get_dialogs(): + print(dialog.chat.first_name or dialog.chat.title) """ + current = 0 + total = limit or (1 << 31) - 1 + limit = min(100, total) - if pinned_only: - r = await self.invoke( - raw.functions.messages.GetPinnedDialogs(folder_id=0), - sleep_threshold=60 - ) - else: + offset_date = 0 + offset_id = 0 + offset_peer = raw.types.InputPeerEmpty() + + while True: r = await self.invoke( raw.functions.messages.GetDialogs( - offset_date=utils.datetime_to_timestamp(offset_date), - offset_id=0, - offset_peer=raw.types.InputPeerEmpty(), + offset_date=offset_date, + offset_id=offset_id, + offset_peer=offset_peer, limit=limit, - hash=0, - exclude_pinned=True + hash=0 ), sleep_threshold=60 ) - users = {i.id: i for i in r.users} - chats = {i.id: i for i in r.chats} + users = {i.id: i for i in r.users} + chats = {i.id: i for i in r.chats} - messages = {} + messages = {} - for message in r.messages: - if isinstance(message, raw.types.MessageEmpty): - continue + for message in r.messages: + if isinstance(message, raw.types.MessageEmpty): + continue - chat_id = utils.get_peer_id(message.peer_id) - messages[chat_id] = await types.Message._parse(self, message, users, chats) + chat_id = utils.get_peer_id(message.peer_id) + messages[chat_id] = await types.Message._parse(self, message, users, chats) - parsed_dialogs = [] + dialogs = [] - for dialog in r.dialogs: - if not isinstance(dialog, raw.types.Dialog): - continue + for dialog in r.dialogs: + if not isinstance(dialog, raw.types.Dialog): + continue - parsed_dialogs.append(types.Dialog._parse(self, dialog, messages, users, chats)) + dialogs.append(types.Dialog._parse(self, dialog, messages, users, chats)) - return types.List(parsed_dialogs) + if not dialogs: + return + + last = dialogs[-1] + + offset_id = last.top_message.id + offset_date = utils.datetime_to_timestamp(last.top_message.date) + offset_peer = await self.resolve_peer(last.chat.id) + + for dialog in dialogs: + yield dialog + + current += 1 + + if current >= total: + return diff --git a/pyrogram/methods/chats/iter_dialogs.py b/pyrogram/methods/chats/iter_dialogs.py deleted file mode 100644 index d0f037be..00000000 --- a/pyrogram/methods/chats/iter_dialogs.py +++ /dev/null @@ -1,106 +0,0 @@ -# Pyrogram - Telegram MTProto API Client Library for Python -# Copyright (C) 2017-present Dan -# -# 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 . - -from typing import AsyncGenerator, Optional - -import pyrogram -from pyrogram import types, raw, utils - - -class IterDialogs: - async def iter_dialogs( - self: "pyrogram.Client", - limit: int = 0 - ) -> Optional[AsyncGenerator["types.Dialog", None]]: - """Iterate through a user's dialogs sequentially. - - This convenience method does the same as repeatedly calling :meth:`~pyrogram.Client.get_dialogs` in a loop, - thus saving you from the hassle of setting up boilerplate code. It is useful for getting the whole dialogs list - with a single call. - - Parameters: - limit (``int``, *optional*): - Limits the number of dialogs to be retrieved. - By default, no limit is applied and all dialogs are returned. - - Returns: - ``Generator``: A generator yielding :obj:`~pyrogram.types.Dialog` objects. - - Example: - .. code-block:: python - - # Iterate through all dialogs - async for dialog in app.iter_dialogs(): - print(dialog.chat.first_name or dialog.chat.title) - """ - current = 0 - total = limit or (1 << 31) - 1 - limit = min(100, total) - - offset_date = 0 - offset_id = 0 - offset_peer = raw.types.InputPeerEmpty() - - while True: - r = (await self.invoke( - raw.functions.messages.GetDialogs( - offset_date=offset_date, - offset_id=offset_id, - offset_peer=offset_peer, - limit=limit, - hash=0 - ), - sleep_threshold=60 - )) - - users = {i.id: i for i in r.users} - chats = {i.id: i for i in r.chats} - - messages = {} - - for message in r.messages: - if isinstance(message, raw.types.MessageEmpty): - continue - - chat_id = utils.get_peer_id(message.peer_id) - messages[chat_id] = await types.Message._parse(self, message, users, chats) - - dialogs = [] - - for dialog in r.dialogs: - if not isinstance(dialog, raw.types.Dialog): - continue - - dialogs.append(types.Dialog._parse(self, dialog, messages, users, chats)) - - if not dialogs: - return - - last = dialogs[-1] - - offset_id = last.top_message.id - offset_date = last.top_message.date - offset_peer = await self.resolve_peer(last.chat.id) - - for dialog in dialogs: - yield dialog - - current += 1 - - if current >= total: - return diff --git a/pyrogram/methods/users/__init__.py b/pyrogram/methods/users/__init__.py index 6cd81bc3..2ed719e8 100644 --- a/pyrogram/methods/users/__init__.py +++ b/pyrogram/methods/users/__init__.py @@ -18,12 +18,11 @@ from .block_user import BlockUser from .delete_profile_photos import DeleteProfilePhotos +from .get_chat_photos import GetChatPhotos +from .get_chat_photos_count import GetChatPhotosCount from .get_common_chats import GetCommonChats from .get_me import GetMe -from .get_profile_photos import GetProfilePhotos -from .get_profile_photos_count import GetProfilePhotosCount from .get_users import GetUsers -from .iter_profile_photos import IterProfilePhotos from .set_profile_photo import SetProfilePhoto from .set_username import SetUsername from .unblock_user import UnblockUser @@ -33,14 +32,13 @@ from .update_profile import UpdateProfile class Users( BlockUser, GetCommonChats, - GetProfilePhotos, + GetChatPhotos, SetProfilePhoto, DeleteProfilePhotos, GetUsers, GetMe, SetUsername, - GetProfilePhotosCount, - IterProfilePhotos, + GetChatPhotosCount, UnblockUser, UpdateProfile, ): diff --git a/pyrogram/methods/users/get_profile_photos.py b/pyrogram/methods/users/get_chat_photos.py similarity index 64% rename from pyrogram/methods/users/get_profile_photos.py rename to pyrogram/methods/users/get_chat_photos.py index ba20c89c..d3bc1f1f 100644 --- a/pyrogram/methods/users/get_profile_photos.py +++ b/pyrogram/methods/users/get_chat_photos.py @@ -16,22 +16,19 @@ # You should have received a copy of the GNU Lesser General Public License # along with Pyrogram. If not, see . -from typing import Union, List +from typing import Union, AsyncGenerator, Optional import pyrogram -from pyrogram import raw -from pyrogram import types -from pyrogram import utils +from pyrogram import types, raw, utils -class GetProfilePhotos: - async def get_profile_photos( +class GetChatPhotos: + async def get_chat_photos( self: "pyrogram.Client", chat_id: Union[int, str], - offset: int = 0, - limit: int = 100 - ) -> List["types.Photo"]: - """Get a list of profile pictures for a user or a chat. + limit: int = 0, + ) -> Optional[AsyncGenerator["types.Photo", None]]: + """Get a chat or a user profile photos sequentially. Parameters: chat_id (``int`` | ``str``): @@ -39,28 +36,18 @@ class GetProfilePhotos: 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). - offset (``int``, *optional*): - Sequential number of the first photo to be returned. - By default, all photos are returned. - limit (``int``, *optional*): - Limits the number of photos to be retrieved. - Values between 1—100 are accepted. Defaults to 100. + Limits the number of profile photos to be retrieved. + By default, no limit is applied and all profile photos are returned. Returns: - List of :obj:`~pyrogram.types.Photo`: On success, a list of profile photos is returned. + ``Generator``: A generator yielding :obj:`~pyrogram.types.Photo` objects. Example: .. code-block:: python - # Get the first 100 profile photos of a user - await app.get_profile_photos("me") - - # Get only the first profile photo of a user - await app.get_profile_photos("me", limit=1) - - # Get 3 profile photos of a user, skip the first 5 - await app.get_profile_photos("me", limit=3, offset=5) + async for photo in app.get_chat_photos("me"): + print(photo) """ peer_id = await self.resolve_peer(chat_id) @@ -105,15 +92,42 @@ class GetProfilePhotos: else: photos = [] - return types.List(photos[offset:limit]) - else: - r = await self.invoke( - raw.functions.photos.GetUserPhotos( - user_id=peer_id, - offset=offset, - max_id=0, - limit=limit - ) - ) + current = 0 - return types.List(types.Photo._parse(self, photo) for photo in r.photos) + for photo in photos: + yield photo + + current += 1 + + if current >= limit: + return + else: + current = 0 + total = limit or (1 << 31) + limit = min(100, total) + offset = 0 + + while True: + r = await self.invoke( + raw.functions.photos.GetUserPhotos( + user_id=peer_id, + offset=offset, + max_id=0, + limit=limit + ) + ) + + photos = [types.Photo._parse(self, photo) for photo in r.photos] + + if not photos: + return + + offset += len(photos) + + for photo in photos: + yield photo + + current += 1 + + if current >= total: + return diff --git a/pyrogram/methods/users/get_profile_photos_count.py b/pyrogram/methods/users/get_chat_photos_count.py similarity index 92% rename from pyrogram/methods/users/get_profile_photos_count.py rename to pyrogram/methods/users/get_chat_photos_count.py index 4c0fe5d5..eca186a8 100644 --- a/pyrogram/methods/users/get_profile_photos_count.py +++ b/pyrogram/methods/users/get_chat_photos_count.py @@ -22,12 +22,12 @@ import pyrogram from pyrogram import raw -class GetProfilePhotosCount: - async def get_profile_photos_count( +class GetChatPhotosCount: + async def get_chat_photos_count( self: "pyrogram.Client", chat_id: Union[int, str] ) -> int: - """Get the total count of profile pictures for a user. + """Get the total count of photos for a chat. Parameters: chat_id (``int`` | ``str``): @@ -41,7 +41,7 @@ class GetProfilePhotosCount: Example: .. code-block:: python - count = await app.get_profile_photos_count("me") + count = await app.get_chat_photos_count("me") print(count) """ diff --git a/pyrogram/methods/users/iter_profile_photos.py b/pyrogram/methods/users/iter_profile_photos.py deleted file mode 100644 index 6665bc9b..00000000 --- a/pyrogram/methods/users/iter_profile_photos.py +++ /dev/null @@ -1,82 +0,0 @@ -# Pyrogram - Telegram MTProto API Client Library for Python -# Copyright (C) 2017-present Dan -# -# 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 . - -from typing import Union, AsyncGenerator, Optional - -import pyrogram -from pyrogram import types - - -class IterProfilePhotos: - async def iter_profile_photos( - self: "pyrogram.Client", - chat_id: Union[int, str], - offset: int = 0, - limit: int = 0, - ) -> Optional[AsyncGenerator["types.Photo", None]]: - """Iterate through a chat or a user profile photos sequentially. - - This convenience method does the same as repeatedly calling :meth:`~pyrogram.Client.get_profile_photos` in a - loop, thus saving you from the hassle of setting up boilerplate code. It is useful for getting all the profile - photos with a single call. - - Parameters: - chat_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). - - limit (``int``, *optional*): - Limits the number of profile photos to be retrieved. - By default, no limit is applied and all profile photos are returned. - - offset (``int``, *optional*): - Sequential number of the first profile photo to be returned. - - Returns: - ``Generator``: A generator yielding :obj:`~pyrogram.types.Photo` objects. - - Example: - .. code-block:: python - - async for photo in app.iter_profile_photos("me"): - print(photo) - """ - current = 0 - total = limit or (1 << 31) - limit = min(100, total) - - while True: - photos = await self.get_profile_photos( - chat_id=chat_id, - offset=offset, - limit=limit - ) - - if not photos: - return - - offset += len(photos) - - for photo in photos: - yield photo - - current += 1 - - if current >= total: - return