Pytdbot 0.9.1__tar.gz → 0.9.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. {pytdbot-0.9.1 → pytdbot-0.9.2}/PKG-INFO +4 -3
  2. {pytdbot-0.9.1 → pytdbot-0.9.2}/Pytdbot.egg-info/PKG-INFO +4 -3
  3. {pytdbot-0.9.1 → pytdbot-0.9.2}/Pytdbot.egg-info/SOURCES.txt +2 -0
  4. {pytdbot-0.9.1 → pytdbot-0.9.2}/README.md +1 -1
  5. {pytdbot-0.9.1 → pytdbot-0.9.2}/pytdbot/__init__.py +11 -2
  6. {pytdbot-0.9.1 → pytdbot-0.9.2}/pytdbot/client.py +104 -166
  7. pytdbot-0.9.2/pytdbot/client_manager.py +197 -0
  8. {pytdbot-0.9.1 → pytdbot-0.9.2}/pytdbot/handlers/td_updates.py +68 -0
  9. {pytdbot-0.9.1 → pytdbot-0.9.2}/pytdbot/methods/td_functions.py +550 -72
  10. {pytdbot-0.9.1 → pytdbot-0.9.2}/pytdbot/tdjson/tdjson.py +12 -4
  11. {pytdbot-0.9.1 → pytdbot-0.9.2}/pytdbot/types/__init__.py +43 -13
  12. {pytdbot-0.9.1 → pytdbot-0.9.2}/pytdbot/types/td_types/bound_methods/message.py +2 -2
  13. {pytdbot-0.9.1 → pytdbot-0.9.2}/pytdbot/types/td_types/types.py +898 -84
  14. {pytdbot-0.9.1 → pytdbot-0.9.2}/pytdbot/utils/__init__.py +2 -0
  15. pytdbot-0.9.2/pytdbot/utils/asyncio_utils.py +10 -0
  16. {pytdbot-0.9.1 → pytdbot-0.9.2}/LICENSE +0 -0
  17. {pytdbot-0.9.1 → pytdbot-0.9.2}/MANIFEST.in +0 -0
  18. {pytdbot-0.9.1 → pytdbot-0.9.2}/Pytdbot.egg-info/dependency_links.txt +0 -0
  19. {pytdbot-0.9.1 → pytdbot-0.9.2}/Pytdbot.egg-info/requires.txt +0 -0
  20. {pytdbot-0.9.1 → pytdbot-0.9.2}/Pytdbot.egg-info/top_level.txt +0 -0
  21. {pytdbot-0.9.1 → pytdbot-0.9.2}/pytdbot/exception/__init__.py +0 -0
  22. {pytdbot-0.9.1 → pytdbot-0.9.2}/pytdbot/filters.py +0 -0
  23. {pytdbot-0.9.1 → pytdbot-0.9.2}/pytdbot/handlers/__init__.py +0 -0
  24. {pytdbot-0.9.1 → pytdbot-0.9.2}/pytdbot/handlers/decorators.py +0 -0
  25. {pytdbot-0.9.1 → pytdbot-0.9.2}/pytdbot/handlers/handler.py +0 -0
  26. {pytdbot-0.9.1 → pytdbot-0.9.2}/pytdbot/methods/__init__.py +0 -0
  27. {pytdbot-0.9.1 → pytdbot-0.9.2}/pytdbot/methods/methods.py +0 -0
  28. {pytdbot-0.9.1 → pytdbot-0.9.2}/pytdbot/tdjson/__init__.py +0 -0
  29. {pytdbot-0.9.1 → pytdbot-0.9.2}/pytdbot/types/plugins/__init__.py +0 -0
  30. {pytdbot-0.9.1 → pytdbot-0.9.2}/pytdbot/types/td_types/__init__.py +0 -0
  31. {pytdbot-0.9.1 → pytdbot-0.9.2}/pytdbot/types/td_types/bound_methods/__init__.py +0 -0
  32. {pytdbot-0.9.1 → pytdbot-0.9.2}/pytdbot/types/td_types/bound_methods/callback_query.py +0 -0
  33. {pytdbot-0.9.1 → pytdbot-0.9.2}/pytdbot/types/td_types/bound_methods/chatActions.py +0 -0
  34. {pytdbot-0.9.1 → pytdbot-0.9.2}/pytdbot/types/td_types/bound_methods/file.py +0 -0
  35. {pytdbot-0.9.1 → pytdbot-0.9.2}/pytdbot/utils/escape.py +0 -0
  36. {pytdbot-0.9.1 → pytdbot-0.9.2}/pytdbot/utils/json_utils.py +0 -0
  37. {pytdbot-0.9.1 → pytdbot-0.9.2}/pytdbot/utils/obj_encoder.py +0 -0
  38. {pytdbot-0.9.1 → pytdbot-0.9.2}/pytdbot/utils/strings.py +0 -0
  39. {pytdbot-0.9.1 → pytdbot-0.9.2}/pytdbot/utils/text_format.py +0 -0
  40. {pytdbot-0.9.1 → pytdbot-0.9.2}/pytdbot/utils/webapps.py +0 -0
  41. {pytdbot-0.9.1 → pytdbot-0.9.2}/requirements.txt +0 -0
  42. {pytdbot-0.9.1 → pytdbot-0.9.2}/setup.cfg +0 -0
  43. {pytdbot-0.9.1 → pytdbot-0.9.2}/setup.py +0 -0
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.2
1
+ Metadata-Version: 2.4
2
2
  Name: Pytdbot
