diff --git a/pyrogram/methods/users/get_chat_photos.py b/pyrogram/methods/users/get_chat_photos.py
index 05dfd92d..64e56cee 100644
--- a/pyrogram/methods/users/get_chat_photos.py
+++ b/pyrogram/methods/users/get_chat_photos.py
@@ -16,6 +16,7 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see .
+from datetime import datetime
from typing import Union, AsyncGenerator, Optional
import pyrogram
@@ -27,7 +28,12 @@ class GetChatPhotos:
self: "pyrogram.Client",
chat_id: Union[int, str],
limit: int = 0,
- ) -> AsyncGenerator["types.Photo", None]:
+ ) -> Optional[
+ Union[
+ AsyncGenerator["types.Photo", None],
+ AsyncGenerator["types.Animation", None]
+ ]
+ ]:
"""Get a chat or a user profile photos sequentially.
.. include:: /_includes/usable-by/users-bots.rst
@@ -43,7 +49,7 @@ class GetChatPhotos:
By default, no limit is applied and all profile photos are returned.
Returns:
- ``Generator``: A generator yielding :obj:`~pyrogram.types.Photo` objects.
+ ``Generator``: A generator yielding :obj:`~pyrogram.types.Photo` | :obj:`~pyrogram.types.Animation` objects.
Example:
.. code-block:: python
@@ -60,39 +66,45 @@ class GetChatPhotos:
)
)
- current = types.Photo._parse(self, r.full_chat.chat_photo) or []
-
- r = await utils.parse_messages(
+ current = types.Animation._parse_chat_animation(
self,
- await self.invoke(
- raw.functions.messages.Search(
- peer=peer_id,
- q="",
- filter=raw.types.InputMessagesFilterChatPhotos(),
- min_date=0,
- max_date=0,
- offset_id=0,
- add_offset=0,
- limit=limit,
- max_id=0,
- min_id=0,
- hash=0
+ r.full_chat.chat_photo,
+ f"photo_{datetime.now().strftime('%Y-%m-%d_%H-%M-%S')}.mp4"
+ ) or types.Photo._parse(self, r.full_chat.chat_photo) or []
+ current = [current]
+
+ if not self.me.is_bot:
+ r = await utils.parse_messages(
+ self,
+ await self.invoke(
+ raw.functions.messages.Search(
+ peer=peer_id,
+ q="",
+ filter=raw.types.InputMessagesFilterChatPhotos(),
+ min_date=0,
+ max_date=0,
+ offset_id=0,
+ add_offset=0,
+ limit=limit,
+ max_id=0,
+ min_id=0,
+ hash=0
+ )
)
)
- )
- extra = [message.new_chat_photo for message in r]
+ extra = [message.new_chat_photo for message in r]
- if extra:
- if current:
- photos = ([current] + extra) if current.file_id != extra[0].file_id else extra
+ if extra:
+ if current:
+ photos = (current + extra) if current[0].file_id != extra[0].file_id else extra
+ else:
+ photos = extra
else:
- photos = extra
- else:
- if current:
- photos = [current]
- else:
- photos = []
+ if current:
+ photos = current
+ else:
+ photos = []
current = 0
@@ -119,7 +131,14 @@ class GetChatPhotos:
)
)
- photos = [types.Photo._parse(self, photo) for photo in r.photos]
+ photos = [
+ types.Animation._parse_chat_animation(
+ self,
+ photo,
+ f"photo_{datetime.now().strftime('%Y-%m-%d_%H-%M-%S')}.mp4"
+ ) or types.Photo._parse(self, photo)
+ for photo in r.photos
+ ]
if not photos:
return
diff --git a/pyrogram/types/messages_and_media/animation.py b/pyrogram/types/messages_and_media/animation.py
index 1e7bf4cf..fa735e75 100644
--- a/pyrogram/types/messages_and_media/animation.py
+++ b/pyrogram/types/messages_and_media/animation.py
@@ -17,12 +17,12 @@
# along with Pyrogram. If not, see .
from datetime import datetime
-from typing import List
+from typing import List, Optional
import pyrogram
from pyrogram import raw, utils
from pyrogram import types
-from pyrogram.file_id import FileId, FileType, FileUniqueId, FileUniqueType
+from pyrogram.file_id import FileId, FileType, FileUniqueId, FileUniqueType, ThumbnailSource
from ..object import Object
@@ -99,7 +99,7 @@ class Animation(Object):
) -> "Animation":
return Animation(
file_id=FileId(
- file_type=FileType.ANIMATION,
+ file_type=FileType.PHOTO,
dc_id=animation.dc_id,
media_id=animation.id,
access_hash=animation.access_hash,
@@ -119,3 +119,50 @@ class Animation(Object):
thumbs=types.Thumbnail._parse(client, animation),
client=client
)
+
+ @staticmethod
+ def _parse_chat_animation(
+ client,
+ video: "raw.types.Photo",
+ file_name: str
+ ) -> Optional["Animation"]:
+ if isinstance(video, raw.types.Photo):
+ if not video.video_sizes:
+ return None
+
+ videos: List[raw.types.VideoSize] = []
+
+ for v in video.video_sizes:
+ if isinstance(v, raw.types.VideoSize):
+ videos.append(v)
+
+ videos.sort(key=lambda v: v.size)
+
+ main = videos[-1]
+
+ return Animation(
+ file_id=FileId(
+ file_type=FileType.PHOTO,
+ dc_id=video.dc_id,
+ media_id=video.id,
+ access_hash=video.access_hash,
+ file_reference=video.file_reference,
+ thumbnail_source=ThumbnailSource.THUMBNAIL,
+ thumbnail_file_type=FileType.PHOTO,
+ thumbnail_size=main.type,
+ volume_id=0,
+ local_id=0
+ ).encode(),
+ file_unique_id=FileUniqueId(
+ file_unique_type=FileUniqueType.DOCUMENT,
+ media_id=video.id
+ ).encode(),
+ width=main.w,
+ height=main.h,
+ duration=0,
+ file_size=main.size,
+ date=utils.timestamp_to_datetime(video.date),
+ file_name=file_name,
+ mime_type="video/mp4",
+ client=client
+ )
diff --git a/pyrogram/types/user_and_chats/chat_photo.py b/pyrogram/types/user_and_chats/chat_photo.py
index b3aba61d..4e73b34a 100644
--- a/pyrogram/types/user_and_chats/chat_photo.py
+++ b/pyrogram/types/user_and_chats/chat_photo.py
@@ -43,6 +43,12 @@ class ChatPhoto(Object):
big_photo_unique_id (``str``):
Unique file identifier of big (640x640) chat photo, which is supposed to be the same over time and for
different accounts. Can't be used to download or reuse the file.
+
+ has_animation (``bool``):
+ True, if animated profile picture is available for this user.
+
+ is_personal (``bool``):
+ True, if the photo is visible only for the current user.
"""
def __init__(
@@ -52,8 +58,9 @@ class ChatPhoto(Object):
small_file_id: str,
small_photo_unique_id: str,
big_file_id: str,
- big_photo_unique_id: str
-
+ big_photo_unique_id: str,
+ has_animation: bool,
+ is_personal: bool
):
super().__init__(client)
@@ -61,6 +68,8 @@ class ChatPhoto(Object):
self.small_photo_unique_id = small_photo_unique_id
self.big_file_id = big_file_id
self.big_photo_unique_id = big_photo_unique_id
+ self.has_animation = has_animation
+ self.is_personal = is_personal
@staticmethod
def _parse(
@@ -103,5 +112,7 @@ class ChatPhoto(Object):
file_unique_type=FileUniqueType.DOCUMENT,
media_id=chat_photo.photo_id
).encode(),
+ has_animation=chat_photo.has_video,
+ is_personal=getattr(chat_photo, "personal", False),
client=client
)