1616# You should have received a copy of the GNU Lesser General Public License
1717# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
1818
19+ from functools import partial
1920from typing import List , Match , Union
2021
2122import pyrogram
2223from pyrogram .api import types
2324from pyrogram .api .errors import MessageIdsEmpty
24- from pyrogram .client .ext import ChatAction
25+ from pyrogram .client .ext import ChatAction , ParseMode
2526from pyrogram .client .types .input_media import InputMedia
2627from .contact import Contact
2728from .location import Location
3334from ..user_and_chats .user import User
3435
3536
37+ class Str (str ):
38+ def __init__ (self , * args ):
39+ super ().__init__ ()
40+
41+ self ._client = None
42+ self ._entities = None
43+
44+ def init (self , client , entities ):
45+ self ._client = client
46+ self ._entities = entities
47+
48+ return self
49+
50+ @property
51+ def text (self ):
52+ return self
53+
54+ @property
55+ def markdown (self ):
56+ return self ._client .markdown .unparse (self , self ._entities )
57+
58+ @property
59+ def html (self ):
60+ return self ._client .html .unparse (self , self ._entities )
61+
62+
3663class Message (PyrogramType , Update ):
3764 """This object represents a message.
3865
@@ -268,7 +295,7 @@ def __init__(
268295 edit_date : int = None ,
269296 media_group_id : str = None ,
270297 author_signature : str = None ,
271- text : str = None ,
298+ text : Str = None ,
272299 entities : List ["pyrogram.MessageEntity" ] = None ,
273300 caption_entities : List ["pyrogram.MessageEntity" ] = None ,
274301 audio : "pyrogram.Audio" = None ,
@@ -280,7 +307,7 @@ def __init__(
280307 video : "pyrogram.Video" = None ,
281308 voice : "pyrogram.Voice" = None ,
282309 video_note : "pyrogram.VideoNote" = None ,
283- caption : str = None ,
310+ caption : Str = None ,
284311 contact : "pyrogram.Contact" = None ,
285312 location : "pyrogram.Location" = None ,
286313 venue : "pyrogram.Venue" = None ,
@@ -2519,7 +2546,13 @@ def edit_reply_markup(self, reply_markup: "pyrogram.InlineKeyboardMarkup" = None
25192546 reply_markup = reply_markup
25202547 )
25212548
2522- def forward (self , chat_id : int or str , disable_notification : bool = None ) -> "Message" :
2549+ def forward (
2550+ self ,
2551+ chat_id : int or str ,
2552+ disable_notification : bool = None ,
2553+ as_copy : bool = False ,
2554+ remove_caption : bool = False
2555+ ) -> "Message" :
25232556 """Bound method *forward* of :obj:`Message <pyrogram.Message>`.
25242557
25252558 Use as a shortcut for:
@@ -2547,18 +2580,120 @@ def forward(self, chat_id: int or str, disable_notification: bool = None) -> "Me
25472580 Sends the message silently.
25482581 Users will receive a notification with no sound.
25492582
2583+ as_copy (``bool``, *optional*):
2584+ Pass True to forward messages without the forward header (i.e.: send a copy of the message content).
2585+ Defaults to False.
2586+
2587+ remove_caption (``bool``, *optional*):
2588+ If set to True and *as_copy* is enabled as well, media captions are not preserved when copying the
2589+ message. Has no effect if *as_copy* is not enabled.
2590+ Defaults to False.
2591+
25502592 Returns:
25512593 On success, the forwarded Message is returned.
25522594
25532595 Raises:
25542596 :class:`Error <pyrogram.Error>`
25552597 """
2556- return self ._client .forward_messages (
2557- chat_id = chat_id ,
2558- from_chat_id = self .chat .id ,
2559- message_ids = self .message_id ,
2560- disable_notification = disable_notification
2561- )
2598+ if as_copy :
2599+ if self .service :
2600+ raise ValueError ("Unable to copy service messages" )
2601+
2602+ if self .game and not self ._client .is_bot :
2603+ raise ValueError ("Users cannot send messages with Game media type" )
2604+
2605+ # TODO: Improve markdown parser. Currently html appears to be more stable, thus we use it here because users
2606+ # can"t choose.
2607+
2608+ if self .text :
2609+ return self ._client .send_message (
2610+ chat_id ,
2611+ text = self .text .html ,
2612+ parse_mode = "html" ,
2613+ disable_web_page_preview = not self .web_page ,
2614+ disable_notification = disable_notification
2615+ )
2616+ elif self .media :
2617+ caption = self .caption .html if self .caption and not remove_caption else None
2618+
2619+ send_media = partial (
2620+ self ._client .send_cached_media ,
2621+ chat_id = chat_id ,
2622+ disable_notification = disable_notification
2623+ )
2624+
2625+ if self .photo :
2626+ file_id = self .photo .sizes [- 1 ].file_id
2627+ elif self .audio :
2628+ file_id = self .audio .file_id
2629+ elif self .document :
2630+ file_id = self .document .file_id
2631+ elif self .video :
2632+ file_id = self .video .file_id
2633+ elif self .animation :
2634+ file_id = self .animation .file_id
2635+ elif self .voice :
2636+ file_id = self .voice .file_id
2637+ elif self .sticker :
2638+ file_id = self .sticker .file_id
2639+ elif self .video_note :
2640+ file_id = self .video_note .file_id
2641+ elif self .contact :
2642+ return self ._client .send_contact (
2643+ chat_id ,
2644+ phone_number = self .contact .phone_number ,
2645+ first_name = self .contact .first_name ,
2646+ last_name = self .contact .last_name ,
2647+ vcard = self .contact .vcard ,
2648+ disable_notification = disable_notification
2649+ )
2650+ elif self .location :
2651+ return self ._client .send_location (
2652+ chat_id ,
2653+ latitude = self .location .latitude ,
2654+ longitude = self .location .longitude ,
2655+ disable_notification = disable_notification
2656+ )
2657+ elif self .venue :
2658+ return self ._client .send_venue (
2659+ chat_id ,
2660+ latitude = self .venue .location .latitude ,
2661+ longitude = self .venue .location .longitude ,
2662+ title = self .venue .title ,
2663+ address = self .venue .address ,
2664+ foursquare_id = self .venue .foursquare_id ,
2665+ foursquare_type = self .venue .foursquare_type ,
2666+ disable_notification = disable_notification
2667+ )
2668+ elif self .poll :
2669+ return self ._client .send_poll (
2670+ chat_id ,
2671+ question = self .poll .question ,
2672+ options = [opt .text for opt in self .poll .options ],
2673+ disable_notification = disable_notification
2674+ )
2675+ elif self .game :
2676+ return self ._client .send_game (
2677+ chat_id ,
2678+ game_short_name = self .game .short_name ,
2679+ disable_notification = disable_notification
2680+ )
2681+ else :
2682+ raise ValueError ("Unknown media type" )
2683+
2684+ if self .sticker or self .video_note : # Sticker and VideoNote should have no caption
2685+ return send_media (file_id )
2686+ else :
2687+ return send_media (file_id = file_id , caption = caption , parse_mode = ParseMode .HTML )
2688+ else :
2689+ raise ValueError ("Can't copy this message" )
2690+ else :
2691+ return self ._client .forward_messages (
2692+ chat_id = chat_id ,
2693+ from_chat_id = self .chat .id ,
2694+ message_ids = self .message_id ,
2695+ disable_notification = disable_notification
2696+ )
25622697
25632698 def delete (self , revoke : bool = True ):
25642699 """Bound method *delete* of :obj:`Message <pyrogram.Message>`.
@@ -2798,29 +2933,3 @@ def pin(self, disable_notification: bool = None) -> "Message":
27982933 message_id = self .message_id ,
27992934 disable_notification = disable_notification
28002935 )
2801-
2802-
2803- class Str (str ):
2804- def __init__ (self , * args ):
2805- super ().__init__ ()
2806-
2807- self .client = None
2808- self .entities = None
2809-
2810- def init (self , client , entities ):
2811- self .client = client
2812- self .entities = entities
2813-
2814- return self
2815-
2816- @property
2817- def text (self ):
2818- return self
2819-
2820- @property
2821- def markdown (self ):
2822- return self .client .markdown .unparse (self , self .entities )
2823-
2824- @property
2825- def html (self ):
2826- return self .client .html .unparse (self , self .entities )
0 commit comments