diff --git a/compiler/docs/compiler.py b/compiler/docs/compiler.py index 406a6a5c..9ae21807 100644 --- a/compiler/docs/compiler.py +++ b/compiler/docs/compiler.py @@ -468,6 +468,8 @@ def pyrogram_api(): stories=""" Stories Story + StoryDeleted + StorySkipped StoriesPrivacy StoryViews """, diff --git a/pyrogram/types/messages_and_media/__init__.py b/pyrogram/types/messages_and_media/__init__.py index 642ec8ab..01aeb229 100644 --- a/pyrogram/types/messages_and_media/__init__.py +++ b/pyrogram/types/messages_and_media/__init__.py @@ -43,11 +43,13 @@ from .web_page import WebPage from .message_reactions import MessageReactions from .message_story import MessageStory from .story import Story +from .story_deleted import StoryDeleted +from .story_skipped import StorySkipped from .story_views import StoryViews from .exported_story_link import ExportedStoryLink __all__ = [ "Animation", "Audio", "Contact", "Document", "Game", "Location", "Message", "MessageEntity", "Photo", "Thumbnail", "StrippedThumbnail", "Poll", "PollOption", "Sticker", "StickerSet", "Venue", "Video", "VideoNote", "Voice", "WebPage", "Dice", - "Reaction", "WebAppData", "MessageReactions", "MessageStory", "Story", "StoryViews", "StoriesPrivacy", "ExportedStoryLink" + "Reaction", "WebAppData", "MessageReactions", "MessageStory", "Story", "StoryDeleted", "StorySkipped", "StoryViews", "StoriesPrivacy", "ExportedStoryLink" ] diff --git a/pyrogram/types/messages_and_media/story.py b/pyrogram/types/messages_and_media/story.py index 29fc701e..21c97937 100644 --- a/pyrogram/types/messages_and_media/story.py +++ b/pyrogram/types/messages_and_media/story.py @@ -142,63 +142,68 @@ class Story(Object, Update): stories: raw.base.StoryItem, peer: Union["raw.types.PeerChannel", "raw.types.PeerUser"] ) -> "Story": - entities = [types.MessageEntity._parse(client, entity, {}) for entity in stories.entities] - entities = types.List(filter(lambda x: x is not None, entities)) - animation = None - photo = None - video = None - from_user = None - sender_chat = None - if stories.media: - if isinstance(stories.media, raw.types.MessageMediaPhoto): - photo = types.Photo._parse(client, stories.media.photo, stories.media.ttl_seconds) - media_type = enums.MessageMediaType.PHOTO - elif isinstance(stories.media, raw.types.MessageMediaDocument): - doc = stories.media.document + if isinstance(stories, raw.types.StoryItem): + entities = [types.MessageEntity._parse(client, entity, {}) for entity in stories.entities] + entities = types.List(filter(lambda x: x is not None, entities)) + animation = None + photo = None + video = None + from_user = None + sender_chat = None + if stories.media: + if isinstance(stories.media, raw.types.MessageMediaPhoto): + photo = types.Photo._parse(client, stories.media.photo, stories.media.ttl_seconds) + media_type = enums.MessageMediaType.PHOTO + elif isinstance(stories.media, raw.types.MessageMediaDocument): + doc = stories.media.document - if isinstance(doc, raw.types.Document): - attributes = {type(i): i for i in doc.attributes} + if isinstance(doc, raw.types.Document): + attributes = {type(i): i for i in doc.attributes} - if raw.types.DocumentAttributeAnimated in attributes: - video_attributes = attributes.get(raw.types.DocumentAttributeVideo, None) - animation = types.Animation._parse(client, doc, video_attributes, None) - media_type = enums.MessageMediaType.ANIMATION - elif raw.types.DocumentAttributeVideo in attributes: - video_attributes = attributes.get(raw.types.DocumentAttributeVideo, None) - video = types.Video._parse(client, doc, video_attributes, None, stories.media.ttl_seconds) - media_type = enums.MessageMediaType.VIDEO - else: - media_type = None + if raw.types.DocumentAttributeAnimated in attributes: + video_attributes = attributes.get(raw.types.DocumentAttributeVideo, None) + animation = types.Animation._parse(client, doc, video_attributes, None) + media_type = enums.MessageMediaType.ANIMATION + elif raw.types.DocumentAttributeVideo in attributes: + video_attributes = attributes.get(raw.types.DocumentAttributeVideo, None) + video = types.Video._parse(client, doc, video_attributes, None, stories.media.ttl_seconds) + media_type = enums.MessageMediaType.VIDEO + else: + media_type = None + else: + media_type = None + if isinstance(peer, raw.types.PeerChannel): + sender_chat = await client.get_chat(peer.channel_id) + elif isinstance(peer, raw.types.InputPeerSelf): + from_user = client.me else: - media_type = None - if isinstance(peer, raw.types.PeerChannel): - sender_chat = await client.get_chat(peer.channel_id) - elif isinstance(peer, raw.types.InputPeerSelf): - from_user = client.me - else: - from_user = await client.get_users(peer.user_id) + from_user = await client.get_users(peer.user_id) - return Story( - id=stories.id, - from_user=from_user, - sender_chat=sender_chat, - date=utils.timestamp_to_datetime(stories.date), - expire_date=utils.timestamp_to_datetime(stories.expire_date), - media=media_type, - has_protected_content=stories.noforwards, - animation=animation, - photo=photo, - video=video, - edited=stories.edited, - pinned=stories.pinned, - public=stories.public, - close_friends=stories.close_friends, - contacts=stories.contacts, - selected_contacts=stories.selected_contacts, - caption=stories.caption, - caption_entities=entities or None, - views=types.StoryViews._parse(stories.views) - ) + return Story( + id=stories.id, + from_user=from_user, + sender_chat=sender_chat, + date=utils.timestamp_to_datetime(stories.date), + expire_date=utils.timestamp_to_datetime(stories.expire_date), + media=media_type, + has_protected_content=stories.noforwards, + animation=animation, + photo=photo, + video=video, + edited=stories.edited, + pinned=stories.pinned, + public=stories.public, + close_friends=stories.close_friends, + contacts=stories.contacts, + selected_contacts=stories.selected_contacts, + caption=stories.caption, + caption_entities=entities or None, + views=types.StoryViews._parse(stories.views) + ) + if isinstance(stories, raw.types.StoryItemSkipped): + return await types.StorySkipped()._parse(client, stories, peer) + if isinstance(stories, raw.types.StoryItemDeleted): + return await types.StoryDeleted()._parse(client, stories, peer) async def reply_text( self, diff --git a/pyrogram/types/messages_and_media/story_deleted.py b/pyrogram/types/messages_and_media/story_deleted.py new file mode 100644 index 00000000..49aa4195 --- /dev/null +++ b/pyrogram/types/messages_and_media/story_deleted.py @@ -0,0 +1,71 @@ +# Pyrofork - Telegram MTProto API Client Library for Python +# Copyright (C) 2022-present Mayuri-Chan +# +# This file is part of Pyrofork. +# +# Pyrofork 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. +# +# Pyrofork 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 Pyrofork. If not, see . + +import pyrogram + +from datetime import datetime +from pyrogram import enums, raw, types, utils +from typing import BinaryIO, Callable, List, Optional, Union +from ..object import Object +from ..update import Update + +class StoryDeleted(Object, Update): + """A deleted story. + + Parameters: + id (``int``): + Unique story identifier. + + from_user (:obj:`~pyrogram.types.User`, *optional*): + Sender of the story. + + sender_chat (:obj:`~pyrogram.types.Chat`, *optional*): + Sender of the story. If the story is from channel. + """ + + def __init__( + self, + *, + client: "pyrogram.Client" = None, + id: int, + from_user: "types.User" = None, + sender_chat: "types.Chat" = None + ): + super().__init__(client) + + self.id = id + + async def _parse( + client: "pyrogram.Client", + stories: raw.base.StoryItem, + peer: Union["raw.types.PeerChannel", "raw.types.PeerUser"] + ) -> "StoryDeleted": + from_user = None + sender_chat = None + if isinstance(peer, raw.types.PeerChannel): + sender_chat = await client.get_chat(peer.channel_id) + elif isinstance(peer, raw.types.InputPeerSelf): + from_user = client.me + else: + from_user = await client.get_users(peer.user_id) + + return StoryDeleted( + id=stories.id, + from_user=from_user, + sender_chat=sender_chat + ) diff --git a/pyrogram/types/messages_and_media/story_skipped.py b/pyrogram/types/messages_and_media/story_skipped.py new file mode 100644 index 00000000..c00bc67a --- /dev/null +++ b/pyrogram/types/messages_and_media/story_skipped.py @@ -0,0 +1,91 @@ +# Pyrofork - Telegram MTProto API Client Library for Python +# Copyright (C) 2022-present Mayuri-Chan +# +# This file is part of Pyrofork. +# +# Pyrofork 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. +# +# Pyrofork 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 Pyrofork. If not, see . + +import pyrogram + +from datetime import datetime +from pyrogram import enums, raw, types, utils +from typing import BinaryIO, Callable, List, Optional, Union +from ..object import Object +from ..update import Update + +class StorySkipped(Object, Update): + """A skipped story. + + Parameters: + id (``int``): + Unique story identifier. + + from_user (:obj:`~pyrogram.types.User`, *optional*): + Sender of the story. + + sender_chat (:obj:`~pyrogram.types.Chat`, *optional*): + Sender of the story. If the story is from channel. + + date (:py:obj:`~datetime.datetime`, *optional*): + Date the story was sent. + + expire_date (:py:obj:`~datetime.datetime`, *optional*): + Date the story will be expired. + + close_friends (``bool``, *optional*): + True, if the Story is shared with close_friends only. + """ + + # TODO: Add Privacy + + def __init__( + self, + *, + client: "pyrogram.Client" = None, + id: int, + from_user: "types.User" = None, + sender_chat: "types.Chat" = None, + date: datetime, + expire_date: datetime, + close_friends: bool = None + ): + super().__init__(client) + + self.id = id + self.date = date + self.expire_date = expire_date + self.close_friends = close_friends + + async def _parse( + client: "pyrogram.Client", + stories: raw.base.StoryItem, + peer: Union["raw.types.PeerChannel", "raw.types.PeerUser"] + ) -> "StorySkipped": + from_user = None + sender_chat = None + if isinstance(peer, raw.types.PeerChannel): + sender_chat = await client.get_chat(peer.channel_id) + elif isinstance(peer, raw.types.InputPeerSelf): + from_user = client.me + else: + from_user = await client.get_users(peer.user_id) + + return StorySkipped( + id=stories.id, + from_user=from_user, + sender_chat=sender_chat, + date=utils.timestamp_to_datetime(stories.date), + expire_date=utils.timestamp_to_datetime(stories.expire_date), + close_friends=stories.close_friends + )