From 5b9081cb08b28deeb3756180244882e33747685e Mon Sep 17 00:00:00 2001 From: KurimuzonAkuma Date: Fri, 21 Mar 2025 19:13:59 +0300 Subject: [PATCH] Add LinkPreviewOptions Signed-off-by: wulan17 --- compiler/docs/compiler.py | 1 + pyrogram/methods/messages/edit_inline_text.py | 18 +++- .../methods/messages/edit_message_text.py | 19 ++-- pyrogram/methods/messages/send_message.py | 31 +++++-- .../bots_and_keyboards/callback_query.py | 23 +++-- .../input_text_message_content.py | 21 +++-- pyrogram/types/messages_and_media/__init__.py | 2 + .../link_preview_options.py | 87 +++++++++++++++++++ pyrogram/types/messages_and_media/message.py | 36 +++++--- pyrogram/types/messages_and_media/story.py | 10 ++- pyrogram/types/messages_and_media/web_page.py | 1 + 11 files changed, 205 insertions(+), 44 deletions(-) create mode 100644 pyrogram/types/messages_and_media/link_preview_options.py diff --git a/compiler/docs/compiler.py b/compiler/docs/compiler.py index 23157631..a73ca043 100644 --- a/compiler/docs/compiler.py +++ b/compiler/docs/compiler.py @@ -530,6 +530,7 @@ def pyrogram_api(): Voice VideoNote Contact + LinkPreviewOptions Location Venue Sticker diff --git a/pyrogram/methods/messages/edit_inline_text.py b/pyrogram/methods/messages/edit_inline_text.py index b22dbc07..67daa06f 100644 --- a/pyrogram/methods/messages/edit_inline_text.py +++ b/pyrogram/methods/messages/edit_inline_text.py @@ -17,14 +17,15 @@ # You should have received a copy of the GNU Lesser General Public License # along with Pyrofork. If not, see . +import logging from typing import Optional import pyrogram -from pyrogram import raw, enums -from pyrogram import types -from pyrogram import utils +from pyrogram import enums, raw, types, utils + from .inline_session import get_session +log = logging.getLogger(__name__) class EditInlineText: async def edit_inline_text( @@ -32,6 +33,7 @@ class EditInlineText: inline_message_id: str, text: str, parse_mode: Optional["enums.ParseMode"] = None, + link_preview_options: "types.LinkPreviewOptions" = None, disable_web_page_preview: bool = None, reply_markup: "types.InlineKeyboardMarkup" = None, invert_media: bool = None @@ -51,6 +53,9 @@ class EditInlineText: By default, texts are parsed using both Markdown and HTML styles. You can combine both syntaxes together. + link_preview_options (:obj:`~pyrogram.types.LinkPreviewOptions`, *optional*): + Options used for link preview generation for the message. + disable_web_page_preview (``bool``, *optional*): Disables link previews for links in this message. @@ -77,6 +82,11 @@ class EditInlineText: inline_message_id, message.text, disable_web_page_preview=True) """ + if disable_web_page_preview is not None: + log.warning( + "`disable_web_page_preview` is deprecated and will be removed in future updates. Use `link_preview_options` instead." + ) + link_preview_options = types.LinkPreviewOptions(is_disabled=disable_web_page_preview) unpacked = utils.unpack_inline_message_id(inline_message_id) dc_id = unpacked.dc_id @@ -86,7 +96,7 @@ class EditInlineText: return await session.invoke( raw.functions.messages.EditInlineBotMessage( id=unpacked, - no_webpage=disable_web_page_preview or None, + no_webpage=getattr(link_preview_options, "is_disabled", None) or None, reply_markup=await reply_markup.write(self) if reply_markup else None, **await self.parser.parse(text, parse_mode), invert_media=invert_media diff --git a/pyrogram/methods/messages/edit_message_text.py b/pyrogram/methods/messages/edit_message_text.py index 31f4eb47..e07bd202 100644 --- a/pyrogram/methods/messages/edit_message_text.py +++ b/pyrogram/methods/messages/edit_message_text.py @@ -17,12 +17,13 @@ # You should have received a copy of the GNU Lesser General Public License # along with Pyrofork. If not, see . +import logging from typing import Union, List, Optional import pyrogram -from pyrogram import raw, enums -from pyrogram import types -from pyrogram import utils +from pyrogram import enums, raw, types, utils + +log = logging.getLogger(__name__) class EditMessageText: @@ -33,6 +34,7 @@ class EditMessageText: text: str, parse_mode: Optional["enums.ParseMode"] = None, entities: List["types.MessageEntity"] = None, + link_preview_options: "types.LinkPreviewOptions" = None, disable_web_page_preview: bool = None, invert_media: bool = None, reply_markup: "types.InlineKeyboardMarkup" = None, @@ -62,8 +64,8 @@ class EditMessageText: entities (List of :obj:`~pyrogram.types.MessageEntity`): List of special entities that appear in message text, which can be specified instead of *parse_mode*. - disable_web_page_preview (``bool``, *optional*): - Disables link previews for links in this message. + link_preview_options (:obj:`~pyrogram.types.LinkPreviewOptions`, *optional*): + Options used for link preview generation for the message. invert_media (``bool``, *optional*): Inverts the position of the media and caption. @@ -89,11 +91,16 @@ class EditMessageText: chat_id, message_id, message.text, disable_web_page_preview=True) """ + if disable_web_page_preview is not None: + log.warning( + "`disable_web_page_preview` is deprecated and will be removed in future updates. Use `link_preview_options` instead." + ) + link_preview_options = types.LinkPreviewOptions(is_disabled=disable_web_page_preview) rpc = raw.functions.messages.EditMessage( peer=await self.resolve_peer(chat_id), id=message_id, - no_webpage=disable_web_page_preview or None, + no_webpage=getattr(link_preview_options, "is_disabled", None) or None, invert_media=invert_media, reply_markup=await reply_markup.write(self) if reply_markup else None, **await utils.parse_text_entities(self, text, parse_mode, entities) diff --git a/pyrogram/methods/messages/send_message.py b/pyrogram/methods/messages/send_message.py index c8547f30..7a218980 100644 --- a/pyrogram/methods/messages/send_message.py +++ b/pyrogram/methods/messages/send_message.py @@ -17,12 +17,14 @@ # You should have received a copy of the GNU Lesser General Public License # along with Pyrofork. If not, see . +import logging from datetime import datetime -from typing import Union, List, Optional +from typing import List, Optional, Union import pyrogram -from pyrogram import raw, utils, enums -from pyrogram import types +from pyrogram import enums, raw, types, utils + +log = logging.getLogger(__name__) class SendMessage: @@ -32,7 +34,7 @@ class SendMessage: text: str, parse_mode: Optional["enums.ParseMode"] = None, entities: List["types.MessageEntity"] = None, - disable_web_page_preview: bool = None, + link_preview_options: "types.LinkPreviewOptions" = None, disable_notification: bool = None, message_thread_id: int = None, business_connection_id: str = None, @@ -51,7 +53,8 @@ class SendMessage: "types.ReplyKeyboardMarkup", "types.ReplyKeyboardRemove", "types.ForceReply" - ] = None + ] = None, + disable_web_page_preview: bool = None, # TODO: Remove later ) -> "types.Message": """Send text messages. @@ -74,8 +77,8 @@ class SendMessage: entities (List of :obj:`~pyrogram.types.MessageEntity`): List of special entities that appear in message text, which can be specified instead of *parse_mode*. - disable_web_page_preview (``bool``, *optional*): - Disables link previews for links in this message. + link_preview_options (:obj:`~pyrogram.types.LinkPreviewOptions`, *optional*): + Options used for link preview generation for the message. disable_notification (``bool``, *optional*): Sends the message silently. @@ -166,6 +169,16 @@ class SendMessage: """ message, entities = (await utils.parse_text_entities(self, text, parse_mode, entities)).values() + + if disable_web_page_preview is not None or invert_media is not None: + if disable_web_page_preview is not None: + log.warning( + "`disable_web_page_preview` is deprecated and will be removed in future updates. Use `link_preview_options` instead." + ) + link_preview_options = types.LinkPreviewOptions( + is_disabled=disable_web_page_preview, + invert_media=invert_media + ) reply_to = await utils.get_reply_to( client=self, @@ -181,7 +194,7 @@ class SendMessage: rpc = raw.functions.messages.SendMessage( peer=await self.resolve_peer(chat_id), - no_webpage=disable_web_page_preview or None, + no_webpage=getattr(link_preview_options, "is_disabled", None) or None, silent=disable_notification or None, reply_to=reply_to, random_id=self.rnd_id(), @@ -191,7 +204,7 @@ class SendMessage: entities=entities, noforwards=protect_content, allow_paid_floodskip=allow_paid_broadcast, - invert_media=invert_media, + invert_media=getattr(link_preview_options, "invert_media", None) or None, effect=message_effect_id, ) if business_connection_id is not None: diff --git a/pyrogram/types/bots_and_keyboards/callback_query.py b/pyrogram/types/bots_and_keyboards/callback_query.py index 1491497b..a18cc71e 100644 --- a/pyrogram/types/bots_and_keyboards/callback_query.py +++ b/pyrogram/types/bots_and_keyboards/callback_query.py @@ -17,15 +17,18 @@ # You should have received a copy of the GNU Lesser General Public License # along with Pyrofork. If not, see . -from typing import Union, List, Match, Optional +import logging +from typing import List, Match, Optional, Union import pyrogram from pyrogram import raw, enums from pyrogram import types + +from ... import utils from ..object import Object from ..update import Update -from ... import utils +log = logging.getLogger(__name__) class CallbackQuery(Object, Update): """An incoming callback query from a callback button in an inline keyboard. @@ -180,8 +183,9 @@ class CallbackQuery(Object, Update): self, text: str, parse_mode: Optional["enums.ParseMode"] = None, - disable_web_page_preview: bool = None, + link_preview_options: "types.LinkPreviewOptions" = None, reply_markup: "types.InlineKeyboardMarkup" = None, + disable_web_page_preview: bool = None, business_connection_id: Optional[str] = None ) -> Union["types.Message", bool]: """Edit the text of messages attached to callback queries. @@ -196,8 +200,8 @@ class CallbackQuery(Object, Update): By default, texts are parsed using both Markdown and HTML styles. You can combine both syntaxes together. - disable_web_page_preview (``bool``, *optional*): - Disables link previews for links in this message. + link_preview_options (:obj:`~pyrogram.types.LinkPreviewOptions`, *optional*): + Options used for link preview generation for the message. reply_markup (:obj:`~pyrogram.types.InlineKeyboardMarkup`, *optional*): An InlineKeyboardMarkup object. @@ -213,6 +217,12 @@ class CallbackQuery(Object, Update): Raises: RPCError: In case of a Telegram RPC error. """ + if disable_web_page_preview is not None: + log.warning( + "`disable_web_page_preview` is deprecated and will be removed in future updates. Use `link_preview_options` instead." + ) + link_preview_options = types.LinkPreviewOptions(is_disabled=disable_web_page_preview) + if self.inline_message_id is None: return await self._client.edit_message_text( chat_id=self.message.chat.id, @@ -220,6 +230,7 @@ class CallbackQuery(Object, Update): text=text, parse_mode=parse_mode, disable_web_page_preview=disable_web_page_preview, + link_preview_options=link_preview_options, reply_markup=reply_markup, business_connection_id=getattr(self.message, "business_connection_id", None) ) @@ -228,7 +239,7 @@ class CallbackQuery(Object, Update): inline_message_id=self.inline_message_id, text=text, parse_mode=parse_mode, - disable_web_page_preview=disable_web_page_preview, + link_preview_options=link_preview_options, reply_markup=reply_markup ) diff --git a/pyrogram/types/input_message_content/input_text_message_content.py b/pyrogram/types/input_message_content/input_text_message_content.py index 48ca9dc8..97849bd3 100644 --- a/pyrogram/types/input_message_content/input_text_message_content.py +++ b/pyrogram/types/input_message_content/input_text_message_content.py @@ -17,12 +17,15 @@ # You should have received a copy of the GNU Lesser General Public License # along with Pyrofork. If not, see . -from typing import Optional, List +import logging +from typing import List, Optional import pyrogram -from pyrogram import raw, types, utils, enums +from pyrogram import enums, raw, types, utils + from .input_message_content import InputMessageContent +log = logging.getLogger(__name__) class InputTextMessageContent(InputMessageContent): """Content of a text message to be sent as the result of an inline query. @@ -38,8 +41,8 @@ class InputTextMessageContent(InputMessageContent): entities (List of :obj:`~pyrogram.types.MessageEntity`): List of special entities that appear in message text, which can be specified instead of *parse_mode*. - disable_web_page_preview (``bool``, *optional*): - Disables link previews for links in this message. + link_preview_options (:obj:`~pyrogram.types.LinkPreviewOptions`, *optional*): + Options used for link preview generation for the message. """ def __init__( @@ -47,13 +50,21 @@ class InputTextMessageContent(InputMessageContent): message_text: str, parse_mode: Optional["enums.ParseMode"] = None, entities: List["types.MessageEntity"] = None, + link_preview_options: "types.LinkPreviewOptions" = None, disable_web_page_preview: bool = None ): super().__init__() + if disable_web_page_preview is not None: + log.warning( + "`disable_web_page_preview` is deprecated and will be removed in future updates. Use `link_preview_options` instead." + ) + link_preview_options = types.LinkPreviewOptions(is_disabled=disable_web_page_preview) + self.message_text = message_text self.parse_mode = parse_mode self.entities = entities + self.link_preview_options = link_preview_options self.disable_web_page_preview = disable_web_page_preview async def write(self, client: "pyrogram.Client", reply_markup): @@ -62,7 +73,7 @@ class InputTextMessageContent(InputMessageContent): )).values() return raw.types.InputBotInlineMessageText( - no_webpage=self.disable_web_page_preview or None, + no_webpage=getattr(self.link_preview_options, "is_disabled", None) or None, reply_markup=await reply_markup.write(client) if reply_markup else None, message=message, entities=entities diff --git a/pyrogram/types/messages_and_media/__init__.py b/pyrogram/types/messages_and_media/__init__.py index 6bfb0018..2b56f2c0 100644 --- a/pyrogram/types/messages_and_media/__init__.py +++ b/pyrogram/types/messages_and_media/__init__.py @@ -31,6 +31,7 @@ from .game import Game from .giveaway import Giveaway from .giveaway_launched import GiveawayLaunched from .giveaway_result import GiveawayResult +from .link_preview_options import LinkPreviewOptions from .location import Location from .media_area import MediaArea from .media_area_channel_post import MediaAreaChannelPost @@ -93,6 +94,7 @@ __all__ = [ "Giveaway", "GiveawayLaunched", "GiveawayResult", + "LinkPreviewOptions", "Location", "MediaArea", "MediaAreaChannelPost", diff --git a/pyrogram/types/messages_and_media/link_preview_options.py b/pyrogram/types/messages_and_media/link_preview_options.py new file mode 100644 index 00000000..fe4c9733 --- /dev/null +++ b/pyrogram/types/messages_and_media/link_preview_options.py @@ -0,0 +1,87 @@ +# 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 Optional + +from pyrogram import raw + +from ..object import Object + + +class LinkPreviewOptions(Object): + """Describes the options used for link preview generation. + + Parameters: + is_disabled (``bool``, *optional*): + True, if the link preview is disabled. + + url (``str``, *optional*): + URL to use for the link preview. + If empty, then the first URL found in the message text will be used. + + prefer_small_media (``bool``, *optional*): + True, if the media in the link preview is suppposed to be shrunk. + Ignored if the URL isn't explicitly specified or media size change isn't supported for the preview. + + prefer_large_media (``bool``, *optional*): + True, if the media in the link preview is suppposed to be enlarged. + Ignored if the URL isn't explicitly specified or media size change isn't supported for the preview. + + invert_media (``bool``, *optional*): + True, if the link preview must be shown above the message text. + Otherwise, the link preview will be shown below the message text. + """ + + def __init__( + self, + *, + is_disabled: bool = None, + url: str = None, + prefer_small_media: bool = None, + prefer_large_media: bool = None, + invert_media: bool = None + ): + super().__init__() + + self.is_disabled = is_disabled + self.url = url + self.prefer_small_media = prefer_small_media + self.prefer_large_media = prefer_large_media + self.invert_media = invert_media + + @staticmethod + def _parse( + media: "raw.types.MessageMediaWebPage", + url: str = None, + invert_media: bool = None + ) -> Optional["LinkPreviewOptions"]: + if isinstance(media, raw.types.MessageMediaWebPage) and not isinstance(media.webpage, raw.types.WebPageNotModified): + return LinkPreviewOptions( + is_disabled=False, + url=media.webpage.url, + prefer_small_media=media.force_small_media, + prefer_large_media=media.force_large_media, + invert_media=invert_media, + ) + + if url: + return LinkPreviewOptions( + is_disabled=True, + url=url, + invert_media=invert_media, + ) diff --git a/pyrogram/types/messages_and_media/message.py b/pyrogram/types/messages_and_media/message.py index e62398dd..4c37769a 100644 --- a/pyrogram/types/messages_and_media/message.py +++ b/pyrogram/types/messages_and_media/message.py @@ -242,6 +242,9 @@ class Message(Object, Update): venue (:obj:`~pyrogram.types.Venue`, *optional*): Message is a venue, information about the venue. + link_preview_options (:obj:`~pyrogram.types.LinkPreviewOptions`, *optional*): + Options used for link preview generation for the message. + poll (:obj:`~pyrogram.types.Poll`, *optional*): Message is a native poll, information about the poll. @@ -488,6 +491,7 @@ class Message(Object, Update): contact: "types.Contact" = None, location: "types.Location" = None, venue: "types.Venue" = None, + link_preview_options: "types.LinkPreviewOptions" = None, poll: "types.Poll" = None, dice: "types.Dice" = None, new_chat_members: List["types.User"] = None, @@ -603,6 +607,7 @@ class Message(Object, Update): self.contact = contact self.location = location self.venue = venue + self.link_preview_options = link_preview_options self.poll = poll self.dice = dice self.new_chat_members = new_chat_members @@ -1010,6 +1015,7 @@ class Message(Object, Update): web_page_preview = None sticker = None document = None + link_preview_options = None poll = None dice = None @@ -1122,6 +1128,12 @@ class Message(Object, Update): else: media = None + link_preview_options = types.LinkPreviewOptions._parse( + media, + getattr(getattr(media, "webpage", None), "url", utils.get_first_url(message.message)), + message.invert_media + ) + reply_markup = message.reply_markup if reply_markup: @@ -1205,6 +1217,7 @@ class Message(Object, Update): web_page_preview=web_page_preview, sticker=sticker, document=document, + link_preview_options=link_preview_options, poll=poll, dice=dice, views=message.views, @@ -1406,7 +1419,7 @@ class Message(Object, Update): quote: bool = None, parse_mode: Optional["enums.ParseMode"] = None, entities: List["types.MessageEntity"] = None, - disable_web_page_preview: bool = None, + link_preview_options: "types.LinkPreviewOptions" = None, disable_notification: bool = None, reply_to_message_id: int = None, business_connection_id: str = None, @@ -1418,7 +1431,8 @@ class Message(Object, Update): allow_paid_broadcast: bool = None, message_effect_id: int = None, invert_media: bool = None, - reply_markup=None + reply_markup=None, + disable_web_page_preview: bool = None ) -> "Message": """Bound method *reply_text* of :obj:`~pyrogram.types.Message`. @@ -1458,9 +1472,8 @@ class Message(Object, Update): disable_web_page_preview (``bool``, *optional*): Disables link previews for links in this message. - disable_notification (``bool``, *optional*): - Sends the message silently. - Users will receive a notification with no sound. + link_preview_options (:obj:`~pyrogram.types.LinkPreviewOptions`, *optional*): + Options used for link preview generation for the message. reply_to_message_id (``int``, *optional*): If the message is a reply, ID of the original message. @@ -1533,6 +1546,7 @@ class Message(Object, Update): parse_mode=parse_mode, entities=entities, disable_web_page_preview=disable_web_page_preview, + link_preview_options=link_preview_options, disable_notification=disable_notification, message_thread_id=message_thread_id, reply_to_message_id=reply_to_message_id, @@ -4320,10 +4334,11 @@ class Message(Object, Update): text: str, parse_mode: Optional["enums.ParseMode"] = None, entities: List["types.MessageEntity"] = None, - disable_web_page_preview: bool = None, + link_preview_options: "types.LinkPreviewOptions" = None, invert_media: bool = None, reply_markup: "types.InlineKeyboardMarkup" = None, - business_connection_id: str = None + business_connection_id: str = None, + disable_web_page_preview: bool = None ) -> "Message": """Bound method *edit_text* of :obj:`~pyrogram.types.Message`. @@ -4355,8 +4370,8 @@ class Message(Object, Update): entities (List of :obj:`~pyrogram.types.MessageEntity`): List of special entities that appear in message text, which can be specified instead of *parse_mode*. - disable_web_page_preview (``bool``, *optional*): - Disables link previews for links in this message. + link_preview_options (:obj:`~pyrogram.types.LinkPreviewOptions`, *optional*): + Options used for link preview generation for the message. invert_media (``bool``, *optional*): Inverts the position of the media and caption. @@ -4381,6 +4396,7 @@ class Message(Object, Update): parse_mode=parse_mode, entities=entities, disable_web_page_preview=disable_web_page_preview, + link_preview_options=link_preview_options, invert_media=invert_media, reply_markup=reply_markup, business_connection_id=self.business_connection_id if business_connection_id is None else business_connection_id @@ -4755,7 +4771,7 @@ class Message(Object, Update): text=self.text, entities=self.entities, parse_mode=enums.ParseMode.DISABLED, - disable_web_page_preview=not self.web_page_preview, + link_preview_options=types.LinkPreviewOptions(is_disabled=not self.web_page), disable_notification=disable_notification, message_thread_id=message_thread_id, reply_to_message_id=reply_to_message_id, diff --git a/pyrogram/types/messages_and_media/story.py b/pyrogram/types/messages_and_media/story.py index 91bfbfb4..c4d15e4e 100644 --- a/pyrogram/types/messages_and_media/story.py +++ b/pyrogram/types/messages_and_media/story.py @@ -327,12 +327,13 @@ class Story(Object, Update): text: str, parse_mode: Optional["enums.ParseMode"] = None, entities: List["types.MessageEntity"] = None, - disable_web_page_preview: bool = None, + link_preview_options: "types.LinkPreviewOptions" = None, disable_notification: bool = None, reply_to_story_id: int = None, schedule_date: datetime = None, protect_content: bool = None, - reply_markup=None + reply_markup=None, + disable_web_page_preview: bool = None ) -> "types.Message": """Bound method *reply_text* of :obj:`~pyrogram.types.Story`. @@ -364,8 +365,8 @@ class Story(Object, Update): entities (List of :obj:`~pyrogram.types.MessageEntity`): List of special entities that appear in message text, which can be specified instead of *parse_mode*. - disable_web_page_preview (``bool``, *optional*): - Disables link previews for links in this message. + link_preview_options (:obj:`~pyrogram.types.LinkPreviewOptions`, *optional*): + Options used for link preview generation for the message. disable_notification (``bool``, *optional*): Sends the message silently. @@ -400,6 +401,7 @@ class Story(Object, Update): parse_mode=parse_mode, entities=entities, disable_web_page_preview=disable_web_page_preview, + link_preview_options=link_preview_options, disable_notification=disable_notification, reply_to_story_id=reply_to_story_id, schedule_date=schedule_date, diff --git a/pyrogram/types/messages_and_media/web_page.py b/pyrogram/types/messages_and_media/web_page.py index 47d899c0..b1a16b15 100644 --- a/pyrogram/types/messages_and_media/web_page.py +++ b/pyrogram/types/messages_and_media/web_page.py @@ -22,6 +22,7 @@ from pyrogram import raw from pyrogram import types from ..object import Object +from typing import Optional class WebPage(Object): # TODO: hash, cached_page