Repository: alexander-akhmetov/python-telegram

Issue:
"Failed to parse JSON object as TDLib request: Wrong padding length" When tried to login
File "/app/index.py", line 17, in <module>
    tg.login()
  File "/usr/local/lib/python3.8/site-packages/telegram/client.py", line 439, in login
    result.wait(raise_exc=True)
  File "/usr/local/lib/python3.8/site-packages/telegram/utils.py", line 41, in wait
    raise RuntimeError(f'Telegram error: {self.error_info}')
RuntimeError: Telegram error: {'@type': 'error', 'code': 400, 'message': 'Failed to parse JSON object as TDLib request: Wrong padding length', '@extra': {'request_id': 'updateAuthorizationState'}}

Code is running in docker!

Thank you

Comments:

Patch:
diff --git a/telegram/client.py b/telegram/client.py
index e427a88..17bf2a5 100644
--- a/telegram/client.py
+++ b/telegram/client.py
@@ -6,8 +6,9 @@ import signal
 import typing
 import getpass
 import logging
+import base64
 import threading
-from typing import Any, Dict, List, Type, Callable, Optional, DefaultDict, Tuple
+from typing import Any, Dict, List, Type, Callable, Optional, DefaultDict, Tuple, Union
 from types import FrameType
 from collections import defaultdict
 
@@ -27,7 +28,7 @@ class Telegram:
         self,
         api_id: int,
         api_hash: str,
-        database_encryption_key: str,
+        database_encryption_key: Union[str, bytes],
         phone: Optional[str] = None,
         bot_token: Optional[str] = None,
         library_path: Optional[str] = None,
@@ -530,9 +531,14 @@ class Telegram:
 
     def _send_encryption_key(self) -> AsyncResult:
         logger.info('Sending encryption key')
+
+        key = self._database_encryption_key
+        if isinstance(key, str):
+            key = key.encode()
+
         data = {
             '@type': 'checkDatabaseEncryptionKey',
-            'encryption_key': self._database_encryption_key,
+            'encryption_key': base64.b64encode(key).decode(),
         }
 
         return self._send_data(data, result_id='updateAuthorizationState')


Test patch:
diff --git a/tests/test_telegram_methods.py b/tests/test_telegram_methods.py
index 24cec65..96a1f01 100644
--- a/tests/test_telegram_methods.py
+++ b/tests/test_telegram_methods.py
@@ -17,13 +17,20 @@ DATABASE_ENCRYPTION_KEY = 'changeme1234'
 def telegram():
     with patch('telegram.client.TDJson'):
         with patch('telegram.client.threading'):
-            tg = Telegram(
-                api_id=API_ID,
-                api_hash=API_HASH,
-                phone=PHONE,
-                library_path=LIBRARY_PATH,
-                database_encryption_key=DATABASE_ENCRYPTION_KEY,
-            )
+            return _get_telegram_instance()
+
+
+def _get_telegram_instance(**kwargs):
+    kwargs.setdefault('api_id', API_ID)
+    kwargs.setdefault('api_hash', API_HASH)
+    kwargs.setdefault('phone', PHONE)
+    kwargs.setdefault('library_path', LIBRARY_PATH)
+    kwargs.setdefault('database_encryption_key', DATABASE_ENCRYPTION_KEY)
+
+    with patch('telegram.client.TDJson'):
+        with patch('telegram.client.threading'):
+            tg = Telegram(**kwargs)
+
     return tg
 
 
@@ -278,6 +285,25 @@ class TestTelegram:
         telegram._tdjson.send.assert_called_once_with(exp_data)
         assert async_result.id == 'updateAuthorizationState'
 
+    @pytest.mark.parametrize(
+        'key, exp_key',
+        [('key', 'a2V5'), (b'byte-key', 'Ynl0ZS1rZXk='), ('', ''), (b'', '')],
+    )
+    def test_send_encryption_key(self, key, exp_key):
+        # check that _send_encryption_key calls tdlib with
+        # correct parameters encoded using base64
+        tg = _get_telegram_instance(database_encryption_key=key)
+
+        tg._send_encryption_key()
+
+        exp_data = {
+            '@type': 'checkDatabaseEncryptionKey',
+            'encryption_key': exp_key,
+            '@extra': {'request_id': 'updateAuthorizationState'},
+        }
+
+        tg._tdjson.send.assert_called_once_with(exp_data)
+
 
 class TestTelegram__update_async_result:
     def test_update_async_result_returns_async_result_with_same_id(self, telegram):