10
10
import sys
11
11
from ctypes import CDLL , CFUNCTYPE , c_char_p , c_double , c_int
12
12
from ctypes .util import find_library
13
- from typing import Any , Dict , Optional , Union
13
+ from typing import Any , Dict , Optional
14
14
15
15
16
16
class TdExample :
@@ -32,12 +32,14 @@ def __init__(self, api_id: int = None, api_hash: str = None):
32
32
33
33
def _load_library (self ) -> None :
34
34
"""Load the TDLib shared library."""
35
- tdjson_path = find_library (' tdjson' )
35
+ tdjson_path = find_library (" tdjson" )
36
36
if tdjson_path is None :
37
- if os .name == 'nt' :
38
- tdjson_path = os .path .join (os .path .dirname (__file__ ), ' tdjson.dll' )
37
+ if os .name == "nt" :
38
+ tdjson_path = os .path .join (os .path .dirname (__file__ ), " tdjson.dll" )
39
39
else :
40
- sys .exit ("Error: Can't find 'tdjson' library. Make sure it's installed correctly." )
40
+ sys .exit (
41
+ "Error: Can't find 'tdjson' library. Make sure it's installed correctly."
42
+ )
41
43
42
44
try :
43
45
self .tdjson = CDLL (tdjson_path )
@@ -70,21 +72,27 @@ def _setup_functions(self) -> None:
70
72
self .log_message_callback_type = CFUNCTYPE (None , c_int , c_char_p )
71
73
self ._td_set_log_message_callback = self .tdjson .td_set_log_message_callback
72
74
self ._td_set_log_message_callback .restype = None
73
- self ._td_set_log_message_callback .argtypes = [c_int , self .log_message_callback_type ]
75
+ self ._td_set_log_message_callback .argtypes = [
76
+ c_int ,
77
+ self .log_message_callback_type ,
78
+ ]
74
79
75
80
def _setup_logging (self , verbosity_level : int = 1 ) -> None :
76
81
"""Configure TDLib logging.
77
82
78
83
Args:
79
84
verbosity_level: 0-fatal, 1-errors, 2-warnings, 3+-debug
80
85
"""
86
+
81
87
@self .log_message_callback_type
82
88
def on_log_message_callback (verbosity_level , message ):
83
89
if verbosity_level == 0 :
84
- sys .exit (f' TDLib fatal error: { message .decode (" utf-8" ) } ' )
90
+ sys .exit (f" TDLib fatal error: { message .decode (' utf-8' ) } " )
85
91
86
92
self ._td_set_log_message_callback (2 , on_log_message_callback )
87
- self .execute ({'@type' : 'setLogVerbosityLevel' , 'new_verbosity_level' : verbosity_level })
93
+ self .execute (
94
+ {"@type" : "setLogVerbosityLevel" , "new_verbosity_level" : verbosity_level }
95
+ )
88
96
89
97
def execute (self , query : Dict [str , Any ]) -> Optional [Dict [str , Any ]]:
90
98
"""Execute a synchronous TDLib request.
@@ -95,10 +103,10 @@ def execute(self, query: Dict[str, Any]) -> Optional[Dict[str, Any]]:
95
103
Returns:
96
104
Response from TDLib or None
97
105
"""
98
- query_json = json .dumps (query ).encode (' utf-8' )
106
+ query_json = json .dumps (query ).encode (" utf-8" )
99
107
result = self ._td_execute (query_json )
100
108
if result :
101
- return json .loads (result .decode (' utf-8' ))
109
+ return json .loads (result .decode (" utf-8" ))
102
110
return None
103
111
104
112
def send (self , query : Dict [str , Any ]) -> None :
@@ -107,7 +115,7 @@ def send(self, query: Dict[str, Any]) -> None:
107
115
Args:
108
116
query: The request to send
109
117
"""
110
- query_json = json .dumps (query ).encode (' utf-8' )
118
+ query_json = json .dumps (query ).encode (" utf-8" )
111
119
self ._td_send (self .client_id , query_json )
112
120
113
121
def receive (self , timeout : float = 1.0 ) -> Optional [Dict [str , Any ]]:
@@ -121,12 +129,12 @@ def receive(self, timeout: float = 1.0) -> Optional[Dict[str, Any]]:
121
129
"""
122
130
result = self ._td_receive (timeout )
123
131
if result :
124
- return json .loads (result .decode (' utf-8' ))
132
+ return json .loads (result .decode (" utf-8" ))
125
133
return None
126
134
127
135
def login (self ) -> None :
128
136
"""Start the authentication process."""
129
- self .send ({' @type' : ' getOption' , ' name' : ' version' })
137
+ self .send ({" @type" : " getOption" , " name" : " version" })
130
138
131
139
print ("Starting Telegram authentication flow..." )
132
140
print ("Press Ctrl+C to cancel at any time." )
@@ -145,70 +153,102 @@ def _handle_authentication(self) -> None:
145
153
continue
146
154
147
155
# Print all updates for debugging
148
- if event .get ('@type' ) != 'updateAuthorizationState' :
156
+ event_type = event ["@type" ]
157
+ if event_type != "updateAuthorizationState" :
149
158
print (f"Receive: { json .dumps (event , indent = 2 )} " )
150
159
151
160
# Process authorization states
152
- if event . get ( '@type' ) == ' updateAuthorizationState' :
153
- auth_state = event [' authorization_state' ]
154
- auth_type = auth_state . get ( ' @type' )
161
+ if event_type == " updateAuthorizationState" :
162
+ auth_state = event [" authorization_state" ]
163
+ auth_type = auth_state [ " @type" ]
155
164
156
- if auth_type == ' authorizationStateClosed' :
165
+ if auth_type == " authorizationStateClosed" :
157
166
print ("Authorization state closed." )
158
167
break
159
168
160
- elif auth_type == ' authorizationStateWaitTdlibParameters' :
169
+ elif auth_type == " authorizationStateWaitTdlibParameters" :
161
170
if not self .api_id or not self .api_hash :
162
- print ("\n You MUST obtain your own api_id and api_hash at https://my.telegram.org" )
171
+ print (
172
+ "\n You MUST obtain your own api_id and api_hash at https://my.telegram.org"
173
+ )
163
174
self .api_id = int (input ("Please enter your API ID: " ))
164
175
self .api_hash = input ("Please enter your API hash: " )
165
176
166
177
print ("Setting TDLib parameters..." )
167
- self .send ({
168
- '@type' : 'setTdlibParameters' ,
169
- 'database_directory' : 'tdlib_data' ,
170
- 'use_message_database' : True ,
171
- 'use_secret_chats' : True ,
172
- 'api_id' : self .api_id ,
173
- 'api_hash' : self .api_hash ,
174
- 'system_language_code' : 'en' ,
175
- 'device_model' : 'Python TDLib Client' ,
176
- 'application_version' : '1.1' ,
177
- })
178
-
179
- elif auth_type == 'authorizationStateWaitPhoneNumber' :
180
- phone_number = input ('Please enter your phone number (international format): ' )
181
- self .send ({'@type' : 'setAuthenticationPhoneNumber' , 'phone_number' : phone_number })
182
-
183
- elif auth_type == 'authorizationStateWaitPremiumPurchase' :
178
+ self .send (
179
+ {
180
+ "@type" : "setTdlibParameters" ,
181
+ "database_directory" : "tdlib_data" ,
182
+ "use_message_database" : True ,
183
+ "use_secret_chats" : True ,
184
+ "api_id" : self .api_id ,
185
+ "api_hash" : self .api_hash ,
186
+ "system_language_code" : "en" ,
187
+ "device_model" : "Python TDLib Client" ,
188
+ "application_version" : "1.1" ,
189
+ }
190
+ )
191
+
192
+ elif auth_type == "authorizationStateWaitPhoneNumber" :
193
+ phone_number = input (
194
+ "Please enter your phone number (international format): "
195
+ )
196
+ self .send (
197
+ {
198
+ "@type" : "setAuthenticationPhoneNumber" ,
199
+ "phone_number" : phone_number ,
200
+ }
201
+ )
202
+
203
+ elif auth_type == "authorizationStateWaitPremiumPurchase" :
184
204
print ("Telegram Premium subscription is required." )
185
205
return
186
206
187
- elif auth_type == 'authorizationStateWaitEmailAddress' :
188
- email_address = input ('Please enter your email address: ' )
189
- self .send ({'@type' : 'setAuthenticationEmailAddress' , 'email_address' : email_address })
190
-
191
- elif auth_type == 'authorizationStateWaitEmailCode' :
192
- code = input ('Please enter the email authentication code you received: ' )
193
- self .send ({
194
- '@type' : 'checkAuthenticationEmailCode' ,
195
- 'code' : {'@type' : 'emailAddressAuthenticationCode' , 'code' : code }
196
- })
197
-
198
- elif auth_type == 'authorizationStateWaitCode' :
199
- code = input ('Please enter the authentication code you received: ' )
200
- self .send ({'@type' : 'checkAuthenticationCode' , 'code' : code })
201
-
202
- elif auth_type == 'authorizationStateWaitRegistration' :
203
- first_name = input ('Please enter your first name: ' )
204
- last_name = input ('Please enter your last name: ' )
205
- self .send ({'@type' : 'registerUser' , 'first_name' : first_name , 'last_name' : last_name })
206
-
207
- elif auth_type == 'authorizationStateWaitPassword' :
208
- password = input ('Please enter your password: ' )
209
- self .send ({'@type' : 'checkAuthenticationPassword' , 'password' : password })
210
-
211
- elif auth_type == 'authorizationStateReady' :
207
+ elif auth_type == "authorizationStateWaitEmailAddress" :
208
+ email_address = input ("Please enter your email address: " )
209
+ self .send (
210
+ {
211
+ "@type" : "setAuthenticationEmailAddress" ,
212
+ "email_address" : email_address ,
213
+ }
214
+ )
215
+
216
+ elif auth_type == "authorizationStateWaitEmailCode" :
217
+ code = input (
218
+ "Please enter the email authentication code you received: "
219
+ )
220
+ self .send (
221
+ {
222
+ "@type" : "checkAuthenticationEmailCode" ,
223
+ "code" : {
224
+ "@type" : "emailAddressAuthenticationCode" ,
225
+ "code" : code ,
226
+ },
227
+ }
228
+ )
229
+
230
+ elif auth_type == "authorizationStateWaitCode" :
231
+ code = input ("Please enter the authentication code you received: " )
232
+ self .send ({"@type" : "checkAuthenticationCode" , "code" : code })
233
+
234
+ elif auth_type == "authorizationStateWaitRegistration" :
235
+ first_name = input ("Please enter your first name: " )
236
+ last_name = input ("Please enter your last name: " )
237
+ self .send (
238
+ {
239
+ "@type" : "registerUser" ,
240
+ "first_name" : first_name ,
241
+ "last_name" : last_name ,
242
+ }
243
+ )
244
+
245
+ elif auth_type == "authorizationStateWaitPassword" :
246
+ password = input ("Please enter your password: " )
247
+ self .send (
248
+ {"@type" : "checkAuthenticationPassword" , "password" : password }
249
+ )
250
+
251
+ elif auth_type == "authorizationStateReady" :
212
252
print ("Authorization complete! You are now logged in." )
213
253
return
214
254
@@ -222,10 +262,14 @@ def main():
222
262
223
263
print ("TDLib Python Client" )
224
264
print ("===================" )
225
- print ("IMPORTANT: You should obtain your own api_id and api_hash at https://my.telegram.org" )
265
+ print (
266
+ "IMPORTANT: You should obtain your own api_id and api_hash at https://my.telegram.org"
267
+ )
226
268
print (" The default values are for demonstration only.\n " )
227
269
228
- use_default = input ("Use default API credentials for testing? (y/n): " ).lower () == 'y'
270
+ use_default = (
271
+ input ("Use default API credentials for testing? (y/n): " ).lower () == "y"
272
+ )
229
273
230
274
if use_default :
231
275
client = TdExample (DEFAULT_API_ID , DEFAULT_API_HASH )
@@ -234,10 +278,12 @@ def main():
234
278
235
279
# Test execute method
236
280
print ("\n Testing TDLib execute method..." )
237
- result = client .execute ({
238
- '@type' : 'getTextEntities' ,
239
- 'text' : '@telegram /test_command https://telegram.org telegram.me'
240
- })
281
+ result = client .execute (
282
+ {
283
+ "@type" : "getTextEntities" ,
284
+ "text" : "@telegram /test_command https://telegram.org telegram.me" ,
285
+ }
286
+ )
241
287
print (f"Text entities: { json .dumps (result , indent = 2 )} " )
242
288
243
289
# Start login process
0 commit comments