From a1448f3da89ea576a657608e1fe6b605d2018ece Mon Sep 17 00:00:00 2001 From: Tanuj Date: Tue, 3 Apr 2018 12:05:01 +0100 Subject: [PATCH 1/5] Clearer variable names in get_input_entity (#738) --- telethon/sessions/memory.py | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/telethon/sessions/memory.py b/telethon/sessions/memory.py index 5faf721d..330a82c1 100644 --- a/telethon/sessions/memory.py +++ b/telethon/sessions/memory.py @@ -196,14 +196,15 @@ class MemorySession(Session): result = self.get_entity_rows_by_name(key) if result: - i, h = result # unpack resulting tuple - i, k = utils.resolve_id(i) # removes the mark and returns kind - if k == PeerUser: - return InputPeerUser(i, h) - elif k == PeerChat: - return InputPeerChat(i) - elif k == PeerChannel: - return InputPeerChannel(i, h) + entity_id, entity_hash = result # unpack resulting tuple + entity_id, kind = utils.resolve_id(entity_id) + # removes the mark and returns type of entity + if kind == PeerUser: + return InputPeerUser(entity_id, entity_hash) + elif kind == PeerChat: + return InputPeerChat(entity_id) + elif kind == PeerChannel: + return InputPeerChannel(entity_id, entity_hash) else: raise ValueError('Could not find input entity with key ', key) From eabaa3854a76642fa594aaff8e792daf16fcbfd1 Mon Sep 17 00:00:00 2001 From: Lonami Exo Date: Tue, 3 Apr 2018 13:46:54 +0200 Subject: [PATCH 2/5] Replace offset with match.start() to allow custom regex --- 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 680aabda..94a13818 100644 --- a/telethon/extensions/markdown.py +++ b/telethon/extensions/markdown.py @@ -81,7 +81,7 @@ def parse(message, delimiters=None, url_re=None): )) result.append(MessageEntityTextUrl( - offset=i, length=len(url_match.group(1)), + offset=url_match.start(), length=len(url_match.group(1)), url=_del_surrogate(url_match.group(2)) )) i += len(url_match.group(1)) From 07a8a73e3ed6d1a4c69141a3fd8b0703193a0a16 Mon Sep 17 00:00:00 2001 From: Lonami Exo Date: Tue, 3 Apr 2018 14:23:05 +0200 Subject: [PATCH 3/5] Support callable parse_mode's This allows to more easily plug in custom parse methods. --- telethon/telegram_client.py | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/telethon/telegram_client.py b/telethon/telegram_client.py index ca072f4f..08c32b88 100644 --- a/telethon/telegram_client.py +++ b/telethon/telegram_client.py @@ -679,13 +679,18 @@ class TelegramClient(TelegramBareClient): if not parse_mode: return message, [] - parse_mode = parse_mode.lower() - if parse_mode in {'md', 'markdown'}: - message, msg_entities = markdown.parse(message) - elif parse_mode.startswith('htm'): - message, msg_entities = html.parse(message) + if isinstance(parse_mode, str): + parse_mode = parse_mode.lower() + if parse_mode in {'md', 'markdown'}: + message, msg_entities = markdown.parse(message) + elif parse_mode.startswith('htm'): + message, msg_entities = html.parse(message) + else: + raise ValueError('Unknown parsing mode: {}'.format(parse_mode)) + elif callable(parse_mode): + message, msg_entities = parse_mode(message) else: - raise ValueError('Unknown parsing mode: {}'.format(parse_mode)) + raise TypeError('Invalid parsing mode type: {}'.format(parse_mode)) for i, e in enumerate(msg_entities): if isinstance(e, MessageEntityTextUrl): From 55b5fca6fd633ab5ac92899fba9c0e5eea58869d Mon Sep 17 00:00:00 2001 From: Lonami Exo Date: Wed, 4 Apr 2018 10:21:55 +0200 Subject: [PATCH 4/5] Add python_requires to setup.py --- setup.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 7178c131..7b0a5db5 100755 --- a/setup.py +++ b/setup.py @@ -126,6 +126,11 @@ def main(): license='MIT', + # See https://stackoverflow.com/a/40300957/4759433 + # -> https://www.python.org/dev/peps/pep-0345/#requires-python + # -> http://setuptools.readthedocs.io/en/latest/setuptools.html + python_requires='>=3.4', + # See https://pypi.python.org/pypi?%3Aaction=list_classifiers classifiers=[ # 3 - Alpha @@ -139,7 +144,6 @@ def main(): 'License :: OSI Approved :: MIT License', 'Programming Language :: Python :: 3', - 'Programming Language :: Python :: 3.3', 'Programming Language :: Python :: 3.4', 'Programming Language :: Python :: 3.5', 'Programming Language :: Python :: 3.6' From 591e34b49162d70d533ad9d8bd26c3b06b5edddf Mon Sep 17 00:00:00 2001 From: Lonami Exo Date: Wed, 4 Apr 2018 13:35:51 +0200 Subject: [PATCH 5/5] Change TypeError with ValueError, don't call .get_dialogs() This closes #735 and #736 since now it can be properly handled from user code, and behave more correctly depending on the situation. Also the errors provide more information on how to get around it. --- telethon/telegram_client.py | 45 +++++++++++++++---------------------- 1 file changed, 18 insertions(+), 27 deletions(-) diff --git a/telethon/telegram_client.py b/telethon/telegram_client.py index 08c32b88..18bfda43 100644 --- a/telethon/telegram_client.py +++ b/telethon/telegram_client.py @@ -38,7 +38,8 @@ from .errors import ( RPCError, UnauthorizedError, PhoneCodeEmptyError, PhoneCodeExpiredError, PhoneCodeHashEmptyError, PhoneCodeInvalidError, LocationInvalidError, SessionPasswordNeededError, FileMigrateError, PhoneNumberUnoccupiedError, - PhoneNumberOccupiedError, EmailUnconfirmedError, PasswordEmptyError + PhoneNumberOccupiedError, EmailUnconfirmedError, PasswordEmptyError, + UsernameNotOccupiedError ) from .network import ConnectionMode from .tl.custom import Draft, Dialog @@ -192,9 +193,6 @@ class TelegramClient(TelegramBareClient): # Sometimes we need to know who we are, cache the self peer self._self_input_peer = None - # Don't call .get_dialogs() every time a .get_entity() fails - self._called_get_dialogs = False - # endregion # region Telegram requests functions @@ -2391,15 +2389,21 @@ class TelegramClient(TelegramBareClient): invite = self(CheckChatInviteRequest(username)) if isinstance(invite, ChatInvite): raise ValueError( - 'Cannot get entity from a channel ' - '(or group) that you are not part of' + 'Cannot get entity from a channel (or group) ' + 'that you are not part of. Join the group and retry' ) elif isinstance(invite, ChatInviteAlready): return invite.chat elif username: if username in ('me', 'self'): return self.get_me() - result = self(ResolveUsernameRequest(username)) + + try: + result = self(ResolveUsernameRequest(username)) + except UsernameNotOccupiedError as e: + raise ValueError('No user has "{}" as username' + .format(username)) from e + for entity in itertools.chain(result.users, result.chats): if getattr(entity, 'username', None) or ''\ .lower() == username: @@ -2410,8 +2414,8 @@ class TelegramClient(TelegramBareClient): except ValueError: pass - raise TypeError( - 'Cannot turn "{}" into any entity (user or chat)'.format(string) + raise ValueError( + 'Cannot find any entity corresponding to "{}"'.format(string) ) def get_input_entity(self, peer): @@ -2460,25 +2464,12 @@ class TelegramClient(TelegramBareClient): 'Cannot turn "{}" into an input entity.'.format(original_peer) ) - # Add the mark to the peers if the user passed a Peer (not an int), - # or said ID is negative. If it's negative it's been marked already. - # Look in the dialogs with the hope to find it. - if not self._called_get_dialogs: - self._called_get_dialogs = True - mark = not isinstance(peer, int) or peer < 0 - target_id = utils.get_peer_id(peer) - if mark: - for dialog in self.get_dialogs(100): - if utils.get_peer_id(dialog.entity) == target_id: - return utils.get_input_peer(dialog.entity) - else: - for dialog in self.get_dialogs(100): - if dialog.entity.id == target_id: - return utils.get_input_peer(dialog.entity) - - raise TypeError( + raise ValueError( 'Could not find the input entity corresponding to "{}". ' - 'Make sure you have encountered this peer before.'.format(peer) + 'Make sure you have encountered this user/chat/channel before. ' + 'If the peer is in your dialogs call client.get_dialogs().' + 'If the peer belongs to a chat call client.get_participants().' + .format(peer) ) def edit_2fa(self, current_password=None, new_password=None, hint='',