From c84043cf71bbe200823aa1af99ec0659dcc7bc6c Mon Sep 17 00:00:00 2001 From: Lonami Exo Date: Sun, 12 Sep 2021 14:09:53 +0200 Subject: [PATCH] Fix calls to private client methods --- telethon/_client/auth.py | 11 ++--- telethon/_client/downloads.py | 56 ++++++++++++------------ telethon/_client/messageparse.py | 4 +- telethon/_client/messages.py | 6 +-- telethon/_client/telegrambaseclient.py | 33 ++++---------- telethon/_client/telegramclient.py | 59 +++++++++++++++++++++++++- telethon/_client/updates.py | 18 ++++---- telethon/_client/uploads.py | 16 +++---- telethon/_client/users.py | 4 +- 9 files changed, 124 insertions(+), 83 deletions(-) diff --git a/telethon/_client/auth.py b/telethon/_client/auth.py index ccfaa68b..4ae32c43 100644 --- a/telethon/_client/auth.py +++ b/telethon/_client/auth.py @@ -40,7 +40,8 @@ async def start( raise ValueError('Both a phone and a bot token provided, ' 'must only provide one of either') - return await self._start( + return await _start( + self=self, phone=phone, password=password, bot_token=bot_token, @@ -211,7 +212,7 @@ async def sign_in( return await self.send_code_request(phone) elif code: phone, phone_code_hash = \ - self._parse_phone_and_hash(phone, phone_code_hash) + _parse_phone_and_hash(self, phone, phone_code_hash) # May raise PhoneCodeEmptyError, PhoneCodeExpiredError, # PhoneCodeHashEmptyError or PhoneCodeInvalidError. @@ -240,7 +241,7 @@ async def sign_in( self._tos = result.terms_of_service raise errors.PhoneNumberUnoccupiedError(request=request) - return self._on_login(result.user) + return _on_login(self, result.user) async def sign_up( self: 'TelegramClient', @@ -280,7 +281,7 @@ async def sign_up( sys.stderr.flush() phone, phone_code_hash = \ - self._parse_phone_and_hash(phone, phone_code_hash) + _parse_phone_and_hash(self, phone, phone_code_hash) result = await self(_tl.fn.auth.SignUp( phone_number=phone, @@ -293,7 +294,7 @@ async def sign_up( await self( _tl.fn.help.AcceptTermsOfService(self._tos.id)) - return self._on_login(result.user) + return _on_login(self, result.user) def _on_login(self, user): """ diff --git a/telethon/_client/downloads.py b/telethon/_client/downloads.py index dbb279f3..25a461cb 100644 --- a/telethon/_client/downloads.py +++ b/telethon/_client/downloads.py @@ -213,8 +213,8 @@ async def download_profile_photo( if not hasattr(entity, 'chat_photo'): return None - return await self._download_photo( - entity.chat_photo, file, date=None, + return await _download_photo( + self, entity.chat_photo, file, date=None, thumb=thumb, progress_callback=None ) @@ -237,7 +237,7 @@ async def download_profile_photo( # media which should be done with `download_media` instead. return None - file = self._get_proper_filename( + file = _get_proper_filename( file, 'profile_photo', '.jpg', possible_names=possible_names ) @@ -252,8 +252,8 @@ async def download_profile_photo( ty = helpers._entity_type(ie) if ty == helpers._EntityType.CHANNEL: full = await self(_tl.fn.channels.GetFullChannel(ie)) - return await self._download_photo( - full.full_chat.chat_photo, file, + return await _download_photo( + self, full.full_chat.chat_photo, file, date=None, progress_callback=None, thumb=thumb ) @@ -295,20 +295,20 @@ async def download_media( media = media.webpage.document or media.webpage.photo if isinstance(media, (_tl.MessageMediaPhoto, _tl.Photo)): - return await self._download_photo( - media, file, date, thumb, progress_callback + return await _download_photo( + self, media, file, date, thumb, progress_callback ) elif isinstance(media, (_tl.MessageMediaDocument, _tl.Document)): - return await self._download_document( - media, file, date, thumb, progress_callback, msg_data + return await _download_document( + self, media, file, date, thumb, progress_callback, msg_data ) elif isinstance(media, _tl.MessageMediaContact) and thumb is None: - return self._download_contact( - media, file + return _download_contact( + self, media, file ) elif isinstance(media, (_tl.WebDocument, _tl.WebDocumentNoProxy)) and thumb is None: - return await self._download_web_document( - media, file, progress_callback + return await _download_web_document( + self, media, file, progress_callback ) async def download_file( @@ -322,7 +322,8 @@ async def download_file( dc_id: int = None, key: bytes = None, iv: bytes = None) -> typing.Optional[bytes]: - return await self._download_file( + return await _download_file( + self, input_location, file, part_size_kb=part_size_kb, @@ -370,8 +371,8 @@ async def _download_file( f = file try: - async for chunk in self._iter_download( - input_location, request_size=part_size, dc_id=dc_id, msg_data=msg_data): + async for chunk in _iter_download( + self, input_location, request_size=part_size, dc_id=dc_id, msg_data=msg_data): if iv and key: chunk = AES.decrypt_ige(chunk, key, iv) r = f.write(chunk) @@ -405,7 +406,8 @@ def iter_download( file_size: int = None, dc_id: int = None ): - return self._iter_download( + return _iter_download( + self, file, offset=offset, stride=stride, @@ -552,17 +554,17 @@ async def _download_photo(self: 'TelegramClient', photo, file, date, thumb, prog return # Include video sizes here (but they may be None so provide an empty list) - size = self._get_thumb(photo.sizes + (photo.video_sizes or []), thumb) + size = _get_thumb(photo.sizes + (photo.video_sizes or []), thumb) if not size or isinstance(size, _tl.PhotoSizeEmpty): return if isinstance(size, _tl.VideoSize): - file = self._get_proper_filename(file, 'video', '.mp4', date=date) + file = _get_proper_filename(file, 'video', '.mp4', date=date) else: - file = self._get_proper_filename(file, 'photo', '.jpg', date=date) + file = _get_proper_filename(file, 'photo', '.jpg', date=date) if isinstance(size, (_tl.PhotoCachedSize, _tl.PhotoStrippedSize)): - return self._download_cached_photo_size(size, file) + return _download_cached_photo_size(self, size, file) if isinstance(size, _tl.PhotoSizeProgressive): file_size = max(size.sizes) @@ -614,19 +616,19 @@ async def _download_document( return if thumb is None: - kind, possible_names = self._get_kind_and_names(document.attributes) - file = self._get_proper_filename( + kind, possible_names = _get_kind_and_names(document.attributes) + file = _get_proper_filename( file, kind, utils.get_extension(document), date=date, possible_names=possible_names ) size = None else: - file = self._get_proper_filename(file, 'photo', '.jpg', date=date) - size = self._get_thumb(document.thumbs, thumb) + file = _get_proper_filename(file, 'photo', '.jpg', date=date) + size = _get_thumb(document.thumbs, thumb) if isinstance(size, (_tl.PhotoCachedSize, _tl.PhotoStrippedSize)): - return self._download_cached_photo_size(size, file) + return _download_cached_photo_size(self, size, file) - result = await self._download_file( + result = await _download_file( _tl.InputDocumentFileLocation( id=document.id, access_hash=document.access_hash, diff --git a/telethon/_client/messageparse.py b/telethon/_client/messageparse.py index d68ab38f..9f1f3b70 100644 --- a/telethon/_client/messageparse.py +++ b/telethon/_client/messageparse.py @@ -55,12 +55,12 @@ async def _parse_message_text(self: 'TelegramClient', message, parse_mode): m = re.match(r'^@|\+|tg://user\?id=(\d+)', e.url) if m: user = int(m.group(1)) if m.group(1) else e.url - is_mention = await self._replace_with_mention(msg_entities, i, user) + is_mention = await _replace_with_mention(self, msg_entities, i, user) if not is_mention: del msg_entities[i] elif isinstance(e, (_tl.MessageEntityMentionName, _tl.InputMessageEntityMentionName)): - is_mention = await self._replace_with_mention(msg_entities, i, e.user_id) + is_mention = await _replace_with_mention(self, msg_entities, i, e.user_id) if not is_mention: del msg_entities[i] diff --git a/telethon/_client/messages.py b/telethon/_client/messages.py index 00ee418a..5dae6eb4 100644 --- a/telethon/_client/messages.py +++ b/telethon/_client/messages.py @@ -436,7 +436,7 @@ async def send_message( entity = await self.get_input_entity(entity) if comment_to is not None: - entity, reply_to = await self._get_comment_data(entity, comment_to) + entity, reply_to = await _get_comment_data(self, entity, comment_to) if isinstance(message, _tl.Message): if buttons is None: @@ -712,7 +712,7 @@ async def pin_message( notify: bool = False, pm_oneside: bool = False ): - return await self._pin(entity, message, unpin=False, notify=notify, pm_oneside=pm_oneside) + return await _pin(self, entity, message, unpin=False, notify=notify, pm_oneside=pm_oneside) async def unpin_message( self: 'TelegramClient', @@ -721,7 +721,7 @@ async def unpin_message( *, notify: bool = False ): - return await self._pin(entity, message, unpin=True, notify=notify) + return await _pin(self, entity, message, unpin=True, notify=notify) async def _pin(self, entity, message, *, unpin, notify=False, pm_oneside=False): message = utils.get_message_id(message) or 0 diff --git a/telethon/_client/telegrambaseclient.py b/telethon/_client/telegrambaseclient.py index c89b1809..1cf74821 100644 --- a/telethon/_client/telegrambaseclient.py +++ b/telethon/_client/telegrambaseclient.py @@ -331,7 +331,7 @@ def is_connected(self: 'TelegramClient') -> bool: return sender and sender.is_connected() async def disconnect(self: 'TelegramClient'): - return await self._disconnect_coro() + return await _disconnect_coro(self) def set_proxy(self: 'TelegramClient', proxy: typing.Union[tuple, dict]): init_proxy = None if not issubclass(self._connection, TcpMTProxy) else \ @@ -354,7 +354,7 @@ def set_proxy(self: 'TelegramClient', proxy: typing.Union[tuple, dict]): connection._proxy = proxy async def _disconnect_coro(self: 'TelegramClient'): - await self._disconnect() + await _disconnect(self) # Also clean-up all exported senders because we're done with them async with self._borrow_sender_lock: @@ -408,7 +408,7 @@ async def _switch_dc(self: 'TelegramClient', new_dc): Permanently switches the current connection to the new data center. """ self._log[__name__].info('Reconnecting to new data center %s', new_dc) - dc = await self._get_dc(new_dc) + dc = await _get_dc(self, new_dc) self.session.set_dc(dc.id, dc.ip_address, dc.port) # auth_key's are associated with a server, which has now changed @@ -416,7 +416,7 @@ async def _switch_dc(self: 'TelegramClient', new_dc): self._sender.auth_key.key = None self.session.auth_key = None self.session.save() - await self._disconnect() + await _disconnect(self) return await self.connect() def _auth_key_callback(self: 'TelegramClient', auth_key): @@ -462,7 +462,7 @@ async def _create_exported_sender(self: 'TelegramClient', dc_id): """ # Thanks badoualy/kotlogram on /telegram/api/DefaultTelegramClient.kt # for clearly showing how to export the authorization - dc = await self._get_dc(dc_id) + dc = await _get_dc(self, dc_id) # Can't reuse self._sender._connection as it has its own seqno. # # If one were to do that, Telegram would reset the connection @@ -497,12 +497,12 @@ async def _borrow_exported_sender(self: 'TelegramClient', dc_id): if state is None: state = _ExportState() - sender = await self._create_exported_sender(dc_id) + sender = await _create_exported_sender(self, dc_id) sender.dc_id = dc_id self._borrowed_senders[dc_id] = (state, sender) elif state.need_connect(): - dc = await self._get_dc(dc_id) + dc = await _get_dc(self, dc_id) await sender.connect(self._connection( dc.ip_address, dc.port, @@ -545,7 +545,7 @@ async def _get_cdn_client(self: 'TelegramClient', cdn_redirect): raise NotImplementedError session = self._exported_sessions.get(cdn_redirect.dc_id) if not session: - dc = await self._get_dc(cdn_redirect.dc_id, cdn=True) + dc = await _get_dc(self, cdn_redirect.dc_id, cdn=True) session = self.session.clone() await session.set_dc(dc.id, dc.ip_address, dc.port) self._exported_sessions[cdn_redirect.dc_id] = session @@ -564,20 +564,3 @@ async def _get_cdn_client(self: 'TelegramClient', cdn_redirect): # set already. Avoid invoking non-CDN methods by not syncing updates. client.connect(_sync_updates=False) return client - - -@abc.abstractmethod -def __call__(self: 'TelegramClient', request, ordered=False): - raise NotImplementedError - -@abc.abstractmethod -def _handle_update(self: 'TelegramClient', update): - raise NotImplementedError - -@abc.abstractmethod -def _update_loop(self: 'TelegramClient'): - raise NotImplementedError - -@abc.abstractmethod -async def _handle_auto_reconnect(self: 'TelegramClient'): - raise NotImplementedError diff --git a/telethon/_client/telegramclient.py b/telethon/_client/telegramclient.py index 986b89f0..f219605e 100644 --- a/telethon/_client/telegramclient.py +++ b/telethon/_client/telegramclient.py @@ -3496,7 +3496,7 @@ class TelegramClient: # region Users - def __call__(self: 'TelegramClient', request, ordered=False): + async def __call__(self: 'TelegramClient', request, ordered=False, flood_sleep_threshold=None): """ Invokes (sends) one or more MTProtoRequests and returns (receives) their result. @@ -3519,7 +3519,7 @@ class TelegramClient: The result of the request (often a `TLObject`) or a list of results if more than one request was given. """ - return users.call(self._sender, request, ordered=ordered) + return self._call(request, ordered, flood_sleep_threshold) async def get_me(self: 'TelegramClient', input_peer: bool = False) \ -> 'typing.Union[_tl.User, _tl.InputPeerUser]': @@ -3719,4 +3719,59 @@ class TelegramClient: # endregion Users + # region Private + + async def _call(self: 'TelegramClient', sender, request, ordered=False, flood_sleep_threshold=None): + return users.call(self._sender, request, ordered=ordered, flood_sleep_threshold=flood_sleep_threshold) + + async def _update_loop(self: 'TelegramClient'): + return updates._update_loop(**locals()) + + async def _parse_message_text(self: 'TelegramClient', message, parse_mode): + return messageparse._parse_message_text(**locals()) + + async def _file_to_media( + self, file, force_document=False, file_size=None, + progress_callback=None, attributes=None, thumb=None, + allow_cache=True, voice_note=False, video_note=False, + supports_streaming=False, mime_type=None, as_image=None, + ttl=None): + return uploads._file_to_media(**locals()) + + async def _get_peer(self: 'TelegramClient', peer: 'hints.EntityLike'): + return users._get_peer(**locals()) + + def _get_response_message(self: 'TelegramClient', request, result, input_chat): + return messageparse._get_response_message(**locals()) + + async def _get_comment_data( + self: 'TelegramClient', + entity: 'hints.EntityLike', + message: 'typing.Union[int, _tl.Message]' + ): + return messages._get_comment_data(**locals()) + + async def _switch_dc(self: 'TelegramClient', new_dc): + return telegrambaseclient._switch_dc(**locals()) + + async def _borrow_exported_sender(self: 'TelegramClient', dc_id): + return telegrambaseclient._borrow_exported_sender(**locals()) + + async def _return_exported_sender(self: 'TelegramClient', sender): + return telegrambaseclient._return_exported_sender(**locals()) + + async def _clean_exported_senders(self: 'TelegramClient'): + return telegrambaseclient._clean_exported_senders(**locals()) + + def _auth_key_callback(self: 'TelegramClient', auth_key): + return telegrambaseclient._auth_key_callback + + def _handle_update(self: 'TelegramClient', update): + return updates._handle_update(**locals()) + + async def _handle_auto_reconnect(self: 'TelegramClient'): + return updates._handle_auto_reconnect(**locals()) + + # endregion Private + # TODO re-patch everything to remove the intermediate calls diff --git a/telethon/_client/updates.py b/telethon/_client/updates.py index e8c5709c..9d1e205c 100644 --- a/telethon/_client/updates.py +++ b/telethon/_client/updates.py @@ -34,7 +34,7 @@ async def set_receive_updates(self: 'TelegramClient', receive_updates): await self(_tl.fn.updates.GetState()) async def run_until_disconnected(self: 'TelegramClient'): - return await self._run_until_disconnected() + return await _run_until_disconnected(self) def on(self: 'TelegramClient', event: EventBuilder): def decorator(f): @@ -101,7 +101,7 @@ async def catch_up(self: 'TelegramClient'): state = d.intermediate_state pts, date = state.pts, state.date - self._handle_update(_tl.Updates( + _handle_update(self, _tl.Updates( users=d.users, chats=d.chats, date=state.date, @@ -151,11 +151,11 @@ def _handle_update(self: 'TelegramClient', update): entities = {utils.get_peer_id(x): x for x in itertools.chain(update.users, update.chats)} for u in update.updates: - self._process_update(u, update.updates, entities=entities) + _process_update(self, u, update.updates, entities=entities) elif isinstance(update, _tl.UpdateShort): - self._process_update(update.update, None) + _process_update(self, update.update, None) else: - self._process_update(update, None) + _process_update(self, update, None) self._state_cache.update(update) @@ -168,14 +168,14 @@ def _process_update(self: 'TelegramClient', update, others, entities=None): channel_id = self._state_cache.get_channel_id(update) args = (update, others, channel_id, self._state_cache[channel_id]) if self._dispatching_updates_queue is None: - task = self.loop.create_task(self._dispatch_update(*args)) + task = self.loop.create_task(_dispatch_update(self, *args)) self._updates_queue.add(task) task.add_done_callback(lambda _: self._updates_queue.discard(task)) else: self._updates_queue.put_nowait(args) if not self._dispatching_updates_queue.is_set(): self._dispatching_updates_queue.set() - self.loop.create_task(self._dispatch_queue_updates()) + self.loop.create_task(_dispatch_queue_updates(self)) self._state_cache.update(update) @@ -235,7 +235,7 @@ async def _update_loop(self: 'TelegramClient'): async def _dispatch_queue_updates(self: 'TelegramClient'): while not self._updates_queue.empty(): - await self._dispatch_update(*self._updates_queue.get_nowait()) + await _dispatch_update(self, *self._updates_queue.get_nowait()) self._dispatching_updates_queue.clear() @@ -248,7 +248,7 @@ async def _dispatch_update(self: 'TelegramClient', update, others, channel_id, p # If the update doesn't have pts, fetching won't do anything. # For example, UpdateUserStatus or UpdateChatUserTyping. try: - await self._get_difference(update, channel_id, pts_date) + await _get_difference(self, update, channel_id, pts_date) except OSError: pass # We were disconnected, that's okay except errors.RPCError: diff --git a/telethon/_client/uploads.py b/telethon/_client/uploads.py index db2cdd77..8043f26c 100644 --- a/telethon/_client/uploads.py +++ b/telethon/_client/uploads.py @@ -125,7 +125,7 @@ async def send_file( entity = await self.get_input_entity(entity) if comment_to is not None: - entity, reply_to = await self._get_comment_data(entity, comment_to) + entity, reply_to = await _get_comment_data(self, entity, comment_to) else: reply_to = utils.get_message_id(reply_to) @@ -139,8 +139,8 @@ async def send_file( result = [] while file: - result += await self._send_album( - entity, file[:10], caption=captions[:10], + result += await _send_album( + self, entity, file[:10], caption=captions[:10], progress_callback=progress_callback, reply_to=reply_to, parse_mode=parse_mode, silent=silent, schedule=schedule, supports_streaming=supports_streaming, clear_draft=clear_draft, @@ -167,10 +167,10 @@ async def send_file( msg_entities = formatting_entities else: caption, msg_entities =\ - await self._parse_message_text(caption, parse_mode) + await _parse_message_text(self, caption, parse_mode) - file_handle, media, image = await self._file_to_media( - file, force_document=force_document, + file_handle, media, image = await _file_to_media( + self, file, force_document=force_document, file_size=file_size, progress_callback=progress_callback, attributes=attributes, allow_cache=allow_cache, thumb=thumb, @@ -223,8 +223,8 @@ async def _send_album(self: 'TelegramClient', entity, files, caption='', # :tl:`InputMediaUploadedPhoto`. However using that will # make it `raise MediaInvalidError`, so we need to upload # it as media and then convert that to :tl:`InputMediaPhoto`. - fh, fm, _ = await self._file_to_media( - file, supports_streaming=supports_streaming, + fh, fm, _ = await _file_to_media( + self, file, supports_streaming=supports_streaming, force_document=force_document, ttl=ttl) if isinstance(fm, (_tl.InputMediaUploadedPhoto, _tl.InputMediaPhotoExternal)): r = await self(_tl.fn.messages.UploadMedia( diff --git a/telethon/_client/users.py b/telethon/_client/users.py index e493ea61..0719cdc4 100644 --- a/telethon/_client/users.py +++ b/telethon/_client/users.py @@ -230,7 +230,7 @@ async def get_entity( result = [] for x in inputs: if isinstance(x, str): - result.append(await self._get_entity_from_string(x)) + result.append(await _get_entity_from_string(self, x)) elif not isinstance(x, _tl.InputPeerSelf): result.append(id_entity[utils.get_peer_id(x)]) else: @@ -271,7 +271,7 @@ async def get_input_entity( # Only network left to try if isinstance(peer, str): return utils.get_input_peer( - await self._get_entity_from_string(peer)) + await _get_entity_from_string(self, peer)) # If we're a bot and the user has messaged us privately users.getUsers # will work with access_hash = 0. Similar for channels.getChannels.