Skip to content

Commit

Permalink
'Refactored by Sourcery'
Browse files Browse the repository at this point in the history
  • Loading branch information
Sourcery AI committed Oct 29, 2023
1 parent 046dbb5 commit 99036fe
Show file tree
Hide file tree
Showing 15 changed files with 343 additions and 484 deletions.
3 changes: 1 addition & 2 deletions telethon/_updates/messagebox.py
Expand Up @@ -109,8 +109,7 @@ def from_update(cls, update):
entry = getattr(update, 'channel_id', None) or ENTRY_ACCOUNT
return cls(pts=pts, pts_count=pts_count, entry=entry)

qts = getattr(update, 'qts', None)
if qts:
if qts := getattr(update, 'qts', None):
pts_count = 1 if isinstance(update, tl.UpdateNewEncryptedMessage) else 0
return cls(pts=qts, pts_count=pts_count, entry=ENTRY_SECRET)

Expand Down
5 changes: 2 additions & 3 deletions telethon/client/chats.py
Expand Up @@ -803,14 +803,13 @@ def action(
try:
action = _ChatAction._str_mapping[action.lower()]
except KeyError:
raise ValueError(
'No such action "{}"'.format(action)) from None
raise ValueError(f'No such action "{action}"') from None
elif not isinstance(action, types.TLObject) or action.SUBCLASS_OF_ID != 0x20b2cc21:
# 0x20b2cc21 = crc32(b'SendMessageAction')
if isinstance(action, type):
raise ValueError('You must pass an instance, not the class')
else:
raise ValueError('Cannot use {} as action'.format(action))
raise ValueError(f'Cannot use {action} as action')

if isinstance(action, types.SendMessageCancelAction):
# ``SetTypingRequest.resolve`` will get input peer of ``entity``.
Expand Down
59 changes: 24 additions & 35 deletions telethon/client/downloads.py
Expand Up @@ -265,27 +265,27 @@ async def download_profile_photo(
thumb=thumb, progress_callback=None
)

for attr in ('username', 'first_name', 'title'):
possible_names.append(getattr(entity, attr, None))

possible_names.extend(
getattr(entity, attr, None)
for attr in ('username', 'first_name', 'title')
)
photo = entity.photo

if isinstance(photo, (types.UserProfilePhoto, types.ChatPhoto)):
dc_id = photo.dc_id
loc = types.InputPeerPhotoFileLocation(
# min users can be used to download profile photos
# self.get_input_entity would otherwise not accept those
peer=utils.get_input_peer(entity, check_hash=False),
photo_id=photo.photo_id,
big=download_big
)
else:
if not isinstance(photo, (types.UserProfilePhoto, types.ChatPhoto)):
# It doesn't make any sense to check if `photo` can be used
# as input location, because then this method would be able
# to "download the profile photo of a message", i.e. its
# media which should be done with `download_media` instead.
return None

dc_id = photo.dc_id
loc = types.InputPeerPhotoFileLocation(
# min users can be used to download profile photos
# self.get_input_entity would otherwise not accept those
peer=utils.get_input_peer(entity, check_hash=False),
photo_id=photo.photo_id,
big=download_big
)
file = self._get_proper_filename(
file, 'profile_photo', '.jpg',
possible_names=possible_names
Expand All @@ -299,16 +299,15 @@ async def download_profile_photo(
# The fix seems to be using the full channel chat photo.
ie = await self.get_input_entity(entity)
ty = helpers._entity_type(ie)
if ty == helpers._EntityType.CHANNEL:
full = await self(functions.channels.GetFullChannelRequest(ie))
return await self._download_photo(
full.full_chat.chat_photo, file,
date=None, progress_callback=None,
thumb=thumb
)
else:
if ty != helpers._EntityType.CHANNEL:
# Until there's a report for chats, no need to.
return None
full = await self(functions.channels.GetFullChannelRequest(ie))
return await self._download_photo(
full.full_chat.chat_photo, file,
date=None, progress_callback=None,
thumb=thumb
)

async def download_media(
self: 'TelegramClient',
Expand Down Expand Up @@ -518,11 +517,7 @@ async def _download_file(
iv: bytes = None,
msg_data: tuple = None) -> typing.Optional[bytes]:
if not part_size_kb:
if not file_size:
part_size_kb = 64 # Reasonable default
else:
part_size_kb = utils.get_appropriated_part_size(file_size)

part_size_kb = utils.get_appropriated_part_size(file_size) if file_size else 64
part_size = int(part_size_kb * 1024)
if part_size % MIN_CHUNK_SIZE != 0:
raise ValueError(
Expand Down Expand Up @@ -756,11 +751,7 @@ def sort_thumbs(thumb):
return 1, thumb.size
if isinstance(thumb, types.PhotoSizeProgressive):
return 1, max(thumb.sizes)
if isinstance(thumb, types.VideoSize):
return 2, thumb.size

# Empty size or invalid should go last
return 0, 0
return (2, thumb.size) if isinstance(thumb, types.VideoSize) else (0, 0)

thumbs = list(sorted(thumbs, key=sort_thumbs))

Expand Down Expand Up @@ -856,9 +847,7 @@ def _get_kind_and_names(attributes):
elif isinstance(attr, types.DocumentAttributeAudio):
kind = 'audio'
if attr.performer and attr.title:
possible_names.append('{} - {}'.format(
attr.performer, attr.title
))
possible_names.append(f'{attr.performer} - {attr.title}')
elif attr.performer:
possible_names.append(attr.performer)
elif attr.title:
Expand Down Expand Up @@ -1044,7 +1033,7 @@ def _get_proper_filename(file, kind, extension,

i = 1
while True:
result = os.path.join(directory, '{} ({}){}'.format(name, i, ext))
result = os.path.join(directory, f'{name} ({i}){ext}')
if not os.path.isfile(result):
return result
i += 1
Expand Down
42 changes: 17 additions & 25 deletions telethon/client/messages.py
Expand Up @@ -242,14 +242,12 @@ def _message_in_range(self, message):
Determine whether the given message is in the range or
it should be ignored (and avoid loading more chunks).
"""
# No entity means message IDs between chats may vary
if self.entity:
if self.reverse:
if message.id <= self.last_id or message.id >= self.max_id:
return False
else:
if message.id >= self.last_id or message.id <= self.min_id:
return False
elif message.id >= self.last_id or message.id <= self.min_id:
return False

return True

Expand Down Expand Up @@ -585,11 +583,7 @@ async def get_messages(self: 'TelegramClient', *args, **kwargs) -> 'hints.TotalL
message_1337 = await client.get_messages(chat, ids=1337)
"""
if len(args) == 1 and 'limit' not in kwargs:
if 'min_id' in kwargs and 'max_id' in kwargs:
kwargs['limit'] = None
else:
kwargs['limit'] = 1

kwargs['limit'] = None if 'min_id' in kwargs and 'max_id' in kwargs else 1
it = self.iter_messages(*args, **kwargs)

ids = kwargs.get('ids')
Expand Down Expand Up @@ -1203,15 +1197,14 @@ async def edit_message(
# Invoke `messages.editInlineBotMessage` from the right datacenter.
# Otherwise, Telegram will error with `MESSAGE_ID_INVALID` and do nothing.
exported = self.session.dc_id != entity.dc_id
if exported:
try:
sender = await self._borrow_exported_sender(entity.dc_id)
return await self._call(sender, request)
finally:
await self._return_exported_sender(sender)
else:
if not exported:
return await self(request)

try:
sender = await self._borrow_exported_sender(entity.dc_id)
return await self._call(sender, request)
finally:
await self._return_exported_sender(sender)
entity = await self.get_input_entity(entity)
request = functions.messages.EditMessageRequest(
peer=entity,
Expand All @@ -1223,8 +1216,7 @@ async def edit_message(
reply_markup=self.build_reply_markup(buttons),
schedule_date=schedule
)
msg = self._get_response_message(request, await self(request), entity)
return msg
return self._get_response_message(request, await self(request), entity)

async def delete_messages(
self: 'TelegramClient',
Expand Down Expand Up @@ -1362,14 +1354,14 @@ async def send_read_acknowledge(
await client.send_read_acknowledge(chat, messages)
"""
if max_id is None:
if not message:
max_id = 0
if message:
max_id = (
max(msg.id for msg in message)
if utils.is_list_like(message)
else message.id
)
else:
if utils.is_list_like(message):
max_id = max(msg.id for msg in message)
else:
max_id = message.id

max_id = 0
entity = await self.get_input_entity(entity)
if clear_mentions:
await self(functions.messages.ReadMentionsRequest(entity))
Expand Down
63 changes: 14 additions & 49 deletions telethon/client/updates.py
Expand Up @@ -301,8 +301,7 @@ async def _update_loop(self: 'TelegramClient'):
)


get_diff = self._message_box.get_difference()
if get_diff:
if get_diff := self._message_box.get_difference():
self._log[__name__].debug('Getting difference for account updates')
try:
diff = await self(get_diff)
Expand Down Expand Up @@ -346,8 +345,9 @@ async def _update_loop(self: 'TelegramClient'):
updates_to_dispatch.extend(self._preprocess_updates(updates, users, chats))
continue

get_diff = self._message_box.get_channel_difference(self._mb_entity_cache)
if get_diff:
if get_diff := self._message_box.get_channel_difference(
self._mb_entity_cache
):
self._log[__name__].debug('Getting difference for channel %s updates', get_diff.channel.channel_id)
try:
diff = await self(get_diff)
Expand Down Expand Up @@ -446,16 +446,15 @@ async def _update_loop(self: 'TelegramClient'):

deadline = self._message_box.check_deadlines()
deadline_delay = deadline - get_running_loop().time()
if deadline_delay > 0:
# Don't bother sleeping and timing out if the delay is already 0 (pollutes the logs).
try:
updates = await asyncio.wait_for(self._updates_queue.get(), deadline_delay)
except asyncio.TimeoutError:
self._log[__name__].debug('Timeout waiting for updates expired')
continue
else:
if deadline_delay <= 0:
continue

# Don't bother sleeping and timing out if the delay is already 0 (pollutes the logs).
try:
updates = await asyncio.wait_for(self._updates_queue.get(), deadline_delay)
except asyncio.TimeoutError:
self._log[__name__].debug('Timeout waiting for updates expired')
continue
processed = []
try:
users, chats = self._message_box.process_updates(updates, self._mb_entity_cache, processed)
Expand Down Expand Up @@ -537,16 +536,13 @@ async def _dispatch_update(self: 'TelegramClient', update):
built = EventBuilderDict(self, update, others)
for conv_set in self._conversations.values():
for conv in conv_set:
ev = built[events.NewMessage]
if ev:
if ev := built[events.NewMessage]:
conv._on_new_message(ev)

ev = built[events.MessageEdited]
if ev:
if ev := built[events.MessageEdited]:
conv._on_edit(ev)

ev = built[events.MessageRead]
if ev:
if ev := built[events.MessageRead]:
conv._on_read(ev)

if conv._custom:
Expand Down Expand Up @@ -637,37 +633,6 @@ async def _handle_auto_reconnect(self: 'TelegramClient'):
'after reconnect: %s: %s', type(e), e)

return
try:
self._log[__name__].info(
'Asking for the current state after reconnect...')

# TODO consider:
# If there aren't many updates while the client is disconnected
# (I tried with up to 20), Telegram seems to send them without
# asking for them (via updates.getDifference).
#
# On disconnection, the library should probably set a "need
# difference" or "catching up" flag so that any new updates are
# ignored, and then the library should call updates.getDifference
# itself to fetch them.
#
# In any case (either there are too many updates and Telegram
# didn't send them, or there isn't a lot and Telegram sent them
# but we dropped them), we fetch the new difference to get all
# missed updates. I feel like this would be the best solution.

# If a disconnection occurs, the old known state will be
# the latest one we were aware of, so we can catch up since
# the most recent state we were aware of.
await self.catch_up()

self._log[__name__].info('Successfully fetched missed updates')
except errors.RPCError as e:
self._log[__name__].warning('Failed to get missed updates after '
'reconnect: %r', e)
except Exception:
self._log[__name__].exception(
'Unhandled exception while getting update difference after reconnect')

# endregion

Expand Down

0 comments on commit 99036fe

Please sign in to comment.