3
- Version: 0.9.1
3
+ Version: 0.9.2
4
4
  Summary: Easy-to-use asynchronous TDLib wrapper for Python.
5
5
  Home-page: https://github.com/pytdbot/client
6
6
  Author: AYMEN Mohammed
@@ -23,13 +23,14 @@ Dynamic: description-content-type
23
23
  Dynamic: home-page
24
24
  Dynamic: keywords
25
25
  Dynamic: license
26
+ Dynamic: license-file
26
27
  Dynamic: project-url
27
28
  Dynamic: provides-extra
28
29
  Dynamic: requires-dist
29
30
  Dynamic: requires-python
30
31
  Dynamic: summary
31
32
 
32
- # Pytdbot [![Version](https://img.shields.io/pypi/v/Pytdbot?style=flat&logo=pypi)](https://pypi.org/project/Pytdbot) [![TDLib version](https://img.shields.io/badge/TDLib-v1.8.46-blue?logo=telegram)](https://github.com/tdlib/td) [![Downloads](https://static.pepy.tech/personalized-badge/pytdbot?period=month&units=none&left_color=grey&right_color=brightgreen&left_text=Downloads)](https://pepy.tech/project/pytdbot)
33
+ # Pytdbot [![Version](https://img.shields.io/pypi/v/Pytdbot?style=flat&logo=pypi)](https://pypi.org/project/Pytdbot) [![TDLib version](https://img.shields.io/badge/TDLib-v1.8.47-blue?logo=telegram)](https://github.com/tdlib/td) [![Downloads](https://static.pepy.tech/personalized-badge/pytdbot?period=month&units=none&left_color=grey&right_color=brightgreen&left_text=Downloads)](https://pepy.tech/project/pytdbot) [![Telegram Chat](https://img.shields.io/badge/Pytdbot%20chat-blue?logo=telegram&label=Telegram)](https://t.me/pytdbotchat)
33
34
 
