diff --git a/telethon/utils.py b/telethon/utils.py index befb2e07..81dd9f23 100644 --- a/telethon/utils.py +++ b/telethon/utils.py @@ -746,17 +746,31 @@ def _rle_decode(data): new = b'' last = b'' for cur in data: - cur = bytes([cur]) if last == b'\0': - new += last * ord(cur) + new += last * cur last = b'' else: new += last - last = cur + last = bytes([cur]) return new + last +def _rle_encode(string): + new = b'' + count = 0 + for cur in string: + if not cur: + count += 1 + else: + if count: + new += b'\0' + bytes([count]) + count = 0 + + new += bytes([cur]) + return new + + def _decode_telegram_base64(string): """ Decodes an url-safe base64-encoded string into its bytes @@ -773,6 +787,16 @@ def _decode_telegram_base64(string): return None # not valid base64, not valid ascii, not a string +def _encode_telegram_base64(string): + """ + Inverse for `_decode_telegram_base64`. + """ + try: + return base64.urlsafe_b64encode(string).rstrip(b'=').decode('ascii') + except (binascii.Error, ValueError, TypeError): + return None # not valid base64, not valid ascii, not a string + + def resolve_bot_file_id(file_id): """ Given a Bot API-style `file_id`, returns the media it represents. @@ -812,7 +836,6 @@ def resolve_bot_file_id(file_id): elif file_type == 10: attributes.append(types.DocumentAttributeAnimated()) - print(file_type) return types.Document( id=media_id, access_hash=access_hash, @@ -840,6 +863,49 @@ def resolve_bot_file_id(file_id): ], date=None) +def pack_bot_file_id(file): + """ + Inverse operation for `resolve_bot_file_id`. + + The only parameters this method will accept are :tl:`Document` and + :tl:`Photo`, and it will return a variable-length ``file_id`` string. + + If an invalid parameter is given, it will ``return None``. + """ + if isinstance(file, types.Document): + file_type = 5 + for attribute in file.attributes: + if isinstance(attribute, types.DocumentAttributeAudio): + file_type = 3 if attribute.voice else 9 + elif isinstance(attribute, types.DocumentAttributeVideo): + file_type = 13 if attribute.round_message else 4 + elif isinstance(attribute, types.DocumentAttributeSticker): + file_type = 8 + elif isinstance(attribute, types.DocumentAttributeAnimated): + file_type = 10 + else: + continue + break + + return _encode_telegram_base64(_rle_encode(struct.pack( + '