From 045df418dfbfe7858288a0a1f8e287260e5e852d Mon Sep 17 00:00:00 2001 From: Lonami Exo Date: Thu, 20 Feb 2025 18:26:00 +0100 Subject: [PATCH 1/6] Update to v1.39 --- readthedocs/misc/changelog.rst | 31 +++++++++++++++++++++++++++++++ telethon/version.py | 2 +- 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/readthedocs/misc/changelog.rst b/readthedocs/misc/changelog.rst index 0155a934..639af35e 100644 --- a/readthedocs/misc/changelog.rst +++ b/readthedocs/misc/changelog.rst @@ -13,6 +13,37 @@ it can take advantage of new goodies! .. contents:: List of All Versions +New layer (v1.39) +================= + ++------------------------+ +| Scheme layer used: 199 | ++------------------------+ + +`View new and changed raw API methods `__. + +Additions +~~~~~~~~~ + +* ``drop_media_captions`` added to ``forward_messages``, and documented together with ``drop_author``. +* :tl:`InputMediaDocumentExternal` is now recognized when sending albums. + +Enhancements +~~~~~~~~~~~~ + +* ``receive_updates=False`` now covers more cases, however, Telegram is still free to ignore it. +* Better type-hints in several methods. +* Markdown parsing of inline links should cover more cases. +* ``range`` is now considered "list-like" and can be used on e.g. ``ids`` parameters. + +Bug fixes +~~~~~~~~~ + +* Session is now saved after setting the DC. +* Fixed rare crash in entity cache handling when iterating through dialogs. +* Fixed IOError that could occur during automatic resizing of some photos. + + New layer (v1.38) ================= diff --git a/telethon/version.py b/telethon/version.py index f27eec37..75010b87 100644 --- a/telethon/version.py +++ b/telethon/version.py @@ -1,3 +1,3 @@ # Versions should comply with PEP440. # This line is parsed in setup.py: -__version__ = '1.38.1' +__version__ = '1.39.0' From a03a8673e1e89e9f391833188f91f657eaf8d1f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?mart=C3=ADn?= Date: Sun, 2 Mar 2025 18:40:34 +0000 Subject: [PATCH 2/6] Clarify warning when reusing unintended session (#4568) --- telethon/client/auth.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/telethon/client/auth.py b/telethon/client/auth.py index 52d671ac..425789a9 100644 --- a/telethon/client/auth.py +++ b/telethon/client/auth.py @@ -147,14 +147,16 @@ class AuthMethods: if bot_token[:bot_token.find(':')] != str(me.id): warnings.warn( 'the session already had an authorized user so it did ' - 'not login to the bot account using the provided ' - 'bot_token (it may not be using the user you expect)' + 'not login to the bot account using the provided bot_token; ' + 'if you were expecting a different user, check whether ' + 'you are accidentally reusing an existing session' ) elif phone and not callable(phone) and utils.parse_phone(phone) != me.phone: warnings.warn( 'the session already had an authorized user so it did ' - 'not login to the user account using the provided ' - 'phone (it may not be using the user you expect)' + 'not login to the user account using the provided phone; ' + 'if you were expecting a different user, check whether ' + 'you are accidentally reusing an existing session' ) return self From 0c2a3c144b715a4d0b3ec986438409a3cd8908c0 Mon Sep 17 00:00:00 2001 From: Nick80835 <24271245+Nick80835@users.noreply.github.com> Date: Wed, 5 Mar 2025 07:52:12 -0500 Subject: [PATCH 3/6] Make URL regex match anything again Including spaces. --- telethon/extensions/markdown.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telethon/extensions/markdown.py b/telethon/extensions/markdown.py index 032f7eef..b69195ee 100644 --- a/telethon/extensions/markdown.py +++ b/telethon/extensions/markdown.py @@ -22,7 +22,7 @@ DEFAULT_DELIMITERS = { '```': MessageEntityPre } -DEFAULT_URL_RE = re.compile(r'\[([\s\S]+?)\]\((.+?)\)') +DEFAULT_URL_RE = re.compile(r'\[([\s\S]*?)\]\(([\s\S]*?)\)') DEFAULT_URL_FORMAT = '[{0}]({1})' From 0fc9b14674b3235492976188a78e2a46a6cf8588 Mon Sep 17 00:00:00 2001 From: Nick80835 <24271245+Nick80835@users.noreply.github.com> Date: Thu, 6 Mar 2025 12:35:40 -0500 Subject: [PATCH 4/6] Make URL regex match everything except ] Hopefully this is the last time I touch this. --- telethon/extensions/markdown.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telethon/extensions/markdown.py b/telethon/extensions/markdown.py index b69195ee..4dbbe397 100644 --- a/telethon/extensions/markdown.py +++ b/telethon/extensions/markdown.py @@ -22,7 +22,7 @@ DEFAULT_DELIMITERS = { '```': MessageEntityPre } -DEFAULT_URL_RE = re.compile(r'\[([\s\S]*?)\]\(([\s\S]*?)\)') +DEFAULT_URL_RE = re.compile(r'\[([^]]*?)\]\(([\s\S]*?)\)') DEFAULT_URL_FORMAT = '[{0}]({1})' From 6f5556373ff48dbd6f1fb562c7341bd0eaba2a84 Mon Sep 17 00:00:00 2001 From: Nick80835 <24271245+Nick80835@users.noreply.github.com> Date: Fri, 7 Mar 2025 11:47:23 -0500 Subject: [PATCH 5/6] Call getDifference on login to ensure qts is up to date --- telethon/client/auth.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/telethon/client/auth.py b/telethon/client/auth.py index 425789a9..4ac1c805 100644 --- a/telethon/client/auth.py +++ b/telethon/client/auth.py @@ -392,6 +392,16 @@ class AuthMethods: self._authorized = True state = await self(functions.updates.GetStateRequest()) + # the server may send an old qts in getState + difference = await self(functions.updates.GetDifferenceRequest(pts=state.pts, date=state.date, qts=state.qts)) + + if isinstance(difference, types.updates.Difference): + state = difference.state + elif isinstance(difference, types.updates.DifferenceSlice): + state = difference.intermediate_state + elif isinstance(difference, types.updates.DifferenceTooLong): + state.pts = difference.pts + self._message_box.load(SessionState(0, 0, 0, state.pts, state.qts, int(state.date.timestamp()), state.seq, 0), []) return user From 859f7423f231f4965bdf8685db00c3a24e333ceb Mon Sep 17 00:00:00 2001 From: Shrimadhav U K Date: Sat, 8 Mar 2025 21:46:40 +0530 Subject: [PATCH 6/6] Add send_as and effect parameters in high level --- telethon/client/messages.py | 24 +++++++++++++++++++++--- telethon/client/uploads.py | 25 ++++++++++++++++++++++--- 2 files changed, 43 insertions(+), 6 deletions(-) diff --git a/telethon/client/messages.py b/telethon/client/messages.py index 5f0afc61..0097be32 100644 --- a/telethon/client/messages.py +++ b/telethon/client/messages.py @@ -644,6 +644,8 @@ class MessageMethods: schedule: 'hints.DateLike' = None, comment_to: 'typing.Union[int, types.Message]' = None, nosound_video: bool = None, + send_as: typing.Optional['hints.EntityLike'] = None, + message_effect_id: typing.Optional[int] = None ) -> 'types.Message': """ Sends a message to the specified user, chat or channel. @@ -766,6 +768,16 @@ class MessageMethods: on non-video files. This is set to ``True`` for albums, as gifs cannot be sent in albums. + send_as (`entity`): + Unique identifier (int) or username (str) of the chat or channel to send the message as. + You can use this to send the message on behalf of a chat or channel where you have appropriate permissions. + Use the GetSendAs to return the list of message sender identifiers, which can be used to send messages in the chat, + This setting applies to the current message and will remain effective for future messages unless explicitly changed. + To set this behavior permanently for all messages, use SaveDefaultSendAs. + + message_effect_id (`int`, optional): + Unique identifier of the message effect to be added to the message; for private chats only + Returns The sent `custom.Message `. @@ -838,6 +850,7 @@ class MessageMethods: formatting_entities=formatting_entities, comment_to=comment_to, background=background, nosound_video=nosound_video, + send_as=send_as, message_effect_id=message_effect_id ) entity = await self.get_input_entity(entity) @@ -867,7 +880,8 @@ class MessageMethods: buttons=markup, formatting_entities=message.entities, parse_mode=None, # explicitly disable parse_mode to force using even empty formatting_entities - schedule=schedule + schedule=schedule, + send_as=send_as, message_effect_id=message_effect_id ) request = functions.messages.SendMessageRequest( @@ -881,7 +895,9 @@ class MessageMethods: clear_draft=clear_draft, no_webpage=not isinstance( message.media, types.MessageMediaWebPage), - schedule_date=schedule + schedule_date=schedule, + send_as=await self.get_input_entity(send_as) if send_as else None, + effect=message_effect_id ) message = message.message else: @@ -902,7 +918,9 @@ class MessageMethods: silent=silent, background=background, reply_markup=self.build_reply_markup(buttons), - schedule_date=schedule + schedule_date=schedule, + send_as=await self.get_input_entity(send_as) if send_as else None, + effect=message_effect_id ) result = await self(request) diff --git a/telethon/client/uploads.py b/telethon/client/uploads.py index afb1f2c2..45a56a8a 100644 --- a/telethon/client/uploads.py +++ b/telethon/client/uploads.py @@ -140,6 +140,8 @@ class UploadMethods: comment_to: 'typing.Union[int, types.Message]' = None, ttl: int = None, nosound_video: bool = None, + send_as: typing.Optional['hints.EntityLike'] = None, + message_effect_id: typing.Optional[int] = None, **kwargs) -> typing.Union[typing.List[typing.Any], typing.Any]: """ Sends message with the given file to the specified entity. @@ -322,6 +324,16 @@ class UploadMethods: on non-video files. This is set to ``True`` for albums, as gifs cannot be sent in albums. + send_as (`entity`): + Unique identifier (int) or username (str) of the chat or channel to send the message as. + You can use this to send the message on behalf of a chat or channel where you have appropriate permissions. + Use the GetSendAs to return the list of message sender identifiers, which can be used to send messages in the chat, + This setting applies to the current message and will remain effective for future messages unless explicitly changed. + To set this behavior permanently for all messages, use SaveDefaultSendAs. + + message_effect_id (`int`, optional): + Unique identifier of the message effect to be added to the message; for private chats only + Returns The `Message ` (or messages) containing the sent file, or messages if a list of them was passed. @@ -421,6 +433,7 @@ class UploadMethods: parse_mode=parse_mode, silent=silent, schedule=schedule, supports_streaming=supports_streaming, clear_draft=clear_draft, force_document=force_document, background=background, + send_as=send_as, message_effect_id=message_effect_id ) file = file[10:] captions = captions[10:] @@ -455,7 +468,9 @@ class UploadMethods: entity, media, reply_to=reply_to, message=caption, entities=msg_entities, reply_markup=markup, silent=silent, schedule_date=schedule, clear_draft=clear_draft, - background=background + background=background, + send_as=await self.get_input_entity(send_as) if send_as else None, + effect=message_effect_id ) return self._get_response_message(request, await self(request), entity) @@ -464,7 +479,9 @@ class UploadMethods: progress_callback=None, reply_to=None, parse_mode=(), silent=None, schedule=None, supports_streaming=None, clear_draft=None, - force_document=False, background=None, ttl=None): + force_document=False, background=None, ttl=None, + send_as: typing.Optional['hints.EntityLike'] = None, + message_effect_id: typing.Optional[int] = None): """Specialized version of .send_file for albums""" # We don't care if the user wants to avoid cache, we will use it # anyway. Why? The cached version will be exactly the same thing @@ -539,7 +556,9 @@ class UploadMethods: request = functions.messages.SendMultiMediaRequest( entity, reply_to=None if reply_to is None else types.InputReplyToMessage(reply_to), multi_media=media, silent=silent, schedule_date=schedule, clear_draft=clear_draft, - background=background + background=background, + send_as=await self.get_input_entity(send_as) if send_as else None, + effect=message_effect_id ) result = await self(request)