diff --git a/pyrogram/methods/chats/set_chat_permissions.py b/pyrogram/methods/chats/set_chat_permissions.py index a985175ad..db9ab5cb2 100644 --- a/pyrogram/methods/chats/set_chat_permissions.py +++ b/pyrogram/methods/chats/set_chat_permissions.py @@ -61,12 +61,12 @@ async def set_chat_permissions( # Completely restrict chat await app.set_chat_permissions(chat_id, ChatPermissions()) - # Chat members can only send text messages and media messages + # Chat members can only send text messages and documents await app.set_chat_permissions( chat_id, ChatPermissions( can_send_messages=True, - can_send_media_messages=True + can_send_documents=True ) ) """ diff --git a/pyrogram/methods/users/get_chat_photos.py b/pyrogram/methods/users/get_chat_photos.py index 2ffd0b9bd..b29f8aa2d 100644 --- a/pyrogram/methods/users/get_chat_photos.py +++ b/pyrogram/methods/users/get_chat_photos.py @@ -17,23 +17,15 @@ # along with Pyrogram. If not, see . from asyncio import sleep -from typing import Union, AsyncGenerator, Optional - -import pyrogram -from pyrogram import types, raw - +from typing import Union, AsyncGenerator +from pyrogram import types, raw, utils class GetChatPhotos: async def get_chat_photos( self: "pyrogram.Client", chat_id: Union[int, str], limit: int = 0, - ) -> Optional[ - Union[ - AsyncGenerator["types.Photo", None], - AsyncGenerator["types.Animation", None], - ] - ]: + ) -> AsyncGenerator[Union["types.Photo", "types.Animation"], None]: """Get a chat or a user profile photos sequentially. .. include:: /_includes/usable-by/users-bots.rst @@ -57,20 +49,35 @@ async def get_chat_photos( async for photo in app.get_chat_photos("me"): print(photo) """ + + def get_unique_file_id(media_obj): + """Отримати унікальний file_id для медіа об'єкта""" + if isinstance(media_obj, types.Animation): + return media_obj.file_unique_id + elif isinstance(media_obj, types.Photo) and media_obj.sizes: + return media_obj.sizes[-1].file_unique_id + return None + total = limit or (1 << 31) - limit = min(100, total) + chunk_limit = min(100, total) peer_id = await self.resolve_peer(chat_id) + seen: set[str] = set() if isinstance(peer_id, raw.types.InputPeerChannel): r = await self.invoke(raw.functions.channels.GetFullChannel(channel=peer_id)) + chat_icons = [] _animation = types.Animation._parse_chat_animation(self, r.full_chat.chat_photo) _photo = types.Photo._parse(self, r.full_chat.chat_photo) - chat_icons = [_animation or _photo] + + if _animation: + chat_icons.append(_animation) + elif _photo: + chat_icons.append(_photo) if not (self.me and self.me.is_bot): - r = await self.invoke( + r_messages = await self.invoke( raw.functions.messages.Search( peer=peer_id, q="", @@ -79,43 +86,34 @@ async def get_chat_photos( max_date=0, offset_id=0, add_offset=0, - limit=limit, + limit=chunk_limit, max_id=0, min_id=0, hash=0, ) ) - if _icon := chat_icons[0]: - _first_file_id = _icon.file_id if _animation else _icon.sizes[0].file_id - else: - _first_file_id = None - - for m in getattr(r, "messages", []): - if not isinstance(getattr(m, "action", None), raw.types.MessageActionChatEditPhoto): - continue - - _c_animation = types.Animation._parse_chat_animation(self, m.action.photo) - _c_photo = types.Photo._parse(self, m.action.photo) - - _current_file_id = (_c_animation and _c_animation.file_id) or (_c_photo and _c_photo.sizes[0].file_id) - - if (_c_animation or _c_photo) and _first_file_id != _current_file_id: - chat_icons.append(_c_animation or _c_photo) + messages = await utils.parse_messages(self, r_messages) + for m in messages: + if isinstance(m.new_chat_photo, (types.Animation, types.Photo)): + chat_icons.append(m.new_chat_photo) current = 0 - for icon in chat_icons: await sleep(0) - if not icon: continue + + file_unique_id = get_unique_file_id(icon) + + if not file_unique_id or file_unique_id in seen: + continue + seen.add(file_unique_id) yield icon - current += 1 - - if current >= limit: + if current >= total: return + else: current = 0 offset = 0 @@ -123,16 +121,22 @@ async def get_chat_photos( while True: r = await self.invoke( raw.functions.photos.GetUserPhotos( - user_id=peer_id, offset=offset, max_id=0, limit=limit + user_id=peer_id, + offset=offset, + max_id=0, + limit=chunk_limit ) ) photos = [] - for photo in r.photos: - photos.append( - types.Animation._parse_chat_animation(self, photo) - or types.Photo._parse(self, photo) - ) + for p in r.photos: + _animation = types.Animation._parse_chat_animation(self, p) + _photo = types.Photo._parse(self, p) + + if _animation: + photos.append(_animation) + elif _photo: + photos.append(_photo) if not photos: return @@ -141,13 +145,14 @@ async def get_chat_photos( for photo in photos: await sleep(0) - - if not photo: + + file_unique_id = get_unique_file_id(photo) + + if not file_unique_id or file_unique_id in seen: continue - + + seen.add(file_unique_id) yield photo - current += 1 - if current >= total: return diff --git a/pyrogram/types/user_and_chats/chat_permissions.py b/pyrogram/types/user_and_chats/chat_permissions.py index 07b655caf..3c8473d73 100644 --- a/pyrogram/types/user_and_chats/chat_permissions.py +++ b/pyrogram/types/user_and_chats/chat_permissions.py @@ -78,6 +78,7 @@ class ChatPermissions(Object): def __init__( self, *, + can_send_plain: bool = None, can_send_messages: bool = None, # Text, contacts, giveaways, giveaway winners, invoices, locations and venues can_send_audios: bool = None, can_send_documents: bool = None, @@ -96,6 +97,7 @@ def __init__( ): super().__init__(None) + self.can_send_plain = can_send_plain self.can_send_messages = can_send_messages self.can_send_audios = can_send_audios self.can_send_documents = can_send_documents @@ -114,6 +116,7 @@ def __init__( @staticmethod def _parse(denied_permissions: "raw.base.ChatBannedRights") -> "ChatPermissions": + can_send_plain = False can_send_messages = False can_send_audios = False can_send_documents = False @@ -131,6 +134,7 @@ def _parse(denied_permissions: "raw.base.ChatBannedRights") -> "ChatPermissions" can_send_media_messages = False if isinstance(denied_permissions, raw.types.ChatBannedRights): + can_send_plain = not denied_permissions.send_plain can_send_messages = not denied_permissions.send_messages can_send_polls = not denied_permissions.send_polls can_send_other_messages = any([ @@ -171,6 +175,7 @@ def _parse(denied_permissions: "raw.base.ChatBannedRights") -> "ChatPermissions" can_send_voice_notes = can_send_media_messages return ChatPermissions( + can_send_plain=can_send_plain, can_send_messages=can_send_messages, can_send_audios=can_send_audios, can_send_documents=can_send_documents, @@ -217,5 +222,6 @@ def write( send_videos=not permissions.can_send_videos,# TODO send_roundvideos=not permissions.can_send_video_notes,# TODO send_voices=not permissions.can_send_voice_notes,# TODO + send_plain=not permissions.can_send_plain# TODO # send_plain=# TODO )