1+ from asyncio import gather
12from collections import deque
2- from collections .abc import Iterator , Sequence
3+ from collections .abc import Iterator
34from contextlib import AbstractAsyncContextManager
4- from dataclasses import dataclass
5+ from dataclasses import dataclass , field
6+ from pathlib import Path
57from types import TracebackType
6- from typing import Self
8+ from typing import Self , cast
79
810from telethon import TelegramClient
11+ from telethon .sessions .string import StringSession
12+ from telethon .types import InputPeerUser
913
1014
11- @dataclass (init = False )
15+ @dataclass (frozen = True , unsafe_hash = False )
1216class TelegramClientPool (AbstractAsyncContextManager ["TelegramClientPool" ]):
1317 _clients : deque [TelegramClient ]
14- _client_by_id : dict [int , TelegramClient ]
1518
16- def __init__ ( self , clients : Sequence [ TelegramClient ]) -> None :
17- self . _clients = deque ( clients , len ( clients ))
18- self . _client_by_id = dict ( )
19+ _client_by_id : dict [ int , TelegramClient ] = field (
20+ init = False , default_factory = dict
21+ )
1922
2023 async def __aenter__ (self ) -> Self :
2124 for client in self ._clients :
22- client_info = await client .get_me (input_peer = True )
25+ client_info = (
26+ cast (InputPeerUser , await client .get_me (input_peer = True ))
27+ )
2328 client_id = client_info .user_id
2429
2530 self ._client_by_id [client_id ] = client
2631
32+ await gather (* (
33+ client .__aenter__ () # type: ignore[no-untyped-call]
34+ for client in self ._clients
35+ ))
36+
2737 return self
2838
2939 async def __aexit__ (
3040 self ,
31- _ : type [BaseException ] | None ,
32- __ : BaseException | None ,
33- ___ : TracebackType | None ,
41+ error_type : type [BaseException ] | None ,
42+ error : BaseException | None ,
43+ traceback : TracebackType | None ,
3444 ) -> None :
35- return
45+ await gather (* (
46+ client .__aexit__ (error_type , error , traceback ) # type: ignore[no-untyped-call]
47+ for client in self ._clients
48+ ))
3649
3750 def __call__ (self , client_id : int | None = None ) -> TelegramClient :
3851 if client_id is None :
@@ -51,3 +64,16 @@ def __call__(self, client_id: int | None = None) -> TelegramClient:
5164 def __iter__ (self ) -> Iterator [TelegramClient ]:
5265 while True :
5366 yield self ()
67+
68+
69+ def loaded_client_pool_from_farm_file (
70+ farm_file_path : Path , app_api_id : int , app_api_hash : str
71+ ) -> TelegramClientPool :
72+ with farm_file_path .open () as farm_file :
73+ return TelegramClientPool (deque (
74+ TelegramClient (
75+ StringSession (session_token ), app_api_id , app_api_hash
76+ )
77+ for session_token in farm_file
78+ if session_token
79+ ))
0 commit comments