34
35
  Pytdbot (Python TDLib) is an asynchronous [**TDLib**](https://github.com/tdlib/td) wrapper for **Telegram** users/bots written in **Python**.
35
36
 
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.2
1
+ Metadata-Version: 2.4
2
2
  Name: Pytdbot
3
- Version: 0.9.1
3
+ Version: 0.9.2
4
4
  Summary: Easy-to-use asynchronous TDLib wrapper for Python.
5
5
  Home-page: https://github.com/pytdbot/client
6
6
  Author: AYMEN Mohammed
@@ -23,13 +23,14 @@ Dynamic: description-content-type
23
23
  Dynamic: home-page
24
24
  Dynamic: keywords
25
25
  Dynamic: license
26
+ Dynamic: license-file
26
27
  Dynamic: project-url
27
28
  Dynamic: provides-extra
28
29
  Dynamic: requires-dist
29
30
  Dynamic: requires-python
30
31
  Dynamic: summary
31
32
 
32
- # Pytdbot [![Version](https://img.shields.io/pypi/v/Pytdbot?style=flat&logo=pypi)](https://pypi.org/project/Pytdbot) [![TDLib version](https://img.shields.io/badge/TDLib-v1.8.46-blue?logo=telegram)](https://github.com/tdlib/td) [![Downloads](https://static.pepy.tech/personalized-badge/pytdbot?period=month&units=none&left_color=grey&right_color=brightgreen&left_text=Downloads)](https://pepy.tech/project/pytdbot)
33
+ # Pytdbot [![Version](https://img.shields.io/pypi/v/Pytdbot?style=flat&logo=pypi)](https://pypi.org/project/Pytdbot) [![TDLib version](https://img.shields.io/badge/TDLib-v1.8.47-blue?logo=telegram)](https://github.com/tdlib/td) [![Downloads](https://static.pepy.tech/personalized-badge/pytdbot?period=month&units=none&left_color=grey&right_color=brightgreen&left_text=Downloads)](https://pepy.tech/project/pytdbot) [![Telegram Chat](https://img.shields.io/badge/Pytdbot%20chat-blue?logo=telegram&label=Telegram)](https://t.me/pytdbotchat)
33
34
 
34
35
  Pytdbot (Python TDLib) is an asynchronous [**TDLib**](https://github.com/tdlib/td) wrapper for **Telegram** users/bots written in **Python**.
35
36
 
@@ -10,6 +10,7 @@ Pytdbot.egg-info/requires.txt
10
10
  Pytdbot.egg-info/top_level.txt
11
11
  pytdbot/__init__.py
12
12
  pytdbot/client.py
13
+ pytdbot/client_manager.py
13
14
  pytdbot/filters.py
14
15
  pytdbot/exception/__init__.py
15
16
  pytdbot/handlers/__init__.py
@@ -31,6 +32,7 @@ pytdbot/types/td_types/bound_methods/chatActions.py
31
32
  pytdbot/types/td_types/bound_methods/file.py
32
33
  pytdbot/types/td_types/bound_methods/message.py
33
34
  pytdbot/utils/__init__.py
35
+ pytdbot/utils/asyncio_utils.py
34
36
  pytdbot/utils/escape.py
35
37
  pytdbot/utils/json_utils.py
36
38
  pytdbot/utils/obj_encoder.py
@@ -1,4 +1,4 @@
1
- # Pytdbot [![Version](https://img.shields.io/pypi/v/Pytdbot?style=flat&logo=pypi)](https://pypi.org/project/Pytdbot) [![TDLib version](https://img.shields.io/badge/TDLib-v1.8.46-blue?logo=telegram)](https://github.com/tdlib/td) [![Downloads](https://static.pepy.tech/personalized-badge/pytdbot?period=month&units=none&left_color=grey&right_color=brightgreen&left_text=Downloads)](https://pepy.tech/project/pytdbot)
1
+ # Pytdbot [![Version](https://img.shields.io/pypi/v/Pytdbot?style=flat&logo=pypi)](https://pypi.org/project/Pytdbot) [![TDLib version](https://img.shields.io/badge/TDLib-v1.8.47-blue?logo=telegram)](https://github.com/tdlib/td) [![Downloads](https://static.pepy.tech/personalized-badge/pytdbot?period=month&units=none&left_color=grey&right_color=brightgreen&left_text=Downloads)](https://pepy.tech/project/pytdbot) [![Telegram Chat](https://img.shields.io/badge/Pytdbot%20chat-blue?logo=telegram&label=Telegram)](https://t.me/pytdbotchat)
2
2
 
3
3
  Pytdbot (Python TDLib) is an asynchronous [**TDLib**](https://github.com/tdlib/td) wrapper for **Telegram** users/bots written in **Python**.
4
4
 
@@ -1,10 +1,19 @@
1
1
  from . import types, utils, filters, exception
2
2
  from .tdjson import TdJson
3
+ from .client_manager import ClientManager
3
4
  from .client import Client
4
5
 
5
- __all__ = ["types", "utils", "filters", "exception", "TdJson", "Client"]
6
+ __all__ = [
7
+ "types",
8
+ "utils",
9
+ "filters",
10
+ "exception",
11
+ "TdJson",
12
+ "ClientManager",
13
+ "Client",
14
+ ]
6
15
 
7
- __version__ = "0.9.1"
16
+ __version__ = "0.9.2"
8
17
  __copyright__ = "Copyright (c) 2022-2025 Pytdbot, AYMENJD"
9
18
  __license__ = "MIT License"
10
19
 
@@ -1,45 +1,37 @@
1
- import signal
2
- import pytdbot
3
1
  import asyncio
4
- import aio_pika
5
-
6
- from platform import python_implementation, python_version
2
+ import signal
3
+ from importlib import import_module
4
+ from json import dumps
5
+ from logging import DEBUG, getLogger
7
6
  from os.path import join as join_path
8
7
  from pathlib import Path
9
- from importlib import import_module
10
-
11
- from typing import Callable, Union, Dict
12
- from logging import getLogger, DEBUG
8
+ from platform import python_implementation, python_version
9
+ from threading import current_thread, main_thread
10
+ from typing import Callable, Dict, Union
13
11
 
12
+ import aio_pika
14
13
  from deepdiff import DeepDiff
15
- from concurrent.futures import ThreadPoolExecutor
16
- from threading import current_thread, main_thread
17
- from json import dumps
18
14
 
19
- from .tdjson import TdJson
20
- from .handlers import Decorators, Handler
21
- from .methods import Methods
22
- from .types import Plugins, LogStream
15
+ import pytdbot
16
+
23
17
  from . import types
18
+ from .client_manager import ClientManager
19
+ from .exception import AuthorizationError, StopHandlers
24
20
  from .filters import Filter
25
- from .exception import StopHandlers, AuthorizationError
21
+ from .handlers import Decorators, Handler
22
+ from .methods import Methods
23
+ from .types import LogStream, Plugins
26
24
  from .utils import (
27
25
  create_extra_id,
28
- json_loads,
29
- json_dumps,
26
+ dict_to_obj,
30
27
  get_bot_id_from_token,
28
+ get_running_loop,
29
+ json_dumps,
30
+ json_loads,
31
31
  obj_to_dict,
32
- dict_to_obj,
33
32
  )
34
33
 
35
34
 
36
- def get_running_loop():
37
- try:
38
- return asyncio.get_running_loop()
39
- except RuntimeError:
40
- return asyncio.new_event_loop()
41
-
42
-
43
35
  class Client(Decorators, Methods):
44
36
  r"""Pytdbot, a TDLib client
45
37
 
@@ -136,6 +128,7 @@ class Client(Decorators, Methods):
136
128
  no_updates: bool = False,
137
129
  td_verbosity: int = 2,
138
130
  td_log: LogStream = None,
131
+ user_bot: bool = False,
139
132
  ) -> None:
140
133
  self.__api_id = api_id
141
134
  self.__api_hash = api_hash
@@ -164,9 +157,17 @@ class Client(Decorators, Methods):
164
157
  self.workers = workers
165
158
  self.no_updates = no_updates
166
159
  self.queue = asyncio.Queue()
167
- self.my_id = get_bot_id_from_token(self.__token)
160
+ self.user_bot = user_bot
161
+ self.my_id = (
162
+ get_bot_id_from_token(self.__token)
163
+ if isinstance(self.__token, str)
164
+ else None
165
+ )
166
+ self.client_id = None
167
+ self.client_manager = None
168
168
  self.logger = getLogger(f"{__name__}:{self.my_id or 0}")
169
169
  self.td_verbosity = td_verbosity
170
+ self.td_log = td_log
170
171
  self.connection_state: str = None
171
172
  self.is_running = None
172
173
  self.me: types.User = None
@@ -178,8 +179,6 @@ class Client(Decorators, Methods):
178
179
 
179
180
  self._handlers = {"initializer": [], "finalizer": []}
180
181
  self._results: Dict[str, asyncio.Future] = {}
181
- self._tdjson = None if self.is_rabbitmq else TdJson(lib_path, td_verbosity)
182
- self.__listen_loop_task = None
183
182
  self._workers_tasks = None
184
183
  self.__authorization_state = None
185
184
  self.__cache = {"is_coro_filter": {}}
@@ -191,9 +190,14 @@ class Client(Decorators, Methods):
191
190
  "updateOption": self.__handle_update_option,
192
191
  "updateUser": self.__handle_update_user,
193
192
  }
194
- self.__login = False
193
+ self.__is_queue_worker = False
195
194
  self.__is_closing = False
196
195
 
196
+ # RabbitMQ
197
+ self.__rqueues = None
198
+ self.__rconnection = None
199
+ self.__rchannel = None
200
+
197
201
  self.loop = (
198
202
  loop if isinstance(loop, asyncio.AbstractEventLoop) else get_running_loop()
199
203
  )
@@ -201,16 +205,10 @@ class Client(Decorators, Methods):
201
205
  if plugins is not None:
202
206
  self._load_plugins()
203
207
 
204
- if isinstance(td_log, LogStream) and not self.is_rabbitmq:
205
- self._tdjson.execute(
206
- {"@type": "setLogStream", "log_stream": obj_to_dict(td_log)}
207
- )
208
-
209
208
  self.logger.info(f"Pytdbot v{pytdbot.VERSION}")
210
209
 
211
210
  async def __aenter__(self):
212
211
  await self.start()
213
- await self.login()
214
212
  return self
215
213
 
216
214
  async def __aexit__(self, exc_type, exc_val, exc_tb):
@@ -225,21 +223,27 @@ class Client(Decorators, Methods):
225
223
 
226
224
  return self.__authorization_state
227
225
 
228
- async def start(self, login: bool = True) -> None:
229
- r"""Start pytdbot client
230
-
231
- Parameters:
232
- login (``bool``, *optional*):
233
- Login after start. Default is ``True``
234
- """
226
+ async def start(self) -> None:
227
+ r"""Start pytdbot client"""
235
228
 
236
229
  if not self.is_running:
237
230
  self.logger.info("Starting pytdbot client...")
238
231
 
232
+ if not self.client_manager:
233
+ self.client_manager = ClientManager(
234
+ self, self.lib_path, self.td_verbosity, loop=self.loop
235
+ )
236
+ await self.client_manager.start()
237
+
238
+ if isinstance(self.td_log, LogStream) and not self.is_rabbitmq:
239
+ await self.__send(
240
+ {"@type": "setLogStream", "log_stream": obj_to_dict(self.td_log)}
241
+ )
242
+
239
243
  if isinstance(self.workers, int):
240
244
  self._workers_tasks = [
241
245
  self.loop.create_task(self._queue_update_worker())
242
- for x in range(self.workers)
246
+ for _ in range(self.workers)
243
247
  ]
244
248
  self.__is_queue_worker = True
245
249
 
@@ -249,45 +253,13 @@ class Client(Decorators, Methods):
249
253
  self.logger.info("Started with unlimited updates processes")
250
254
 
251
255
  if self.is_rabbitmq:
252
- await self.__startRabbitMQ()
253
- else:
254
- self.__listen_loop_task = self.loop.create_task(self.__listen_loop())
255
-
256
- if login:
257
- await self.login()
258
-
259
- async def login(self) -> None:
260
- r"""Login to Telegram."""
261
-
262
- if not self.__token or (self.is_authenticated or self.is_rabbitmq):
263
- return
264
-
265
- self.__login = True
266
-
267
- await self.getOption("version") # Ping TDLib to start authorization process
268
-
269
- while self.authorization_state != "authorizationStateReady":
270
- await asyncio.sleep(0.1)
271
- if self.authorization_state == "authorizationStateClosed":
272
- return
273
-
274
- if not self.is_running:
275
- return
276
-
277
- self.me = await self.getMe()
278
- if isinstance(self.me, types.Error):
279
- self.logger.error(f"Get me error: {self.me.message}")
280
-
281
- self.is_authenticated = True
256
+ await self.__start_rabbitmq()
257
+ else: # client_manager
258
+ self.is_running = True
282
259
 
283
- self.logger.info(
284
- "Logged in as {} {}".format(
285
- self.me.first_name,
286
- str(self.me.id)
287
- if not self.me.usernames
288
- else "@" + self.me.usernames.editable_username,
289
- )
290
- )
260
+ self.loop.create_task(
261
+ self.getOption("version")
262
+ ) # Ping TDLib to start processing updates
291
263
 
292
264
  def add_handler(
293
265
  self,
@@ -351,13 +323,11 @@ class Client(Decorators, Methods):
351
323
 
352
324
  if not isinstance(func, Callable):
353
325
  raise TypeError("func must be callable")
354
- for update_type in self._handlers:
355
- for handler in self._handlers[update_type]:
326
+ for _, handlers in self._handlers.items():
327
+ for handler in handlers.copy():
356
328
  if handler.func == func:
357
- self._handlers[update_type].remove(handler)
358
- self._handlers[update_type].sort(
359
- key=lambda x: (x.position is None, x.position)
360
- )
329
+ handlers.remove(handler)
330
+ handlers.sort(key=lambda x: (x.position is None, x.position))
361
331
  return True
362
332
  return False
363
333
 
@@ -466,7 +436,7 @@ class Client(Decorators, Methods):
466
436
 
467
437
  return await self.invoke(kwargs)
468
438
 
469
- def run(self, login: bool = True) -> None:
439
+ def run(self) -> None:
470
440
  r"""Start the client and block until the client is stopped
471
441
 
472
442
  Example:
@@ -481,15 +451,11 @@ class Client(Decorators, Methods):
481
451
  await update.reply_text('Hello!')
482
452
 
483
453
  client.run()
484
-
485
- Parameters:
486
- login (``bool``, *optional*):
487
- Login after start. Default is ``True``
488
454
  """
489
455
 
490
456
  self._register_signal_handlers()
491
457
 
492
- self.loop.run_until_complete(self.start(login))
458
+ self.loop.run_until_complete(self.start())
493
459
  self.loop.run_until_complete(self.idle())
494
460
 
495
461
  async def idle(self):
@@ -534,6 +500,9 @@ class Client(Decorators, Methods):
534
500
 
535
501
  self.__stop_client()
536
502
 
503
+ if not self.client_manager.start_clients_on_add:
504
+ await self.client_manager.close()
505
+
537
506
  self.logger.info("Instance closed")
538
507
 
539
508
  return True
@@ -552,11 +521,7 @@ class Client(Decorators, Methods):
552
521
  return result
553
522
 
554
523
  async def __send(self, request: dict) -> None:
555
- if not self.is_rabbitmq:
556
- self._tdjson.send(
557
- request
558
- ) # tdjson.send is non-blocking method, So we don't need run_in_executor. This improves performance
559
- else:
524
+ if self.is_rabbitmq:
560
525
  await self.__rchannel.default_exchange.publish(
561
526
  aio_pika.Message(
562
527
  json_dumps(request, encode=True),
@@ -564,8 +529,13 @@ class Client(Decorators, Methods):
564
529
  ),
565
530
  routing_key=self.__rqueues["requests"].name,
566
531
  )
532
+ else:
533
+ self.client_manager.send(self.client_id, request)
567
534
 
568
535
  def _check_init_args(self):
536
+ if self.user_bot:
537
+ return
538
+
569
539
  if not self.is_rabbitmq:
570
540
  if not isinstance(self.__api_id, int):
571
541
  raise TypeError("api_id must be an int")
@@ -657,31 +627,7 @@ class Client(Decorators, Methods):
657
627
  self.__cache["is_coro_filter"][func] = is_coro
658
628
  return is_coro
659
629
 
660
- async def __listen_loop(self):
661
- if self.is_rabbitmq:
662
- return
663
-
664
- with ThreadPoolExecutor(1, "pytdbot_listener") as thread:
665
- try:
666
- self.is_running = True
667
- self.logger.info("Listening to updates...")
668
-
669
- while self.is_running:
670
- update = await self.loop.run_in_executor(
671
- thread,
672
- self._tdjson.receive,
673
- 1.0, # Seconds
674
- )
675
- if update is None:
676
- continue
677
- self.loop.create_task(self._process_update(update))
678
-
679
- except Exception:
680
- self.logger.exception("Exception in __listen_loop")
681
- finally:
682
- self.is_running = False
683
-
684
- async def _process_update(self, update):
630
+ async def process_update(self, update):
685
631
  if not update:
686
632
  self.logger.warning("Received None update")
687
633
  return
@@ -784,7 +730,8 @@ class Client(Decorators, Methods):
784
730
  async def _handle_update(self, update):
785
731
  if update.getType() in self._handlers:
786
732
  if (
787
- isinstance(update, types.UpdateNewMessage)
733
+ not self.user_bot
734
+ and isinstance(update, types.UpdateNewMessage)
788
735
  and update.message.is_outgoing
789
736
  ):
790
737
  return
@@ -872,13 +819,23 @@ class Client(Decorators, Methods):
872
819
  f"Authorization state changed to {self.authorization_state.removeprefix('authorizationState')}"
873
820
  )
874
821
 
875
- if self.__login:
876
- if self.authorization_state == "authorizationStateWaitTdlibParameters":
877
- await self._set_options()
878
- await self.set_td_parameters()
879
- elif self.authorization_state == "authorizationStateWaitPhoneNumber":
880
- self._print_welcome()
881
- await self.__handle_authorization_state_wait_phone_number()
822
+ if self.authorization_state == "authorizationStateWaitTdlibParameters":
823
+ await self._set_options()
824
+ await self.set_td_parameters()
825
+ elif self.authorization_state == "authorizationStateWaitPhoneNumber":
826
+ self._print_welcome()
827
+ await self.__handle_authorization_state_wait_phone_number()
828
+ elif self.authorization_state == "authorizationStateReady":
829
+ self.is_authenticated = True
830
+
831
+ self.me = await self.getMe()
832
+ if isinstance(self.me, types.Error):
833
+ self.logger.error(f"Get me error: {self.me.message}")
834
+
835
+ self.logger.info(
836
+ f"Logged in as {self.me.first_name} "
837
+ f"{str(self.me.id) if not self.me.usernames else '@' + self.me.usernames.editable_username}"
838
+ )
882
839
 
883
840
  if (
884
841
  self.authorization_state == "authorizationStateClosed"
@@ -942,7 +899,7 @@ class Client(Decorators, Methods):
942
899
  f"Could not connect to TDLib Server after {delay * retries} seconds timeout"
943
900
  )
944
901
 
945
- async def __startRabbitMQ(self):
902
+ async def __start_rabbitmq(self):
946
903
  self.__rconnection = await aio_pika.connect_robust(
947
904
  self.__rabbitmq_url,
948
905
  client_properties={
@@ -979,19 +936,7 @@ class Client(Decorators, Methods):
979
936
  for update in res.updates:
980
937
  # when using obj_to_dict the key "@client_id" won't exists
981
938
  # since it's not part of the object
982
- await self._process_update(obj_to_dict(update))
983
-
984
- self.me = await self.getMe()
985
- self.is_authenticated = True
986
-
987
- self.logger.info(
988
- "Logged in as {} {}".format(
989
- self.me.first_name,
990
- str(self.me.id)
991
- if not self.me.usernames
992
- else "@" + self.me.usernames.editable_username,
993
- )
994
- )
939
+ await self.process_update(obj_to_dict(update))
995
940
 
996
941
  if not self.no_updates:
997
942
  await self.__rqueues["updates"].consume(self.__on_update, no_ack=True)
@@ -999,20 +944,16 @@ class Client(Decorators, Methods):
999
944
  await self.__rqueues["notify"].consume(self.__on_update, no_ack=True)
1000
945
 
1001
946
  async def __handle_rabbitmq_message(self, message: aio_pika.IncomingMessage):
1002
- await self._process_update(json_loads(message.body))
947
+ await self.process_update(json_loads(message.body))
1003
948
 
1004
949
  async def __on_update(self, update):
1005
950
  self.loop.create_task(self.__handle_rabbitmq_message(update))
1006
951
 
1007
952
  async def __handle_update_user(self, update: types.UpdateUser):
1008
- if self.is_authenticated and update.user.id == self.me.id:
953
+ if self.is_authenticated and self.me and update.user.id == self.me.id:
1009
954
  self.logger.info(
1010
- "Updating {} ({}) info".format(
1011
- self.me.first_name,
1012
- str(self.me.id)
1013
- if not self.me.usernames
1014
- else "@" + self.me.usernames.editable_username,
1015
- )
955
+ f"Updating {self.me.first_name} "
956
+ f"({str(self.me.id) if not self.me.usernames else '@' + self.me.usernames.editable_username}) info"
1016
957
  )
1017
958
 
1018
959
  try:
@@ -1042,28 +983,25 @@ class Client(Decorators, Methods):
1042
983
  for worker_task in self._workers_tasks:
1043
984
  worker_task.cancel()
1044
985
 
1045
- if self.__listen_loop_task:
1046
- self.__listen_loop_task.cancel()
1047
-
1048
986
  def _register_signal_handlers(self):
1049
987
  def _handle_signal():
1050
988
  self.loop.create_task(self.stop())
1051
- for sig in {
989
+ for sig in (
1052
990
  signal.SIGINT,
1053
991
  signal.SIGTERM,
1054
992
  signal.SIGABRT,
1055
993
  signal.SIGSEGV,
1056
- }:
994
+ ):
1057
995
  self.loop.remove_signal_handler(sig)
1058
996
 
1059
997
  if current_thread() is main_thread():
1060
998
  try:
1061
- for sig in {
999
+ for sig in (
1062
1000
  signal.SIGINT,
1063
1001
  signal.SIGTERM,
1064
1002
  signal.SIGABRT,
1065
1003
  signal.SIGSEGV,
1066
- }:
1004
+ ):
1067
1005
  self.loop.add_signal_handler(sig, _handle_signal)
1068
1006
  except NotImplementedError: # Windows dosen't support add_signal_handler
1069
1007
  pass
@@ -1082,12 +1020,12 @@ def deepdiff(self, d1, d2):
1082
1020
 
1083
1021
  deep = DeepDiff(d1, d2, ignore_order=True, view="tree")
1084
1022
 
1085
- for parent in deep.keys():
1086
- for diff in deep[parent]:
1023
+ for parent, diffs in deep.items():
1024
+ for diff in diffs:
1087
1025
  difflist = diff.path(output_format="list")
1088
- key = ".".join(str(v) for v in difflist)
1026
+ key = ".".join(map(str, difflist))
1089
1027
 
1090
- if parent in {"dictionary_item_added", "values_changed"}:
1028
+ if parent in ("dictionary_item_added", "values_changed"):
1091
1029
  self.logger.info(f"{key} changed to {diff.t2}")
1092
1030
  elif parent == "dictionary_item_removed":
1093
1031
  self.logger.info(f"{key} removed")